Benachrichtigungssymbol mit dem neuen Firebase Cloud Messaging-System

132

Gestern hat Google bei Google I / O das neue Benachrichtigungssystem vorgestellt, das auf der neuen Firebase basiert. Ich habe dieses neue FCM (Firebase Cloud Messaging) mit dem Beispiel auf Github ausprobiert.

Das Symbol der Benachrichtigung ist immer der ic_launcher, obwohl ich ein bestimmtes Drawable deklariert habe

Warum ? Hier unten der offizielle Code für die Bearbeitung der Nachricht

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
quelle
firebase hat nichts damit zu tun, wie SIE die Benachrichtigung erstellen. Bitte geben Sie ein Bild darüber an, was Sie sehen
tyczj
1
genau. Dieser Code stammt direkt aus Firebase und die sendNotification () -Methode ist für jede Benachrichtigung genau gleich. Dieser Code funktioniert gut mit GCM, aber mit FCM-Nr. es bleibt immer ic_launcher und verwendet die neue Weboberfläche zum Senden von Nachrichten
marco
Sie setzen das kleine Symbol, aber nicht das große Symbol, es sei denn, Sie senden einen Push mit dem Benachrichtigungs-Tag in der Push-Nutzlast, es hat nichts mit FCM zu tun
tyczj
Wird Ihr benutzerdefiniertes Benachrichtigungssymbol angezeigt, wenn sich die App im Vordergrund befindet? Das ist für mich in Ordnung. Wenn sich die App jedoch im Hintergrund befindet, muss eine Art Standard-FCM-Handler verwendet werden, da alle Benachrichtigungseinstellungen ignoriert werden (Symbol, Ton, Licht, Vibration usw. können nicht angepasst werden).
Shinypenguin

Antworten:

266

Leider war dies eine Einschränkung der Firebase-Benachrichtigungen in SDK 9.0.0-9.6.1. Wenn sich die App im Hintergrund befindet, wird das Startsymbol aus dem Manifest (mit der erforderlichen Android-Tönung) für Nachrichten verwendet, die von der Konsole gesendet werden.

Mit SDK 9.8.0 können Sie jedoch die Standardeinstellung überschreiben! In Ihrer AndroidManifest.xml können Sie die folgenden Felder festlegen, um das Symbol und die Farbe anzupassen:

<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" />

Beachten Sie, dass Sie die Anzeige vollständig mit Ihrer eigenen Logik anpassen können, wenn sich die App im Vordergrund befindet (oder eine Datennachricht gesendet wird). Sie können das Symbol auch jederzeit anpassen, wenn Sie die Nachricht über die HTTP / XMPP-APIs senden.

Ian Barber
quelle
1
@ Ian Barber: Gibt es bei Google Pläne, dieses Verhalten in naher Zukunft zu ändern?
Skylve
1
Das Team ist sich des Problems bewusst und arbeitet an einer Lösung.
Arthur Thompson
1
Gibt es hierzu Neuigkeiten? Ich dachte, ich würde fragen, weil es Umstände gab, in denen ein Google-Ingenieur einfach vergessen hat, den Patch zu pushen.
CQM
7
Ah, ich habe es mit 9.8.0 zum Laufen gebracht. Denken Sie daran, dass Ihr Statusleistensymbol den Anforderungen entsprechen muss, um anderen zu helfen: developer.android.com/guide/practices/ui_guidelines/… . Meins hat dies nicht getan und daher verwendet Firebase standardmäßig nur das Standard-Whitesquare, anstatt das im Manifest angegebene Symbol zu verwenden.
Zaifrun
3
Wenn Sie dies versuchen und feststellen, dass das Symbol kleiner als andere Benachrichtigungen ist, stellen Sie sicher, dass Sie einen Vektor zum Zeichnen verwenden (und kein PNG). Das hat es für mich gelöst.
Riper
35

Verwenden Sie eine Serverimplementierung, um Nachrichten an Ihren Client zu senden, und verwenden Sie den Datentyp von Nachrichten anstelle des Benachrichtigungstyps von Nachrichten.

Auf diese Weise erhalten Sie einen Rückruf, onMessageReceivedunabhängig davon, ob sich Ihre App im Hintergrund oder im Vordergrund befindet, und können dann Ihre benutzerdefinierte Benachrichtigung generieren

Geekoraul
quelle
2
Dies ist auch die vorgeschlagene Lösung in den Firebase-Dokumenten. Sie können die Benachrichtigung nach Belieben anzeigen, wenn Sie sich auf den Daten-Push anstelle der Benachrichtigung verlassen.
Rennen
1
Ja zustimmen. Dies sollte als richtige Antwort markiert werden. oder meine Antwort unten :)
Developine
3
Nein, es ist nicht machbar für Personen, die die Kompatibilität mit anderen Clients / Legacy-Versionen aufrechterhalten müssen, die eine Benachrichtigung erwarten.
Gabor
Wir haben Apps in der Produktion, die bereits einen Push-Benachrichtigungstyp erwarten, und wir haben diese (komplexe) Backend-Komponente erweitert, um Daten für neue Kunden hinzuzufügen. Die Unterstützung für ältere Versionen unserer App kann jedoch nicht entfernt werden.
Gabor
Oh, ich stimme zu. Das ist ein weiteres Problem. Ich würde empfehlen, die Dokumente vor der Integration gründlich zu lesen. Auch vor der Freigabe zur Produktion gründlich zu testen. Das Problem hätte vermieden werden können, wenn die App lange vor dem Start getestet worden wäre. Wie auch immer, du hattest etwas zu lernen.
Geekoraul
9

atm sie arbeiten an diesem Problem https://github.com/firebase/quickstart-android/issues/4

Wenn Sie eine Benachrichtigung über die Firebase-Konsole senden, wird standardmäßig Ihr App-Symbol verwendet, und das Android-System wird dieses Symbol in der Benachrichtigungsleiste durchgehend weiß färben.

Wenn Sie mit diesem Ergebnis nicht zufrieden sind, sollten Sie FirebaseMessagingService implementieren und die Benachrichtigungen manuell erstellen, wenn Sie eine Nachricht erhalten. Wir arbeiten an einem Weg, dies zu verbessern, aber im Moment ist dies der einzige Weg.

Bearbeiten: Mit SDK 9.8.0 zu AndroidManifest.xml hinzufügen

<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/my_favorite_pic"/>
Jan Hartwig
quelle
Wie man eine benutzerdefinierte Symbolbenachrichtigungsleiste in Marshmallow
Harsha
6

Meine Lösung ähnelt der von ATom, ist jedoch einfacher zu implementieren. Sie müssen keine Klasse erstellen, die FirebaseMessagingService vollständig beschattet. Sie können lediglich die Methode überschreiben, die die Absicht empfängt (die zumindest in Version 9.6.1 öffentlich ist), und die anzuzeigenden Informationen aus den Extras übernehmen. Der "hackige" Teil ist, dass der Methodenname tatsächlich verschleiert ist und sich jedes Mal ändert, wenn Sie das Firebase-SDK auf eine neue Version aktualisieren. Sie können ihn jedoch schnell nachschlagen, indem Sie FirebaseMessagingService mit Android Studio überprüfen und nach einer öffentlichen Methode suchen, die dies erfordert eine Absicht als einziger Parameter. In Version 9.6.1 heißt es zzm. So sieht mein Service aus:

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
quelle
gcm.notification.title für Schlüsselnamen ist für alle Versionen 100% sicher?
Pedroooo
3

Setzen Sie einfach targetSdkVersion auf 19. Das Benachrichtigungssymbol wird farbig angezeigt. Warten Sie dann, bis Firebase dieses Problem behoben hat.

Rattisuk
quelle
7
: D Wow, wo ist die Liste der Nebenwirkungen?
Eugen Pechanec
@ EugenPechanec Ja, der Nachteil ist, dass Sie möglicherweise nicht in der Lage sind, eine API zu verwenden, die am 20+ verfügbar ist
benleung
3

Es gibt auch einen hässlichen, aber funktionierenden Weg. Dekompilieren Sie FirebaseMessagingService.class und ändern Sie das Verhalten. Dann setzen Sie die Klasse einfach in das richtige Paket in Ihrer App und verwenden Sie sie dex anstelle der Klasse in der Messaging-Bibliothek. Es ist ganz einfach und funktioniert.

Es gibt Methode:

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));
}

Dieser Code stammt aus Version 9.4.0. Die Methode hat aufgrund der Verschleierung unterschiedliche Namen in unterschiedlichen Versionen.

Atom
quelle
3

Wenn sich Ihre App im Hintergrund befindet, wird das Benachrichtigungssymbol auf der Nachrichtenempfangsmethode festgelegt. Wenn sich Ihre App jedoch im Vordergrund befindet, ist das Benachrichtigungssymbol dasjenige, das Sie im Manifest definiert haben

Geben Sie hier die Bildbeschreibung ein

Bach
quelle
2

Ich löse meine Benachrichtigungen über die FCM-Konsole und über HTTP / JSON aus ... mit demselben Ergebnis.

Ich kann mit dem Titel und der vollständigen Nachricht umgehen, aber das Symbol ist immer ein weißer Standardkreis:

Benachrichtigungs-Screenshot

Anstelle meines benutzerdefinierten Symbols im Code (setSmallIcon oder setSmallIcon) oder des Standardsymbols aus der App:

 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
quelle
1
Verstanden! Meine <service> -Tags sind aus dem <application> -Tag in AndroidManifest.xml. Hier ist die Antwort stackoverflow.com/a/37352142/6366150
Gonzalo
Funktioniert nur mit laufender Vordergrund-App ... im Hintergrund immer noch das gleiche vorherige Verhalten
Gonzalo
Wenn die App im Vordergrund dieses Kundenbenachrichtigungssymbol kommt und gut funktioniert, aber im App-Hintergrund das weiße Quadrat-Symbol erhält, helfen Sie mir bitte
Harsha
1

Schreib Dies

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

rechts unten <application.....>

Geben Sie hier die Bildbeschreibung ein

Dmarquina
quelle
0

Ich dachte, ich würde eine Antwort auf diese Frage hinzufügen, da mein Problem einfach, aber schwer zu bemerken war. Insbesondere hatte ich beim Erstellen von my ein vorhandenes Metadatenelement kopiert / eingefügt com.google.firebase.messaging.default_notification_icon, das ein android:valueTag zur Angabe seines Werts verwendete. Dies funktioniert nicht für das Benachrichtigungssymbol, und sobald ich es geändert habe, hat android:resourcealles wie erwartet funktioniert.

Charles A.
quelle
Gleiches gilt für das default_notification_colorMeta, es muss eine android:resourceEinstellung sein, android:valuedie nicht funktioniert
flochtililoch