tutorial receive notification notificaciones example android push-notification firebase googleio firebase-cloud-messaging

android - receive - Icono de notificación con el nuevo sistema Firebase Cloud Messaging



push firebase android (10)

Desafortunadamente, esta fue una limitación de las notificaciones de Firebase en SDK 9.0.0-9.6.1. Cuando la aplicación está en segundo plano, el ícono del iniciador se usa desde el manifiesto (con el tinte requerido de Android) para los mensajes enviados desde la consola.

Sin embargo, con SDK 9.8.0, puede anular el valor predeterminado. En su AndroidManifest.xml puede configurar los siguientes campos para personalizar el icono y el color:

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

Tenga en cuenta que si la aplicación está en primer plano (o se envía un mensaje de datos) puede usar completamente su propia lógica para personalizar la pantalla. También siempre puede personalizar el icono si envía el mensaje desde las API HTTP / XMPP.

Ayer, Google presentó en Google I / O el nuevo sistema de notificación basado en la nueva Firebase. Probé este nuevo FCM (Firebase Cloud Messaging) con el ejemplo en Github.

El ícono de la notificación siempre es el ic_launcher a pesar de que he declarado un dibujo específico

Por qué ? Aquí debajo el código oficial para manejar el mensaje

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


Estoy activando mis notificaciones desde la consola FCM y a través de HTTP / JSON ... con el mismo resultado.

Puedo manejar el título, mensaje completo, pero el ícono siempre es un círculo blanco predeterminado:

Captura de pantalla de notificaciones

En lugar de mi icono personalizado en el código (setSmallIcon o setSmallIcon) o el icono predeterminado de la aplicación:

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


Mi solución es similar a la de ATom, pero más fácil de implementar. No necesita crear una clase que sombree completamente FirebaseMessagingService, solo puede anular el método que recibe la Intención (que es pública, al menos en la versión 9.6.1) y tomar la información que se mostrará de los extras. La parte "hacky" es que el nombre del método está realmente ofuscado y cambiará cada vez que actualice Firebase sdk a una nueva versión, pero puede buscarlo rápidamente inspeccionando FirebaseMessagingService con Android Studio y buscando un método público que requiera Una intención como único parámetro. En la versión 9.6.1 se llama zzm. Así es como se ve mi servicio:

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


Pensé que agregaría una respuesta a esta, ya que mi problema era simple pero difícil de notar. En particular, había copiado / pegado un elemento de metadatos existente al crear mi com.google.firebase.messaging.default_notification_icon , que usaba una etiqueta android:value para especificar su valor. Esto no funcionará para el ícono de notificación, y una vez que lo cambié a android:resource todo funcionó como se esperaba.


Simplemente establezca targetSdkVersion en 19. El icono de notificación se coloreará. Luego espera a que Firebase solucione este problema.


También hay una forma fea pero funcional. Descompile FirebaseMessagingService.class y modifique su comportamiento. Luego, coloque la clase en el paquete correcto en su aplicación y dex úsela en lugar de la clase en la propia biblioteca de mensajes. Es bastante fácil y funciona.

Hay un método:

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

Este código es de la versión 9.4.0, el método tendrá diferentes nombres en diferentes versiones debido a la ofuscación.


Use una implementación de servidor para enviar mensajes a su cliente y use el tipo de datos de mensajes en lugar del tipo de notificación de mensajes.

Esto lo ayudará a obtener una devolución de llamada a onMessageReceived independientemente de si su aplicación está en segundo plano o en primer plano y luego puede generar su notificación personalizada


atm están trabajando en ese tema https://github.com/firebase/quickstart-android/issues/4

cuando envía una notificación desde la consola de Firebase, usa el ícono de su aplicación de manera predeterminada, y el sistema Android activará ese ícono en color blanco cuando esté en la barra de notificaciones.

Si no está satisfecho con ese resultado, debe implementar FirebaseMessagingService y crear las notificaciones manualmente cuando reciba un mensaje. Estamos trabajando en una forma de mejorar esto, pero por ahora esa es la única manera.

editar: con SDK 9.8.0 agregar a AndroidManifest.xml

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


escribe esto

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

justo abajo <application.....>


si su aplicación está en segundo plano, el icono de notificación se establecerá en el método de recepción de mensajes, pero si su aplicación está en primer plano, el icono de notificación será el que definió en el manifiesto