FCM — установка значка в onMessageReceived

У меня есть приложение для 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;
}

Когда я искал эту проблему, Я обнаружил, что если приходящее сообщение отображать сообщение, то 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 не вызывается, если сообщение также является сообщением данных. Должен ли я сделать что-то другое для обработки сообщения данных? Работает ли он так же с отображением сообщений на стороне клиента.

Любая помощь будет оценена по достоинству. Заранее спасибо.


comment
Зачем минусовать? Почему бы вам не прокомментировать, что не так?   -  person Hilal    schedule 05.09.2016
comment
Вы должны предоставить коды, которые вы используете. Просто сказать сценарий мало поможет. stackoverflow.com/help/mcve   -  person AL.    schedule 05.09.2016
comment
Разместите свой код здесь   -  person Burhanuddin Rashid    schedule 05.09.2016


Ответы (2)


Невозможно вызвать 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());
}

Спасибо за все.

person Hilal    schedule 09.09.2016
comment
метод setBadge по умолчанию? › setBadge(getApplicationContext(), badge); - person Pratik; 26.07.2017
comment
Нет это не так. Я использовал некоторые коды github. Setbadge является частью этого. - person Hilal; 26.07.2017
comment
Не могли бы вы предоставить ссылку на код Github, который вы использовали - person Krishna; 16.11.2018
comment
Хорошо, извините за мой предыдущий комментарий. Я думаю, что меня смутил метод setBadge, потому что я часами пытаюсь найти библиотеку и не могу найти связанную библиотеку. Кажется, что эти коды в setBadge могут работать без какой-либо библиотеки, но я думаю, только для устройств Samsung => /a> Люди говорят, что эта библиотека хороша и работает на многих устройствах=› github.com/leolin310148/ShortcutBadger Также я узнал, что начиная с уровня API 26 существует метод установки значков по умолчанию. developer.android.com/training/notify-user/badges#java @Пратик - person Hilal; 17.11.2018

Чтобы что-то делать при получении уведомлений в фоновом режиме, просто переопределите zzE в FirebaseMessagingService. Имя метода может меняться между версиями, просто введите @Override в класс и посмотрите, что он предложит вам. В моем случае я нашел zzD и zzE, и, попробовав их, я заметил, что zzE содержит нужные мне данные. У zzD в дополнениях были кое-какие штучки с вейклоками. Возвращаемое значение zzE в основном указывает, было ли обработано уведомление, поэтому, если вы вернете true, ОС не покажет уведомление. Я предпочитаю возвращать super.zzE(intent) после того, как я сделал свои дела, чтобы ОС обработала уведомление.

Однако обновление значка будет работать только на лаунчерах, поддерживаемых ShortcutBadger. Однако вместо этого вы можете делать практически все, что захотите.

Вот мой код (мои уведомления содержат «значок» в полезной нагрузке данных):

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.
    }

}
person Pauli Kettunen    schedule 31.03.2017
comment
Не удалось найти zzE() - person Mehta; 09.05.2018
comment
Это работает с firebase 10.2.1, в более поздних версиях этот метод был скрыт. Эта старая версия по-прежнему работает хорошо, поэтому я придерживаюсь ее, пока не появится другое решение. Я действительно не понимаю, почему они должны скрывать это, хотя я не вижу, какой вред может причинить разработчикам возможность переопределять способ отображения уведомлений... - person Pauli Kettunen; 16.05.2018