Hier, Google a présenté à Google I/O le nouveau système de notification basé sur la nouvelle Firebase. J'ai essayé cette nouvelle FCM (Firebase Cloud Messaging) avec l'exemple sur Github.
L'icône de la notification est toujours l'icône ic_launcher malgré le fait que j'ai déclaré un dessin spécifique
Pourquoi ? Ci-dessous le code officiel de traitement du message
public class AppFirebaseMessagingService extends FirebaseMessagingService {
/**
* Called when message is received.
*
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
sendNotification(remoteMessage);
}
// [END receive_message]
/**
* Create and show a simple notification containing the received FCM message.
*
* @param remoteMessage FCM RemoteMessage received.
*/
private void sendNotification(RemoteMessage remoteMessage) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// this is a my insertion looking for a solution
int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop ? R.drawable.myicon: R.mipmap.myicon;
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(icon)
.setContentTitle(remoteMessage.getFrom())
.setContentText(remoteMessage.getNotification().getBody())
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
Malheureusement, il s’agissait d’une limitation des notifications Firebase dans SDK 9.0.0-9.6.1. Lorsque l'application est en arrière-plan, l'icône du lanceur est utilisée à partir du manifeste (avec la teinte appropriée Android) pour les messages envoyés à partir de la console.
Avec SDK 9.8.0, vous pouvez toutefois remplacer la valeur par défaut! Dans votre fichier AndroidManifest.xml, vous pouvez définir les champs suivants pour personnaliser l'icône et la couleur:
<meta-data
Android:name="com.google.firebase.messaging.default_notification_icon"
Android:resource="@drawable/notification_icon" />
<meta-data Android:name="com.google.firebase.messaging.default_notification_color"
Android:resource="@color/google_blue" />
Notez que si l'application est au premier plan (ou qu'un message de données est envoyé), vous pouvez entièrement utiliser votre propre logique pour personnaliser l'affichage. Vous pouvez également toujours personnaliser l'icône si vous envoyez le message à partir des API HTTP/XMPP.
Utilisez une implémentation de serveur pour envoyer des messages à votre client et utilisez data type de messages plutôt que notification type de messages.
Cela vous aidera à obtenir un rappel sur onMessageReceived
, que votre application soit en arrière-plan ou à l'avant-plan et vous pourrez alors générer votre notification personnalisée.
atm ils travaillent sur cette question https://github.com/firebase/quickstart-Android/issues/4
lorsque vous envoyez une notification à partir de la console Firebase, l’icône de votre application est utilisée par défaut. Le système Android devient blanc lorsque cette icône est affichée dans la barre de notification.
Si vous n'êtes pas satisfait de ce résultat, vous devez implémenter FirebaseMessagingService et créer les notifications manuellement lorsque vous recevez un message. Nous travaillons sur un moyen d'améliorer cela, mais pour l'instant c'est le seul moyen.
edit: avec SDK 9.8.0 ajouter à AndroidManifest.xml
<meta-data Android:name="com.google.firebase.messaging.default_notification_icon" Android:resource="@drawable/my_favorite_pic"/>
Ma solution est similaire à celle d'ATOM, mais plus facile à mettre en œuvre. Vous n'avez pas besoin de créer une classe qui occulte complètement FirebaseMessagingService, vous pouvez simplement remplacer la méthode qui reçoit l'intention (qui est publique, au moins dans la version 9.6.1) et extraire les informations à afficher des extras. La partie "hacky" est que le nom de la méthode est effectivement obscurci et va changer chaque fois que vous mettez à jour le sdk de Firebase vers une nouvelle version, mais vous pouvez le rechercher rapidement en inspectant FirebaseMessagingService avec Android Studio et en recherchant pour une méthode publique qui prend une intention comme seul paramètre. Dans la version 9.6.1, il s'appelle zzm. Voici à quoi ressemble mon service:
public class MyNotificationService extends FirebaseMessagingService {
public void onMessageReceived(RemoteMessage remoteMessage) {
// do nothing
}
@Override
public void zzm(Intent intent) {
Intent launchIntent = new Intent(this, SplashScreenActivity.class);
launchIntent.setAction(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* R equest code */, launchIntent,
PendingIntent.FLAG_ONE_SHOT);
Bitmap rawBitmap = BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(rawBitmap)
.setContentTitle(intent.getStringExtra("gcm.notification.title"))
.setContentText(intent.getStringExtra("gcm.notification.body"))
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
Il y a aussi un chemin moche mais efficace. Décompilez FirebaseMessagingService.class et modifiez son comportement. Ensuite, placez simplement la classe dans le bon paquet dans votre application et dex l’utilise au lieu de la classe dans la bibliothèque de messagerie elle-même. C'est assez facile et ça marche.
Il y a méthode:
private void zzo(Intent intent) {
Bundle bundle = intent.getExtras();
bundle.remove("Android.support.content.wakelockid");
if (zza.zzac(bundle)) { // true if msg is notification sent from FirebaseConsole
if (!zza.zzdc((Context)this)) { // true if app is on foreground
zza.zzer((Context)this).zzas(bundle); // create notification
return;
}
// parse notification data to allow use it in onMessageReceived whe app is on foreground
if (FirebaseMessagingService.zzav(bundle)) {
zzb.zzo((Context)this, intent);
}
}
this.onMessageReceived(new RemoteMessage(bundle));
}
Ce code est à partir de la version 9.4.0, la méthode aura différents noms dans différentes versions en raison de l'obscurcissement.
Il suffit de définir targetSdkVersion sur 19. L'icône de notification sera colorée. Attendez ensuite que Firebase résolve ce problème.
Je déclenche mes notifications depuis la console FCM et via HTTP/JSON ... avec le même résultat.
Je peux gérer le titre, le message complet, mais l'icône est toujours un cercle blanc par défaut:
À la place de mon icône personnalisée dans le code (setSmallIcon ou setSmallIcon) ou une icône par défaut de l'application:
Intent intent = new Intent(this, MainActivity.class);
// use System.currentTimeMillis() to have a unique ID for the pending intent
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
if (Build.VERSION.SDK_INT < 16) {
Notification n = new Notification.Builder(this)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pIntent)
.setAutoCancel(true).getNotification();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//notificationManager.notify(0, n);
notificationManager.notify(id, n);
} else {
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
Notification n = new Notification.Builder(this)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setLargeIcon(bm)
.setContentIntent(pIntent)
.setAutoCancel(true).build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//notificationManager.notify(0, n);
notificationManager.notify(id, n);
}
J'ai pensé ajouter une réponse à celle-ci, car mon problème était simple mais difficile à remarquer. En particulier, j'avais copié/collé un élément de métadonnées existant lors de la création de mon com.google.firebase.messaging.default_notification_icon
, qui utilisait une balise Android:value
pour spécifier sa valeur. Cela ne fonctionnera pas pour l'icône de notification, et une fois que je l'ai changé en Android:resource
tout a fonctionné comme prévu.