76

Ieri Google ha presentato a Google I/O il nuovo sistema di notifica basato sul nuovo Firebase. Ho provato questo nuovo FCM (Firebase Cloud Messaging) con l'esempio su Github.Icona di notifica con il nuovo sistema Firebase Cloud Messaging

L'icona della notifica è sempre la ic_launcher nonostante ho dichiarato una specifica drawable

Perché? Di seguito il codice ufficiale per la gestione del messaggio

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

} 
+0

firebase non ha nulla a che fare con come si sta creando la notifica, si prega di fornire un'immagine come a quello che stai vedendo – tyczj

+0

esatto. questo codice proviene direttamente da Firebase e il metodo sendNotification() è esattamente lo stesso per qualsiasi notifica. Questo codice funziona correttamente con GCM, ma con FCM no. rimane sempre ic_launcher, usando la nuova interfaccia web per inviare messaggi – marco

+0

si imposta l'icona piccola ma non l'icona grande, a meno che non si stia inviando una push con il tag di notifica nel payload push che non ha nulla a che fare con FCM – tyczj

risposta

161

Purtroppo questa è stata una limitazione di Firebase notifiche in SDK 9.0.0-9.6.1. Quando l'app è in background, l'icona di avvio viene utilizzata dal manifest (con la colorazione Android necessaria) per i messaggi inviati dalla console.

Con SDK 9.8.0 tuttavia, è possibile sovrascrivere il valore predefinito! Nel vostro AndroidManifest.xml è possibile impostare i seguenti campi per personalizzare l'icona e il colore:

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

Nota che se l'applicazione è in primo piano (o un messaggio dati vengono inviati) è possibile utilizzare completamente la propria logica di personalizzare il display. È inoltre possibile personalizzare sempre l'icona se si invia il messaggio dalle API HTTP/XMPP.

+0

Grazie per il chiarimento Ian – marco

+34

Sfortunatamente questo rende la Console di notifica Firebase inutile per la produzione, a meno che l'icona del launcher non sia lusingata. –

+1

@Ian Barber: qualsiasi piano di Google per modificare questo comportamento nel prossimo futuro? – skylve

8

Insomma SOLUZIONE

Succede solo quando l'invio di messaggi attraverso la console di Firebase e non l'apis

Problema

Passaggio dal vecchio GCM alla nuova FirebaseMessagingService ho pensato che sarebbe essere buono per testare quindi ho creato messaggi utilizzando la console di Firebase e ho scoperto che quando l'app è in background la mia notifica personalizzata non funzionava e Firebase onMessageReceived non veniva chiamata quando app in backgrou ND

Soluzione

ho cercato di creare messaggi dal api e solo allora mi resi conto che la Firebase non onMessageReceived chiamato quando app in background problema si verifica solo quando si creano messaggi dal Console Firebase e non al momento della spedizione da API

+1

Hai un collegamento alla documentazione sull'invio di notifiche tramite l'API? – TALE

+0

Collegamento all'API per la pubblicazione di notifiche tramite Firebase: https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support – TALE

+1

@ kaushik-bharadwaj Hai ricevuto così tanti equivoci, guarda le risposte sopra e dimentica le tue conclusioni. – Gabor

1

Sto attivando le mie notifiche dalla console FCM e tramite HTTP/JSON ... con lo stesso risultato.

Posso gestire il titolo, messaggio completo, ma l'icona è sempre un cerchio bianco di default:

Notification screenshot

Invece di mia un'icona personalizzata nel codice (setSmallIcon o setSmallIcon) o l'icona predefinita dal 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); 
    } 
+1

Trovato! i miei tag sono in tag in AndroidManifest.xml Qui ho caldo la risposta http://stackoverflow.com/a/37352142/6366150 – Gonzalo

+0

Funziona solo con l'app in primo piano in esecuzione ... in background si ottiene sempre lo stesso comportamento precedente – Gonzalo

+1

Hai capito? – noev

7

atm che stanno lavorando su questo tema https://github.com/firebase/quickstart-android/issues/4

quando si invia una notifica dalla console Firebase viene utilizzata l'icona della propria app per impostazione predefinita e il sistema Android lo renderà bianco fisso quando si trova nella barra delle notifiche.

Se non si è soddisfatti di tale risultato, è necessario implementare FirebaseMessagingService e creare manualmente le notifiche quando si riceve un messaggio. Stiamo lavorando su un modo per migliorare questo, ma per ora è l'unico modo.

edit: con SDK 9.8.0 aggiungi a AndroidManifest.xml

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

come visualizzare vassoio di notifica icona personalizzata in marshmallow – Harsha

22

Utilizzare un'implementazione del server per inviare messaggi al vostro cliente e utilizzare dati tipo di messaggi, piuttosto che notifica tipo di messaggi.

Questo vi aiuterà a ottenere un callback per onMessageReceived a prescindere se la vostra applicazione è in background o in primo piano e si può generare la notifica personalizzato poi

+2

Questa è la soluzione suggerita nel Anche i documenti di Firebase, puoi mostrare la notifica nel modo che preferisci se ti affidi al push dei dati invece della notifica. – racs

+1

sì d'accordo. questo dovrebbe essere contrassegnato come una risposta corretta. o la mia risposta qui sotto :) –

+1

No, non è fattibile per le persone che hanno bisogno di mantenere la compatibilità con altri client/versioni precedenti che si aspettano una notifica. – Gabor

2

Basta impostare targetSdkVersion al 19 sarà colorato L'icona di notifica. Quindi attendi Firebase per risolvere questo problema.

+4

: D Wow, quindi dov'è l'elenco degli effetti collaterali? –

+0

@EugenPechanec sì, il compromesso è che potresti non essere in grado di utilizzare alcune API che sono disponibili su 20 + – benleung

3

C'è anche un modo brutto ma funzionante. Decompila FirebaseMessagingService.class e modifica il suo comportamento. Quindi inserisci la classe nel pacchetto giusto in yout e usalo invece della classe nella stessa messaggistica. È abbastanza facile e funzionante.

C'è del metodo:

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

Questo codice è a partire dalla versione 9.4.0, il metodo avrà nomi diversi in diverse versioni a causa di offuscamento.

5

La mia soluzione è simile a quella di ATOM, ma più semplice da implementare. Non è necessario creare una classe che ombreggia completamente FirebaseMessagingService, basta sovrascrivere il metodo che riceve l'Intent (che è pubblico, almeno nella versione 9.6.1) e prendere le informazioni da visualizzare dagli extra. La parte "hacky" è che il nome del metodo è effettivamente offuscato e cambierà ogni volta che si aggiorna lo sdk Firebase a una nuova versione, ma è possibile consultarlo rapidamente ispezionando FirebaseMessagingService con Android Studio e cercando un metodo pubblico che richiede un intento come unico parametro. Nella versione 9.6.1 si chiama zzm. Ecco come il mio servizio si presenta come:

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()); 
    } 
} 
+0

gcm.notification.title per il nome della chiave è sicuro al 100% per tutte le versioni? – pedroooo

+0

Grazie !! Funziona :) –

2

se la vostra applicazione è in background l'icona di notifica verrà impostata onMessage metodo di ricezione, ma se si è app in primo piano l'icona di notifica sarà quella definita sul manifesto

enter image description here

Problemi correlati