FCM - 在onMessageReceived

时间:2016-09-05 08:26:36

标签: android google-cloud-messaging firebase-cloud-messaging firebase-notifications

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

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

以下是我的代码。我在onMessageReceived内设置了数字。我已经测试了setBadge方法并且可以验证它是否正常工作。问题是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<ResolveInfo> 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;
}

当我搜索此issue时,我发现如果即将发送的消息是显示消息,那么仅当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。我应该做些不同的事情来处理数据信息吗?它是否与客户端的显示消息相同。

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

3 个答案:

答案 0 :(得分:5)

无法调用 onMessageReceived ,除非即将到来的json包含仅数据有效负载,这是我从Firebase支持中学到的。

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

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

谢谢大家。

答案 1 :(得分:3)

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

更新徽章只适用于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.
    }

}

答案 2 :(得分:1)

enter image description here

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

了解更多信息,请点击here