4

First of all, it's not because the app is in the background.

The notifications are sent with a data message payload. In the Play console it says the messages are 'Acknowledged', so they're reaching the device. For most users, the onMessageReceived method is called, but for a minority, it isn't. Why would this be?

AndroidManifest:

<service android:name=".push.MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
    </intent-filter>
</service>
<service android:name=".push.MyFirebaseMessagingService">
    <intent-filter>
         <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

MyFirebaseMessagingService:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

...
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
...
}
Questioner
  • 2,191
  • 3
  • 24
  • 46
  • you have registered your `firebase` token to server I think? – Abdul Kawee Nov 07 '17 at 13:41
  • @AbdulKawee yes. The message reaches the devices and it says 'Acknowledged' in the Play console. – Questioner Nov 07 '17 at 14:18
  • Have you checked If both the notification and data payload are being sent from the server in such case? – Debdeep Nov 13 '17 at 16:33
  • @Debdeep I send the data payload, so that the onMessageReceived method gets called. And yes, I check if it's been sent or not. – Questioner Nov 13 '17 at 16:37
  • For getting the notification in the system tray and the data intent, you'll need to send both of them. Please check this link - https://firebase.google.com/docs/cloud-messaging/android/send-multiple – Debdeep Nov 13 '17 at 16:42
  • Also debug by overriding onDeletedMessages() for those messages. – Debdeep Nov 13 '17 at 16:43
  • @Debdeep I don't understand. Are you saying you need the notification payload in order to get it in the system tray? Why am I getting the notification in the system tray for most of the messages? – Questioner Nov 14 '17 at 09:37
  • @Debdeep If the message is 'Acknowledged' in FCM diagnostics, can it still end up calling onDeletedMessages()? I don't want to push yet another update to the users that doesn't fix the problem. – Questioner Nov 14 '17 at 09:38
  • So it only happens on specific devices/users. Hard to see what's wrong here based on the data provided. Could you test the actual registration tokens and see if they are all valid? – AL. Nov 14 '17 at 12:54
  • In Body of notification don't send notification part , send what ever you need in data part. – Manohar Reddy Nov 14 '17 at 13:42
  • @AL How do I test them past checking them in FCM diagnostics? The messages say 'Acknowledged' when I put in their registration token, so they must be valid. – Questioner Nov 15 '17 at 15:29
  • @Redman I'm already doing that – Questioner Nov 17 '17 at 16:06
  • that's a possible duplicate of https://stackoverflow.com/questions/37358462/firebase-onmessagereceived-not-called-when-app-in-background ..."because "the app is in background", might probably be the reason for the behavior & the answer to the question, already. – Martin Zeitler Nov 20 '17 at 11:32
  • @MartinZeitler No, it's not. That's why I said it wasn't in the question. – Questioner Nov 23 '17 at 13:22
  • @Questioner how can you even know, unless it is being tested locally (the term "minority" suggests otherwise)? to me this reads just alike "a minority of users suffers from the app not receiving the events, because the app is in background mode". – Martin Zeitler Nov 23 '17 at 13:25
  • Because, as I said in the question, the message is sent with a data payload, not a notification payload. This is supposed to result in an onMessageReceived call, which it does for me and most people, whether the app is in the background or not. That's how I know this question is not a duplicate of that one. This is explained even in the answers on that one... – Questioner Nov 23 '17 at 13:41
  • @Questioner added a possible answer. – Martin Zeitler Nov 24 '17 at 09:02

7 Answers7

3

One of the main reasons why this could be happening is because the particular user has changed his login details or is using a different account when using the app. In this particular case, the particular device token would be receiving the notification, but since he is using a a different account, the notification is not displayed. One way to go around this issue is to clear the user's device token each time the user logs out and saved the newly created one, when a user logs in again. This way the device token is kept updated and the user will receive the notifications.

Michele La Ferla
  • 6,265
  • 11
  • 44
  • 75
  • What? If the device is receiving the notification, why wouldn't onMessageReceived be called? – Questioner Nov 17 '17 at 10:05
  • The token is saved whenever onTokenRefresh is called – Questioner Nov 17 '17 at 10:19
  • I'm still confused by your answer. What do you mean by 'account' and 'login details'? First of all, I have logs of all of that and these users aren't logging out, but I don't get how that would even affect the Firebase tokens or the notification being displayed. If the token changes, that's independent of my app, and onTokenRefresh is called, right? Whenever onTokenRefresh is called, my app sends the new token up. I have logs of each time my app sends this token up and I can see clearly it's happened within a day or two of the notification being sent but onMessageReceived not called – Questioner Nov 17 '17 at 10:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/159219/discussion-between-questioner-and-dev-mi). – Questioner Nov 17 '17 at 10:38
2

This is working as intended, notification messages are delivered to your onMessageReceived callback only when your app is in the foreground. If your app is in the background or closed then a notification message is shown in the notification center, and any data from that message is passed to the intent that is launched as a result of the user tapping on the notification.

You can specify a click_action to indicate the intent that should be launched when the notification is tapped by the user. The main activity is used if no click_action is specified.

When the intent is launched you can use them

getIntent().getExtras();

to retrieve a Set that would include any data sent along with the notification message.

SECOND METHOD

Override handleIntent(Intent intent) method in your FirebaseMessagingService class.

handleIntent() method is called every time whether the app is in the foreground, background or killed state.

For more on notification message see docs.

Jitesh Mohite
  • 15,430
  • 6
  • 71
  • 84
Tomin B Azhakathu
  • 2,562
  • 1
  • 13
  • 25
  • 1
    I said in bold text at the start of the question it wasn't because the app was in the background and you ignored that. It's a data payload and the method is called if the app is in the background, just not for every device. – Questioner Nov 21 '17 at 11:24
1

the issue must be with the firebase token registration. have you logged the token generation in the below function:

public class TixDoFirebaseIntentService extends FirebaseInstanceIdService {
    @Override
    public void onTokenRefresh() {
        Common.log("FirebaseToken :"+FirebaseInstanceId.getInstance().getToken());
    }
}

there may be a case that user had installed the app but haven't opened it yet, therefore resulting in no generation of the token.

  • No, it's not. The tokens are being registered and used perfectly fine. The problem is with the notification reaching the device but the onMessageReceived method not being called, like my question said. – Questioner Nov 21 '17 at 11:27
  • in which case is notification not reaching? When app is opened or when app is closed – Chandan Bhandari Nov 21 '17 at 11:32
  • there is a case when you send data in Notification object as well as the Data object.If the app is closed (not in background also) then app uses Notification object to create notification directly without invoking onMessageRecieved() function – Chandan Bhandari Nov 21 '17 at 11:34
  • Please read the docs, read my question and read my comment before posting. It's not because the app is in the background. It's not because the app is in the background. It's not because the app is in the background. – Questioner Nov 21 '17 at 11:37
1

Have you used below service in manifest file?

    <service android:name="push_notification.service.FirebaseIDService">
              <intent-filter>
                    <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
              </intent-filter>
    </service>

if not then use it create a FirebaseIDService which extends FirebaseInstanceIdService implements its methods. If it still doesn't work then there's something wrong with the setup please folow https://www.survivingwithandroid.com/2016/09/android-firebase-push-notification.html to setup firebase into your project.

If still no response then you can use the Tomin's second method.

Updated:- Now you don't need to use above service tag inside your manifest because It's deprecated. Now you can implement the overriden method onNewToken(String token) in your FirebaseMessagingService and update your token.

  • which one is not true? – ChandraShekhar Kaushik Nov 22 '17 at 11:32
  • https://stackoverflow.com/a/47312925/4838107 And to answer your first question, yes I have that in my manifest. The tokens are up to date in my backend. Once again, the notifications reach the device but onMessageReceived isn't called. That's the problem. – Questioner Nov 23 '17 at 10:18
1

I have two solutions for this:

1.Upgrade your firebase to version compile com.google.firebase:firebase-messaging:10.2.1
2.Override handleIntent(Intent intent) method in your FirebaseMessagingService class.

handleIntent() method is called everytime whether app is in foreground, background or killed state.

Jayesh
  • 121
  • 5
1

the docs for "Handling Messages" state:

To receive messages, use a service that extends FirebaseMessagingService.

Your service should override the onMessageReceived and onDeletedMessages callbacks.

It should handle any message within 10 seconds of receipt. After that, Android does not guarantee execution, and could terminate your process at any time.

If your app needs more time to process a message, use the Firebase Job Dispatcher.

the implementation of onMessageReceived should benchmark the execution time and dispatch a Job with the dispatcher, from the RemoteMessage - in case the execution time should be above 10 seconds (on certain occasions). the docs for Override onMessageReceived even show it alike that.

always dispatching a job would generally work around the possibility to have the associated process terminated, no matter how long it may take to return. onMessageReceived most likely is being called, but terminated.

Community
  • 1
  • 1
Martin Zeitler
  • 49,224
  • 12
  • 97
  • 156
  • @Questioner can you isolate the problem in Crashlytics? device-specific bugs are rare, but do exist; it could be a particular Android API level (on a particular model), too... or the installed Google Play app version. the actual question might be: what you mean by "a minority"? in case you can find out: https://firebase.google.com/support/contact/bugs-features – Martin Zeitler Dec 01 '17 at 07:32
  • No, I log each device type and there's no pattern whatsoever. Some devices have the problem and others with the same device and API level don't. Same with app version. By a minority I mean a few thousand. – Questioner Dec 01 '17 at 11:25
  • @Questioner unless one can identify a pattern, this might be merely guessing around - while I'd suspect those devices nevertheless having a different state than the others, for example: the lock-screen. one could ask the `KeyguardManager`, if this is the case (and there are different settings for the display of notifications there, as well)... or asking the `PowerManager`, if the device is sleeping. beside that there is little I could think of which could theoretically affect the behavior. – Martin Zeitler Dec 02 '17 at 03:07
0

This happens when you send the message in general and not to specific device

Take the fcm token, and send the message to the "Single Device option".

This works.

Shadab K
  • 1,497
  • 12
  • 21