Je ne peux pas changer ce sentiment: encore une fois, les développeurs Android ont proposé quelque chose de nouveau et ont laissé tout le monde dans le noir quant à la manière dont ils penseraient que la fonctionnalité est utilisée.
Je parle de canaux de notification dans Android O.
Pendant des années, j'ai utilisé les bibliothèques de support de compatibilité pour éviter de traiter avec des détails spécifiques de la plate-forme. À savoir: NotificationCompat
.
Maintenant, la Builder
nécessite que je fournisse un identifiant de canal de notification, ce qui est Nice, mais me laisse complètement seul avec la création d'un tel canal. Je ne trouve aucun support pour la création de chaînes. Je ne peux pas non plus trouver un moyen raisonnable de les créer au bon moment.
Les documents indiquent simplement que cela doit être fait "quelque part" et "probablement pas lors de la notification". Mais qu'est-ce que je suis supposé faire exactement? Je déteste écrire des choses spécifiques à la version pour des tâches simples - c'est pourquoi j'utilise les bibliothèques compat.
Quelqu'un a-t-il une suggestion sur la façon de le gérer? Est-il "coûteux" de créer chaque fois que je souhaite afficher une notification?
Voici ma solution pour générer des notifications sur Android O et maintenir la compatibilité descendante:
String idChannel = "my_channel_01";
Intent mainIntent;
mainIntent = new Intent(context, LauncherActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, mainIntent, 0);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel mChannel = null;
// The id of the channel.
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, null);
builder.setContentTitle(context.getString(R.string.app_name))
.setSmallIcon(getNotificationIcon())
.setContentIntent(pendingIntent)
.setContentText(context.getString(R.string.alarm_notification) + ManagementDate.getIstance().hourFormat.format(getAlarm(context, 0)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mChannel = new NotificationChannel(idChannel, context.getString(R.string.app_name), importance);
// Configure the notification channel.
mChannel.setDescription(context.getString(R.string.alarm_notification));
mChannel.enableLights(true);
mChannel.setLightColor(Color.RED);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
mNotificationManager.createNotificationChannel(mChannel);
} else {
builder.setContentTitle(context.getString(R.string.app_name))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setColor(ContextCompat.getColor(context, R.color.transparent))
.setVibrate(new long[]{100, 250})
.setLights(Color.YELLOW, 500, 5000)
.setAutoCancel(true);
}
mNotificationManager.notify(1, builder.build());
Voici une solution alternative qui utilise reflect pour créer le canal de notification afin que vous puissiez définir une compileSdkVersion
inférieure à 26.
private void createNotificationChannel(NotificationManager notificationManager) {
// Channel details
String channelId = "myChannelId";
String channelName = "Notifications";
// Channel importance (3 means default importance)
int channelImportance = 3;
try {
// Get NotificationChannel class via reflection (only available on devices running Android O or newer)
Class notificationChannelClass = Class.forName("Android.app.NotificationChannel");
// Get NotificationChannel constructor
Constructor<?> notificationChannelConstructor = notificationChannelClass.getDeclaredConstructor(String.class, CharSequence.class, int.class);
// Instantiate new notification channel
Object notificationChannel = notificationChannelConstructor.newInstance(channelId, channelName, channelImportance);
// Get notification channel creation method via reflection
Method createNotificationChannelMethod = notificationManager.getClass().getDeclaredMethod("createNotificationChannel", notificationChannelClass);
// Invoke method on NotificationManager, passing in the channel object
createNotificationChannelMethod.invoke(notificationManager, notificationChannel);
// Log success to console
Log.d("MyApp", "Notification channel created successfully");
}
catch (Exception exc) {
// Log exception to console
Log.e("MyApp", "Creating notification channel failed", exc);
}
}
Ensuite, lorsque vous créez vos notifications, appelez simplement la méthode .setChannelId()
de NotificationCompat.Builder
:
builder.setChannelId("myChannelId");
Remarque: Vous devez mettre à jour votre bibliothèque appcompat-v7
vers la version 26.x.x
dans build.gradle
:
compile 'com.Android.support:appcompat-v7:26.1.0'
Ce n'est pas aussi cher que vous le pensez! Tout ce que vous avez à faire est de créer un canal de notification et de le lier à la notification.
Vous pouvez résoudre ce problème de deux manières, mais pour les deux, vous devez créer un canal de notification avec un identifiant de canal spécifique.
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String id = "my_channel_01";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(id, name,importance);
mChannel.enableLights(true);
mNotificationManager.createNotificationChannel(mChannel);
La première méthode consiste à définir le canal de notification dans le constructeur:
Notification notification = new Notification.Builder(MainActivity.this , id).setContentTitle("Title");
mNotificationManager.notify("your_notification_id", notification);
La deuxième façon consiste à définir le canal par Notificiation.Builder.setChannelId ()
Notification notification = new Notification.Builder(MainActivity.this).setContentTitle("Title").
setChannelId(id);
mNotificationManager.notify("your_notification_id", notification);
J'espère que cela t'aides
Si votre code de notification a toujours la même structure, vous devez donc créer une méthode statique et pass tout ce que vous voulez et mettre le code qui vérifie le API Level à l'intérieur de cette méthode.
Si vous souhaitez prendre en charge les versions précédentes d'Android (<Oreo). Nous pouvons envelopper la NotificationManager
pour créer et construire l'instance Notification.Builder
dans une NotificationHelper
comme ceci:
/**
* Helper class to manage notification channels, and create notifications.
* <p>
* Created by teocci.
*
* @author [email protected] on 2018-Oct-02
*/
public class NotificationHelper extends ContextWrapper
{
public static final String NOTIFICATION_CHANNEL_PRIMARY = "notification_channel_primary";
public static final int NOTIFICATION_ID_PRIMARY = 1100;
private NotificationManager manager;
/**
* Registers notification channels, which can be used later by individual notifications.
*
* @param ctx The application context
*/
public NotificationHelper(Context ctx)
{
super(ctx);
// For API 26+ create notification channels
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_PRIMARY,
getString(R.string.channel_name),
NotificationManager.IMPORTANCE_DEFAULT
);
channel.setLightColor(Color.BLUE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.setDescription(getString(R.string.channel_description));
getManager().createNotificationChannel(channel);
}
}
/**
* Cancel a previously shown notification. If it's transient, the view
* will be hidden. If it's persistent, it will be removed from the status
* bar.
*
* @param id The ID of the notification
*/
public void remove(int id){
manager.cancel(id);
}
/**
* Get a notification of type 1
* <p>
* Provide the builder rather than the notification it's self as useful for making notification
* changes.
*
* @return the builder as it keeps a reference to the notification (since API 24)
*/
public Notification getNotification()
{
return getNotification(getTitle(), getBody()).build();
}
/**
* Get a notification of type 1
* <p>
* Provide the builder rather than the notification it's self as useful for making notification
* changes.
*
* @param title the title of the notification
* @param body the body text for the notification
* @return the builder as it keeps a reference to the notification (since API 24)
*/
public Notification.Builder getNotification(String title, String body)
{
Notification.Builder builder = new Notification.Builder(getApplicationContext())
.setOngoing(true) // Persistent notification!
.setAutoCancel(true)
.setTicker(title)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(getSmallIcon());
// Set the Channel ID for Android O.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_CHANNEL_PRIMARY); // Channel ID
}
return builder;
}
/**
* Send a notification.
*
* @param id The ID of the notification
* @param notification The notification object
*/
public void notify(int id, Notification.Builder notification)
{
getManager().notify(id, notification.build());
}
/**
* Get the notification manager.
* <p>
* Utility method as this helper works with it a lot.
*
* @return The system service NotificationManager
*/
private NotificationManager getManager()
{
if (manager == null) {
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
return manager;
}
/**
* Get the small icon for this app
*
* @return The small icon resource id
*/
private int getSmallIcon()
{
return R.drawable.ic_smart_audio_noti_icon;
}
/**
* Get the notification title for this app
*
* @return The notification title as string
*/
private String getTitle()
{
return getString(R.string.notification_title);
}
/**
* Get the notification content for this app
*
* @return The notification content as string
*/
private String getBody()
{
return getString(R.string.notification_content);
}
}
Ensuite, nous pouvons l'utiliser facilement comme ceci:
@Override
public void onCreate()
{
...
notificationHelper = new NotificationHelper(this);
notificationHelper.notify(NotificationHelper.NOTIFICATION_ID_PRIMARY, "App is running");
...
}
@Override
public void onDestroy()
{
notificationHelper.remove(NotificationHelper.NOTIFICATION_ID_PRIMARY)
}
Le code ci-dessous fonctionne bien de mon côté, j'espère que cela vous aidera
private void sendNotification(Context ctx, String title, int notificationNumber, String message, String subtext, Intent intent) {
try {
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, notificationNumber, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Uri url = your sound file from raw;
NotificationCompat.Builder notificationBuilder = null;
try {
if (Build.VERSION.SDK_INT >= 26) {
try{
NotificationManager notificationManager = (NotificationManager)getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.deleteNotificationChannel(CHANNEL_ID_1);
notificationManager.deleteNotificationChannel(CHANNEL_ID_2);
if(!intent.getStringExtra("type").equalsIgnoreCase(""+TYPE_RIDE_REQUEST)){
NotificationChannel breaking = new NotificationChannel(CHANNEL_ID_1, CHANNEL_ID_1_NAME, NotificationManager.IMPORTANCE_HIGH);
breaking.setShowBadge(false);
breaking.enableLights(true);
breaking.enableVibration(true);
breaking.setLightColor(Color.WHITE);
breaking.setVibrationPattern(new long[]{100, 200, 100, 200, 100, 200, 100});
breaking.setSound(url,new AudioAttributes.Builder().build());
notificationBuilder = new NotificationCompat.Builder(this,CHANNEL_ID_1)
.setSmallIcon(R.mipmap.ic_launcher);
notificationManager.createNotificationChannel(breaking);
}else{
NotificationChannel politics = new NotificationChannel(CHANNEL_ID_2,CHANNEL_ID_2_NAME, NotificationManager.IMPORTANCE_DEFAULT);
politics.setShowBadge(false);
politics.enableLights(true);
politics.enableVibration(true);
politics.setLightColor(Color.BLUE);
politics.setVibrationPattern(new long[]{100, 200, 100, 200, 100});
politics.setSound(url,new AudioAttributes.Builder().build());
notificationBuilder = new NotificationCompat.Builder(this,CHANNEL_ID_2)
.setSmallIcon(R.mipmap.ic_launcher);
notificationManager.createNotificationChannel(politics);
}
}catch (Exception e){
e.printStackTrace();
}
} else {
notificationBuilder = new NotificationCompat.Builder(ctx)
.setSmallIcon(R.mipmap.ic_launcher);
}
} catch (Exception e) {
e.printStackTrace();
}
if (notificationBuilder == null) {
notificationBuilder = new NotificationCompat.Builder(ctx)
.setSmallIcon(R.mipmap.ic_launcher);
}
notificationBuilder.setContentTitle(title);
notificationBuilder.setSubText(subtext);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setContentIntent(pendingIntent);
notificationBuilder.setNumber(notificationNumber);
NotificationManager notificationManager =
(NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationNumber, notificationBuilder.build());
} catch (Exception e) {
e.printStackTrace();
}
}