Push notification works incorrectly when app is on background or not running

37,174

Solution 1

With FCM you specify a POST payload to send to https://fcm.googleapis.com/fcm/send. In that payload you can specify a data or a notification key, or both.

If your payload contains only a data key, your app will handle all push messages itself. E.g. they are all delivered to your onMessageReceived handler.

If your payload contains a notification key, your app will handle push messages itself only if your app is active/in the foreground. If it is not (so it's in the background, or closed entirely), FCM handles showing the notification for you by using the values you put into the notification key payload.

Note that notifications sent from a console (like Firebase console), they always include a notification key.

Looks like you want to be handling the FCM messages yourself so you can customize the notification a bit more etc, so it would be better to not include the notification key in the POST payload, so all push messages are delivered to your onMessageReceived.

You can read more about it here:
Advanced messaging options
Downstream message syntax

Solution 2

I spent 2 weeks to understand why my application cannot receive data message anymore when it's in background and as strange as it could be, I arrived to the conclusion that Android-Studio 2.1.2 is the problem!

I cannot receive any FCM message anymore in background application

https://github.com/firebase/quickstart-android/issues/89

Share:
37,174
Ololoking
Author by

Ololoking

Updated on February 16, 2021

Comments

  • Ololoking
    Ololoking over 3 years

    I am using Firebase Cloud Messaging to send push notifications.

    Here is my FirebaseMessageService:

    public class FireBaseMessageService extends FirebaseMessagingService {
    
    
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e("TAG", "From: " + remoteMessage.getFrom());
        Log.e("TAG", "Notification Message Body: " + remoteMessage.getData().get("CardName")+"  :  "+remoteMessage.getData().get("CardCode"));
        sendNotification(remoteMessage.getNotification().getBody());
    }
    
    
    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, StartActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
    
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher_final)
                .setContentTitle("Notification")
                .setContentText(messageBody)
                .setTicker("Test")
                .setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_SOUND)
                .setContentIntent(pendingIntent);
    
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
            notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
        }
    }
    

    And FirebaseInstanceServer:

    public class FirebaseInstanceService extends FirebaseInstanceIdService {
    
    
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.e("TAG", "Refreshed token: " + refreshedToken);
    
        // TODO: Implement this method to send any registration to your app's servers.
        sendRegistrationToServer(refreshedToken);
    
    }
    
    private void sendRegistrationToServer(String token) {
    
    
          // Add custom implementation, as needed.
            Log.e("TAG", "Refreshed token2: " + token);
        }
    }
    

    Which is declared in the AndroidManifest:

    <service
        android:name=".util.notifications.FireBaseMessageService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>
    
    <service
        android:name=".util.notifications.FirebaseInstanceService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
        </intent-filter>
    </service>
    

    So issue is that when App is running ticker is shown well and notification come with default sound, but when App is in background or is not running, notification come without any sound and ticker is not shown in status bar.
    Why is this happening and how can I fix it?

  • Ololoking
    Ololoking about 8 years
    thanks, you are right, when I remove notification key I start recieve notifications correctly
  • Arthur Thompson
    Arthur Thompson about 8 years
    Tim is correct, I'd just like to add that messages sent from the Firebase console are notification messages so if you do use the Firebase console you'd have to handle them accordingly.
  • fralbo
    fralbo almost 8 years
    @tim-castelijns Are you sure data-messages are still received in background. It worked for me like that until very recently. I have a working app under FCM 9.2.0 but after the last studio, sdk, java updates, I don't know, it doesn't work anymore despite I didn't made any change in the app code !?!
  • Tim
    Tim almost 8 years
    Yes I'm sure. That is their use after all
  • fralbo
    fralbo almost 8 years
    @TimCastelijns, maybe but if you read the doc, you will see several data payload only examples but no explanation on them and nothing said about the ability to receive them in background. They only talk about notification and notification + payload messages.
  • Tim
    Tim almost 8 years
    @2ndGAB it is explained pretty well in the 'advanced messaging options' I also linked to :-)
  • miroslavign
    miroslavign over 7 years
    So once again, if the message is data only AND your app is in the background or killed -> onMessageReceived() will NOT be called. Been there, done that. On some version it worked, now, on latest (firebase-core:10.0.1) it does not. Just as a reference, I am using Android Studio 2.2 stable if that should matter
  • Tim
    Tim over 7 years
    @miroslavign if the message is "data" only, onMessageReceived is called regardless of the state of the app (unless it was force stopped)
  • miroslavign
    miroslavign over 7 years
    @TimCastelijns is swipe to kill = force stop ?
  • Tim
    Tim over 7 years
    @miroslavign no
  • miroslavign
    miroslavign over 7 years
    @TimCastelijns agreed, so, before going to latest AS beta release, and gradle and build tools, after swipe-to-kill -> data messages did NOT start onMessageReceived() method. This used to work on a couple of releases, but it suddenly stopped working on a huge pool of devices. Only after updating to latest Firebase (10.0.1) as in github.com/firebase/quickstart-android/issues/89 it started (or started again) working as it should.
  • Tim
    Tim over 7 years
    @miroslavign I didn't know that. Thanks for sharing :)
  • SuperNOVA
    SuperNOVA about 7 years
    Very useful info! Thanks!
  • Stony
    Stony over 5 years
    @TimCastelijns If only contains the "data", when app is closed (not killed, such as restart device, but don't open the app), the notification will not show on system tray.
  • mhtamun
    mhtamun about 4 years
    This is the best answer for this question and for all the question about not showing image when app in the background or killed. @Tim, you are joss.
  • Winteriscoming
    Winteriscoming over 3 years
    where is this key? user_device_token? var message = new Message() { Data = Data, Token = token, Notification = new Notification() { Body = notificationBody, Title = title } };