Android FCM-在onMessageReceived中设置徽章

Android FCM-在onMessageReceived中设置徽章,android,google-cloud-messaging,firebase-cloud-messaging,firebase-notifications,Android,Google Cloud Messaging,Firebase Cloud Messaging,Firebase Notifications,我有一个Android应用程序,我用一些方法在应用程序图标上显示通知号。现在我想在收到通知时设置这个数字 我想我应该在收到通知时设置号码,所以我在onMessageReceived方法中设置它。但是,我的问题是当我的应用程序在后台时,onMessageReceived方法没有调用,因此通知号码没有设置。 下面是我的代码。我在messagereceived的中设置了数字。我已经测试了setBadge方法,可以验证它是否有效。问题是未调用onMessageReceived,因此也未调用setBadg

我有一个Android应用程序,我用一些方法在应用程序图标上显示通知号。现在我想在收到通知时设置这个数字

我想我应该在收到通知时设置号码,所以我在
onMessageReceived
方法中设置它。但是,我的问题是当我的应用程序在后台时,
onMessageReceived
方法没有调用,因此通知号码没有设置。

下面是我的代码。我在messagereceived的
中设置了数字。我已经测试了
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;
}
如果我只使用数据对象,onMessageReceived会像他们说的那样被调用,但时间通知不会出现在顶部

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

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

除非即将推出的json只包含数据负载,否则无法调用MessageReceived,正如我从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());
}
@覆盖
收到消息时公共无效(RemoteMessage RemoteMessage){
//用于数据有效载荷
//检查消息是否包含数据有效负载。
如果(remoteMessage.getData().size()>0){
Log.d(标记,“消息数据有效负载:”+remoteMessage.getData());
title=remoteMessage.getData().get(“title”);
sendNotification(remoteMessage.getData().get(“正文”),标题);
badge=Integer.parseInt(remoteMessage.getData().get(“badge”));
Log.e(“通知编号”,即“:”+徽章);
setBadge(getApplicationContext(),badge);
}
//用于通知有效负载,因此我没有在此处使用
//检查消息是否包含通知负载。
if(remoteMessage.getNotification()!=null){
Log.d(标记,“消息通知正文:”+remoteMessage.getNotification().getBody());
}
//此外,如果您打算根据收到的FCM生成自己的通知
//消息,这里是应该启动的位置。请参阅下面的sendNotification方法。
}
//[结束接收消息]
私有void sendNotification(字符串messageBody,字符串title){
Intent Intent=新的Intent(这个,MainMenuActivity.class);
intent.addFlags(intent.FLAG\u ACTIVITY\u CLEAR\u TOP);
PendingEvent PendingEvent=PendingEvent.getActivity(此,通知号/*请求代码*/,意图,
悬挂式帐篷(一杆旗帜);
如果(通知编号<9){
notify_no=notify_no+1;
}否则{
通知_no=0;
}
Uri defaultSoundUri=RingtoneManager.getDefaultUri(RingtoneManager.TYPE_通知);
NotificationCompat.Builder notificationBuilder=新建NotificationCompat.Builder(此)
.setSmallIcon(R.drawable.ic_启动器_3_web)
.setContentTitle(标题)
.setContentText(messageBody)
.setAutoCancel(真)
.setSound(defaultSoundUri)
.setContentIntent(挂起内容);
通知经理通知经理=
(NotificationManager)getSystemService(上下文通知服务);
notificationManager.notify(notify_no+2/*ID of notification*/,notificationBuilder.build());
}

谢谢大家。

要在后台接收通知有效负载,只需覆盖FirebaseMessagingService中的zzE即可。方法名称可能在不同版本之间更改,只需在类中键入@Override,然后查看它对您的建议。在我的例子中,我找到了zzD和zzE,通过尝试,我注意到zzE拥有我想要的数据。zzD的附加节目中有一些wakelock的东西。zzE的返回值基本上表示是否处理了通知,因此如果返回true,操作系统将不会显示通知。我更喜欢在完成任务后返回super.zzE(intent),让操作系统处理通知

不过,更新徽章只能在ShortcutBadger支持的启动器上工作。不过,你几乎可以做任何你想做的事情

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


为什么要投否决票?你为什么不评论一下哪里出了问题?你应该提供你正在使用的代码。只是说这种情况不会有多大帮助。将您的代码发布到此处设置默认方法?>setBadge(getApplicationContext(),badge);不,不是。我使用了一些github代码。Setbadge就是其中的一部分。你能提供你所使用的Github代码的链接吗。我想我对setBadge方法感到困惑,因为我花了几个小时试图找到哪个库,却找不到任何相关的库。这似乎setBadge下的代码可以在没有任何库的情况下工作,但我猜只有三星设备=>人们说这个库很好,可以工作很多设备=>我还了解到,由于api级别26,有一种默认的设置徽章的方法@PratikNot能够找到zzE(),这适用于firebase 10.2.1,在更高版本中,该方法已被隐藏。尽管如此,那个旧版本仍然可以很好地工作,所以我坚持使用它,直到出现一个不同的解决方案。我真的不明白为什么他们会隐藏这一点,尽管如此,我不明白允许开发人员覆盖通知的显示方式会有什么危害。。。
@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());
}
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.
    }

}