Search code examples
androidandroid-push-notificationfcmp

When app is in background or killed FCM onMessageReceived() not called


When app is in background or killed onRecive onMessageReceived() not called and i get just json in notification. below is my Service class

public class AppFireBaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMsgService";


    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "From: " + remoteMessage.getFrom());

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
        }
        // Check if message contains a data payload.
        else if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
            sendNotification(remoteMessage.getData().get("title"), remoteMessage.getData().get("body"));
        }


    }




    @Override
    public void onNewToken(String token) {
        Log.d(TAG, "Refreshed token: " + token);
        PreferenceHelper preferenceHelper = new PreferenceHelper(this);
        preferenceHelper.putString(Constants.FCM_TOKEN, token);

    }




    public void sendNotification(String title, String messageBody) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Notification notification = mapper.readValue(messageBody, Notification.class);
            Intent intent = null;
            if (notification.getPostType().equalsIgnoreCase("message")) {
                intent = new Intent(this, MessageActivity.class);
                intent.putExtra(Constants.LOGIN_ID, notification.getLoginIdEnc());
            } else {
                intent = new Intent(this, HomeActivity.class);
            }

            Toast.makeText(this, notification.toString(), Toast.LENGTH_SHORT).show();

            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                    PendingIntent.FLAG_ONE_SHOT);


            String channelId = getString(R.string.default_notification_channel_id);
            Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            NotificationCompat.Builder notificationBuilder =
                    new NotificationCompat.Builder(this, channelId)
                            .setSmallIcon(R.mipmap.ic_launcher)
                            .setContentTitle(title)
                            .setContentText(notification.getMessage())
                            .setAutoCancel(true)
                            .setSound(defaultSoundUri)
                            .setContentIntent(pendingIntent);

            NotificationManager notificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            // Since android Oreo notification channel is needed.
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel channel = new NotificationChannel(channelId,
                        "Channel human readable title",
                        NotificationManager.IMPORTANCE_DEFAULT);
                notificationManager.createNotificationChannel(channel);
            }

            notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());

        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
        }


    }
}

i tried debugging it and also logs are not printed. if app is opened and running a get the correct notification and notification is build properly. when i tried with app background notification message sets the json response.


Solution

  • If the push notification has a notification part in the payload and your app is in the background, onMessageReceived will never be called. The notification is automatically created and displayed by firebase. There is no way to intercept this and modify the notification or do any other operation for that matter. Your app will only get control once the notification is clicked.

    The only way to ensure that onMessageReceived is called in all situations(foreground, background and app killed) is to send a data-only payload from firebase.

    Please check my answer to a similar question for more details.