Icône de notification avec le nouveau système Firebase Cloud Messaging

132

Hier, Google a présenté à Google I / O le nouveau système de notification basé sur le nouveau Firebase. J'ai essayé ce nouveau FCM (Firebase Cloud Messaging) avec l'exemple sur Github.

L'icône de la notification est toujours le ic_launcher même si 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());
    }

}
marco
la source
firebase n'a rien à voir avec la façon dont VOUS créez la notification, veuillez fournir une image de ce que vous voyez
tyczj
1
exact. ce code vient directement de Firebase et la méthode sendNotification () est exactement la même pour toute notification. Ce code fonctionne bien avec GCM, mais avec FCM no. il reste toujours ic_launcher, utilisant la nouvelle interface web pour envoyer des messages
marco
vous définissez la petite icône mais pas la grande icône, sauf si vous envoyez un push avec la balise de notification dans la charge utile push, cela n'a rien à voir avec FCM
tyczj
Affiche-t-elle votre icône de notification personnalisée lorsque l'application est au premier plan? Ça marche pour moi. Cependant, lorsque l'application est en arrière-plan, elle doit utiliser une sorte de gestionnaire FCM par défaut, car tous les paramètres de notification sont ignorés (l'icône, le son, les lumières, le vibreur, etc. ne peuvent pas être personnalisés).
shinypenguin

Réponses:

267

Malheureusement, il s'agissait d'une limitation des notifications Firebase dans le 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 Android requise) pour les messages envoyés depuis la console.

Cependant, avec le SDK 9.8.0, vous pouvez remplacer la valeur par défaut! Dans votre 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 si 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.

Ian Barber
la source
1
@Ian Barber: un plan chez Google pour changer ce comportement dans un proche avenir?
skylve
1
L'équipe est consciente du problème et travaille sur un correctif.
Arthur Thompson
1
Une mise à jour pour ceci? j'ai pensé demander parce qu'il y a eu des circonstances où un ingénieur de Google a simplement oublié de pousser le correctif.
CQM
7
Ah, je l'ai fait fonctionner avec 9.8.0. Pour aider les autres, n'oubliez pas que l'icône de votre barre d'état doit répondre aux exigences: developer.android.com/guide/practices/ui_guidelines/… . Le mien ne l'a pas fait et donc Firebase utilise par défaut le carré blanc standard au lieu d'utiliser l'icône spécifiée dans le manifeste.
zaifrun
3
Si vous essayez ceci et constatez que l'icône est plus petite que les autres notifications, assurez-vous d'utiliser un dessin vectoriel (et non un png). Cela a résolu le problème pour moi.
riper
35

Utilisez une implémentation de serveur pour envoyer des messages à votre client et utilisez le type de données des messages plutôt que le type de notification des messages.

Cela vous aidera à obtenir un rappel, onMessageReceivedque votre application soit en arrière-plan ou au premier plan et vous pouvez générer votre notification personnalisée alors

geekoraul
la source
2
C'est également la solution suggérée dans la documentation Firebase, vous pouvez afficher la notification de la manière que vous préférez si vous comptez sur la transmission des données au lieu de la notification.
course
1
Oui d'accord. cela doit être marqué comme une réponse correcte. ou ma réponse ci-dessous :)
Developine
3
Non, ce n'est pas possible pour les personnes qui doivent maintenir la compatibilité avec d'autres clients / versions héritées qui attendent une notification.
Gabor
Nous avons des applications en production qui attendent déjà un type de notification push et nous avons étendu ce composant backend (complexe) pour ajouter des données pour les nouveaux clients. Mais nous ne pouvons pas supprimer la prise en charge des anciennes versions de notre application.
Gabor
Oh je suis d'accord. C'est un autre problème. Je suggère de lire attentivement la documentation avant de procéder à l'intégration. Également à tester minutieusement avant de passer à la production. Le problème aurait pu être évité si l'application avait été testée bien avant le lancement. Quoi qu'il en soit, vous aviez quelque chose à apprendre.
geekoraul
9

atm ils travaillent sur ce problème https://github.com/firebase/quickstart-android/issues/4

lorsque vous envoyez une notification à partir de la console Firebase, il utilise l'icône de votre application par défaut, et le système Android rendra cette icône en blanc fixe 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 le SDK 9.8.0 ajouter à AndroidManifest.xml

<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/my_favorite_pic"/>
Jan Hartwig
la source
comment afficher la barre de notification d'icône personnalisée dans la guimauve
Harsha
6

Ma solution est similaire à celle d'ATom, mais plus simple à 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 prendre les informations à afficher à partir 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 Firebase vers une nouvelle version, mais vous pouvez le rechercher rapidement en inspectant FirebaseMessagingService avec Android Studio et en recherchant 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());
    }
}
Carlo Conserva
la source
gcm.notification.title pour le nom de la clé est-il sûr à 100% pour toutes les versions?
pedroooo
3

Réglez simplement targetSdkVersion sur 19. L'icône de notification sera colorée. Attendez ensuite que Firebase résout ce problème.

rattisuk
la source
7
: D Wow, alors où est la liste des effets secondaires?
Eugen Pechanec le
@EugenPechanec oui, le compromis est que vous ne pourrez peut-être pas utiliser une API disponible sur 20+
benleung
3

Il y a aussi une manière moche mais efficace. Décompilez FirebaseMessagingService.class et modifiez son comportement. Ensuite, placez simplement la classe dans le bon package dans votre application et utilisez-le à la place de la classe dans la bibliothèque de messagerie elle-même. C'est assez simple et efficace.

Il existe une 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 de la version 9.4.0, la méthode aura des noms différents dans différentes versions en raison de l'obfuscation.

Atome
la source
3

si votre application est en arrière-plan, l'icône de notification sera définie sur la méthode de réception de message, mais si votre application est au premier plan, l'icône de notification sera celle que vous avez définie sur le manifeste

entrez la description de l'image ici

ruisseau
la source
2

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:

Capture d'écran de notification

Au lieu de mon icône personnalisée dans le code (setSmallIcon ou setSmallIcon) ou de l'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);
    }
Gonzalo
la source
1
Je l'ai! mes balises <service> sont en dehors de la balise <application> dans AndroidManifest.xml Ici, j'ai chaud la réponse stackoverflow.com/a/37352142/6366150
Gonzalo
Fonctionne uniquement avec l'application au premier plan en cours d'exécution ... en arrière-plan toujours le même comportement précédent
Gonzalo
lorsque l'application au premier plan cette icône de notification personnalisée arrive et fonctionne correctement, mais que l'arrière-plan de l'application obtient une icône carrée blanche, aidez-moi
Harsha
1

écrire cela

<meta-data 
         android:name="com.google.firebase.messaging.default_notification_icon"
         android:resource="@drawable/ic_notification" />

en bas <application.....>

entrez la description de l'image ici

dmarquina
la source
0

Je pensais 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éta-données existant lors de la création de my com.google.firebase.messaging.default_notification_icon, qui utilisait une android:valuebalise pour spécifier sa valeur. Cela ne fonctionnera pas pour l'icône de notification, et une fois que je l'ai changé, android:resourcetout a fonctionné comme prévu.

Charles A.
la source
Il en va de même pour la default_notification_colorméta, elle doit être un android:resource- réglage car android:valuene fonctionnera pas
flochtililoch