FCM – 在onMessageReceived中设置徽章

我有一个Android应用程序,我正在使用一些方法在应用程序图标上显示通知编号。 现在我想在收到通知时设置该号码。

我认为我应该在收到通知时设置数字,所以我在onMessageReceived方法中设置它。 但是,我的问题是当我的应用程序处于后台时,未调用onMessageReceived方法,因此未设置通知编号。

以下是我的代码。 我在onMessageReceived设置了数字。 我已经测试了setBadge方法并且可以validation它是否正常工作。 问题是onMessageReceived没有被调用,因此也没有调用setBadge ,也没有设置数字。

 @Override public void onMessageReceived(RemoteMessage remoteMessage) { // TODO(developer): Handle FCM messages here. Log.d(TAG, "From: " + remoteMessage.getFrom()); Conts.notificationCounter ++; //I am setting in here. setBadge(getApplicationContext(),Conts.notificationCounter ); Log.e("notificationNUmber",":"+ Conts.notificationCounter); // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.getData()); } // Check if message contains a notification payload. if (remoteMessage.getNotification() != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); } // 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. } // [END receive_message] public static void setBadge(Context context, int count) { String launcherClassName = getLauncherClassName(context); if (launcherClassName == null) { Log.e("classname","null"); return; } Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); intent.putExtra("badge_count", count); intent.putExtra("badge_count_package_name", context.getPackageName()); intent.putExtra("badge_count_class_name", launcherClassName); context.sendBroadcast(intent); } public static String getLauncherClassName(Context context) { PackageManager pm = context.getPackageManager(); Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); List resolveInfos = pm.queryIntentActivities(intent, 0); for (ResolveInfo resolveInfo : resolveInfos) { String pkgName = resolveInfo.activityInfo.applicationInfo.packageName; if (pkgName.equalsIgnoreCase(context.getPackageName())) { String className = resolveInfo.activityInfo.name; return className; } } return null; } 

当我搜索这个问题时 ,我发现如果即将发出的消息是显示消息,那么仅当app是前景时才调用onMessageReceived 。 但是如果即将发送消息是数据消息,则即使应用程序是后台,也会调用onMessageReceived

但我的朋友告诉我谁发送通知(服务器端),消息已经同时显示和数据消息。 他说数据对象已经填满了。

以下是即将发送消息JSON ,它具有数据对象

 { "to":"my_device_id", "priority":"high", "notification":{ "body":"Notification Body", "title":"Notification Title", "icon":"myicon", "sound":"default" }, "data":{ "Nick":"DataNick", "Room":"DataRoom" } } 

如果我只使用数据对象,则会按照他们的说法调用onMessageReceived,但该时间通知不会出现在顶部。

现在,如果消息也是数据消息,则不会调用onMessageReceived 。 我应该做些不同的事情来处理数据消息吗? 它是否与客户端的显示消息相同。

任何帮助,将不胜感激。 提前致谢。

没有办法调用onMessageReceived,除非我从Firebase支持中学到的只有 json包含数据有效负载

所以我必须使用数据有效负载,但如果您使用数据有效负载,它不会在顶部显示通知 ,因此您应该使用数据有效负载信息创建自定义通知。

因此当我在onMessageReceived中获取数据有效负载时,我向自己发送了通知 。 我在向自己发送通知后立即在onMessageReceived中设置徽章。

以下代码是最终版本。

 @Override public void onMessageReceived(RemoteMessage remoteMessage) { //for data payload // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.getData()); title = remoteMessage.getData().get("title"); sendNotification(remoteMessage.getData().get("body"), title); badge = Integer.parseInt(remoteMessage.getData().get("badge")); Log.e("notificationNUmber",":"+badge); setBadge(getApplicationContext(), badge); } //for notification payload so I did not use here // Check if message contains a notification payload. if (remoteMessage.getNotification() != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); } // 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. } // [END receive_message] private void sendNotification(String messageBody, String title) { Intent intent = new Intent(this, MainMenuActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, notify_no /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT); if (notify_no < 9) { notify_no = notify_no + 1; } else { notify_no = 0; } Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_launcher_3_web) .setContentTitle(title) .setContentText(messageBody) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(notify_no + 2 /* ID of notification */, notificationBuilder.build()); } 

谢谢大家。

要在后台接收Notification-payloads时执行操作,只需在FirebaseMessagingService中覆盖zzE即可。 方法名称可能会在不同版本之间更改,只需在类中键入@Override,然后查看它为您建议的内容。 在我的例子中,我find了zzD和zzE,通过尝试它们,我注意到zzE有我想要的数据。 zzD在其附加function中有一些唤醒锁。 zzE的返回值基本上表示通知是否已处理,因此如果返回true,操作系统将不会显示通知。 在完成我的工作后,我更喜欢返回super.zzE(intent),让操作系统处理通知。

更新徽章只适用于ShortcutBadger支持的启动器。 不过,你可以做任何你想做的事情。

这是我的代码(我的通知在数据有效负载中包含“badge”):

 public class PushNotificationService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { // This is called when the app is in the foreground // Show a custom notification or send a broadcast to update the UI here } @Override public boolean zzE(Intent intent) { if(intent.hasExtra("badge")) { try { ShortcutBadger.applyCount(getApplicationContext(), Integer.parseInt(intent.getStringExtra("badge")); } catch (Exception e) { Log.e("failedToParse", "Badge!?"); } } // pass the intent through to the non-overriden zzE // to show the default notification. return super.zzE(intent); // You could also show a custom notification here // and return true instead of this if you // don't want the default notifications. } } 

在此处输入图像描述

没有自定义启动器和触摸界面的Android不允许更改应用程序图标,因为一旦编译了程序,它就会被密封在.apk中。 没有办法使用标准API以编程方式将其更改为“drawable”。因此,以下代码仅适用于Samsung,Htc,Sony等。

欲了解更多信息,请点击此