Hilal Hilal - 2 months ago 52
Android Question

FCM - Setting badge in onMessageReceived

I have an Android application, where I'm using some method to show notification number on app icon. Now I want to set that number when notification is received.

I thought that I should set the number when notification received so I set it inside

onMessageReceived
method. But, my problem is when my app is in background,
onMessageReceived
method not called, so the notification number isn't set.


Following is my code. I set the number inside
onMessageReceived
. I already tested
setBadge
method and can verify that it is working. The problem is
onMessageReceived
is not called so
setBadge
is also not called, which doesn't set the number.

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


When I searched this issue, I found that if the coming message is display message then
onMessageReceived
is called only if app is foreground. But if coming message is data message then
onMessageReceived
is called even if the app is background.

But my friend told me who is sending the notification(server side), the message already goes as both display and data message. He said that data object is filled.

Following is the JSON for coming message, it has data object.

{
"to":"my_device_id",
"priority":"high",

"notification":{
"body":"Notification Body",
"title":"Notification Title",
"icon":"myicon",
"sound":"default"
},

"data":{
"Nick":"DataNick",
"Room":"DataRoom"
}
}


If I only use data object, onMessageReceived is called as they said but that time notification does not appear at the top.

Now why
onMessageReceived
is not called if the message is also data message. Should I do something different to handle data message? Is it working same with display messaging in client side.

Any help would be appreciated. Thanks in advance.

Answer

No way to call onMessageReceived unless the coming json includes ONLY data payload as I learned from Firebase support.

So I have to use data payload but if you use data payload it does not show notification at the top so you should create your custom notification using data payload information.

So I sent notification to myself when I get the data payload in onMessageReceived. And I set the badge in onMessageReceived right after sending notification to myself.

Following code is the final version.

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

Thanks for all.

Comments