通知图标与新的Firebase云消息传递系统

Google昨天在Google I / O上发布了基于新Firebase的新通知系统。 我用Github上的例子尝试了这个新的FCM(Firebase Cloud Messaging)。

尽pipe我已经声明了特定的drawable,但通知的图标总是ic_launcher

为什么? 这里是处理消息的官方代码

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

不幸的是,这是SDK 9.0.0-9.6.1中的Firebase通知的限制。 当应用程序在后台时,启动程序图标用于从控制台发送的消息清单(具有必要的Android着色)。

但是使用SDK 9.8.0,您可以覆盖默认值! 在您的AndroidManifest.xml中,您可以设置以下字段来自定义图标和颜色:

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

请注意,如果应用程序处于前台(或发送数据消息),则可以完全使用自己的逻辑来自定义显示。 如果从HTTP / XMPP API发送消息,您也可以始终自定义图标。

访问此链接,了解有关Android中Firebase推送通知设置的完整指南

谁说这是不可能的。 有可能的。

从官方firebase文档

“对于下游消息传递,FCM提供了两种types的有效载荷:通知和数据,对于通知types,FCM代表客户端应用自动向最终用户设备显示消息,通知有一组预定义的用户可见密钥。types,客户端应用程序负责处理数据消息,数据消息只有自定义的键值对。

所以如果你发送通知,并添加像这样发送。 myicon(任何图像)应该在应用程序可绘制的文件夹中。 Firebase将使用它来通知图标。 所以你有自定义的通知图标。

 { "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...", "notification" : { "body" : "great match!", "title" : "Portugal vs. Denmark", "icon" : "myicon", "sound" : "mySound" } } 

如果你想在客户端处理通知,你需要发送像这样的数据有效载荷。 现在firebase不会发送通知给系统,而是即使应用程序在后台也会调用MessageReceived。

 { "data": { "title": "Firebase notification", "detail": "I am firebase notification. you can customise me. enjoy", }, "to" : "efaOvIXDbik:APA91bEkNUVWNaoA...." } 

使用服务器实现将消息发送到客户端,并使用消息的数据types而不是通知types的消息。

这将帮助你callbackonMessageReceived而不pipe你的应用程序是在后台还是在前台,你可以生成你的自定义通知

在短的解决scheme

只有在通过Firebase控制台发送消息而不是apis时才会发生

问题

从旧的gcm切换到新的FirebaseMessagingService我认为这将是很好的testing,因此我使用Firebase控制台创build的消息,只发现当应用程序是背景我的自定义通知不工作,Firebase onMessageReceived不调用时,应用程序在后台

我试图从api创build消息,只有这样,我才意识到Firebase onMessageReceived不会在后台问题中的应用程序发生时才从Firebase控制台创build消息,而不是从API发送时调用

atm他们正在处理这个问题https://github.com/firebase/quickstart-android/issues/4

当您从Firebase控制台发送通知时,默认情况下会使用您的应用程序图标,Android系统会在通知栏中将该图标变为白色。

如果您对此结果不满意,则应该实施FirebaseMessagingService并在收到消息时手动创build通知。 我们正在努力改善这一点,但现在这是唯一的方法。

编辑:用SDK 9.8.0添加到AndroidManifest.xml

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

我的解决scheme类似于ATOM的解决scheme,但更容易实现。 您不需要创build一个完全隐藏FirebaseMessagingService的类,只需重写接收Intent(至less在版本9.6.1中为public)的方法,并从extras中显示信息即可。 “hacky”部分是方法名称确实被模糊处理,并且每次将Firebase sdk更新为新版本时都会更改,但您可以通过检查FireplaceMessagingService与Android Studio并查找公共方法一个意图作为唯一的参数。 在版本9.6.1中,它被称为zzm。 以下是我的服务的样子:

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

还有一个丑陋的,但工作的方式。 反编译FirebaseMessagingService.class并修改它的行为。 然后把这个类放在你的应用程序的正确的包中,dex使用它来代替消息库本身的类。 这是很容易和工作。

有方法:

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

此代码是从版本9.4.0,由于混淆,方法将在不同版本中具有不同的名称。

只需将targetSdkVersion设置为19.通知图标将被着色。 然后等待Firebase解决这个问题。

我从FCM控制台和HTTP / JSON触发我的通知…具有相同的结果。

我可以处理标题,完整的消息,但图标总是一个默认的白色圆圈:

通知屏幕截图

代码中的自定义图标(setSmallIcon或setSmallIcon)或应用程序的默认图标:

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