Android通知:onMessageReceived未被调用

4

首先,这不是因为应用程序在后台运行。

通知是使用数据消息负载发送的。在Play控制台中,它显示消息已“确认”,因此它们已到达设备。对于大多数用户,将调用onMessageReceived方法,但对于少数用户,则不会。这是为什么呢?

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>

我的Firebase消息服务:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

...
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
...
}

你是否检查过在这种情况下通知和数据负载是否都已从服务器发送? - Debdeep
@Debdeep 我发送数据有效载荷,以便调用onMessageReceived方法。是的,我会检查它是否已经发送。 - Questioner
为了在系统托盘和数据意图中获取通知,您需要同时发送它们。请查看此链接-https://firebase.google.com/docs/cloud-messaging/android/send-multiple - Debdeep
@Debdeep 如果在 FCM 诊断中消息显示为“已确认”,是否仍可能调用 onDeletedMessages() 方法?我不想向用户推送另一个不能解决问题的更新。 - Questioner
在通知的正文中,不要发送通知部分,而是在数据部分发送您需要的任何内容。 - Manohar
显示剩余12条评论
7个回答

3
这种情况可能的主要原因之一是用户更改了登录详细信息或在使用应用时使用了不同的帐户。在这种情况下,特定的设备令牌将接收到通知,但由于他正在使用不同的帐户,因此通知不会显示。解决此问题的一种方法是在用户注销时清除用户的设备令牌并保存新创建的令牌,在用户再次登录时使用。这样设备令牌就得到更新,用户就可以收到通知。

什么?如果设备正在接收通知,为什么不会调用onMessageReceived? - Questioner
每当调用 onTokenRefresh 时,令牌就会被保存。 - Questioner
我仍然对你的回答感到困惑。你所说的“账户”和“登录详情”是什么意思?首先,我有所有这些的日志记录,而且这些用户没有退出登录,但我不明白这会如何影响 Firebase 令牌或显示通知。如果令牌更改,那与我的应用程序无关,并且会调用 onTokenRefresh,对吗?每当 onTokenRefresh 被调用时,我的应用程序就会将新令牌发送上去。我有每次应用程序发送此令牌的日志记录,并且可以清楚地看到它发生在通知被发送的一两天内,但 onMessageReceived 没有被调用。 - Questioner
让我们在聊天中继续这个讨论 - Questioner

2
这是按预期工作的,只有当您的应用程序在前台时,通知消息才会传递到您的onMessageReceived回调函数。如果您的应用程序在后台或关闭状态下,则通知消息将显示在通知中心,并将从该消息传递给由用户点击通知后启动的意图中的任何数据。
您可以指定click_action以指示用户点击通知时应启动的意图。如果未指定click_action,则使用主活动。
当意图被启动时,您可以使用它们。
getIntent().getExtras();

要检索包括通知消息中发送的任何数据的Set,可以使用以下方法:

第二种方法

在您的FirebaseMessagingService类中覆盖handleIntent(Intent intent)方法。

handleIntent()方法会在应用程序处于前台、后台或已关闭状态时每次调用。

有关通知消息的更多信息,请参见文档


1
我在问题开头用粗体字说过,这不是因为应用程序在后台运行而被忽略了。这是一个数据负载,并且如果应用程序在后台运行,则会调用该方法,但并非适用于每个设备。 - Questioner

1
问题可能出在Firebase令牌注册上。您是否在以下函数中记录了令牌生成过程?
public class TixDoFirebaseIntentService extends FirebaseInstanceIdService {
    @Override
    public void onTokenRefresh() {
        Common.log("FirebaseToken :"+FirebaseInstanceId.getInstance().getToken());
    }
}

可能存在这样一种情况,用户已经安装了应用程序,但尚未打开它,因此没有生成令牌。

不,不是这样的。令牌已经被注册并且正常使用。问题出在通知无法到达设备,导致onMessageReceived方法没有被调用,就像我之前提问的那样。 - Questioner
通知未到达的情况是在应用程序打开时还是关闭时? - Chandan Bhandari
有一种情况是当您在通知对象和数据对象中发送数据时。如果应用程序关闭(不在后台),则应用程序将直接使用通知对象创建通知,而不调用onMessageReceived()函数。 - Chandan Bhandari
请在发帖前阅读文档、我的问题和评论。这不是因为应用程序在后台运行。这不是因为应用程序在后台运行。这不是因为应用程序在后台运行。 - Questioner

1

您在清单文件中使用了下面的服务吗?

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

如果还不行,那么请创建一个FirebaseIDService,它继承FirebaseInstanceIdService并实现其方法。 如果仍然无法解决问题,则设置可能存在问题,请按照https://www.survivingwithandroid.com/2016/09/android-firebase-push-notification.html中的步骤将Firebase设置到您的项目中。
如果仍然没有响应,则可以使用Tomin的第二种方法。
更新:现在您不需要在清单文件中使用上述服务标签,因为它已经过时了。现在,您可以在FirebaseMessagingService中实现重写方法onNewToken(String token)并更新您的令牌。

哪个不是真的? - ChandraShekhar Kaushik
回答你的第一个问题,是的,我在我的清单文件中有这个。令牌在我的后端是最新的。再次强调,通知已经到达设备,但 onMessageReceived 没有被调用。这就是问题所在。 - Questioner

1
我有两个解决方案:
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()方法在应用程序处于前台、后台或被杀死状态时都会被调用。


1
"

对于“处理消息”的文档说明:

要接收消息,请使用扩展FirebaseMessagingService服务

您的服务应覆盖onMessageReceivedonDeletedMessages回调。

它应该在收到消息后的10秒内处理任何消息。之后,Android 不保证执行,并且可能随时终止您的进程

如果您的应用程序需要更多时间来处理消息,请使用Firebase Job Dispatcher

"
实现onMessageReceived应该基准测试执行时间,并在RemoteMessage的情况下,如果执行时间超过10秒(某些情况下),使用调度程序派发一个Job。即使在覆盖onMessageReceived文档中也是如此。 始终分派作业通常可以解决关联进程被终止的可能性,无论需要多长时间才能返回。onMessageReceived很可能已经被调用,但被终止了。

@Questioner,您能在Crashlytics中确定问题吗?虽然设备特定的错误很少见,但确实存在;可能是特定的Android API级别(在特定型号上),或者是已安装的谷歌应用商店版本。实际问题可能是:您所说的“少数人”是什么意思?如果您找到了,请访问以下链接:https://firebase.google.com/support/contact/bugs-features - Martin Zeitler
不,我记录每个设备类型,没有任何模式。一些设备有问题,而其他相同型号和API级别的设备则没有问题。应用程序版本也是如此。少数情况下,我的意思是几千个。 - Questioner
@Questioner 除非能够确定一个模式,否则这可能只是瞎猜 - 虽然我怀疑这些设备仍然与其他设备有不同的状态,例如:锁屏。可以询问 KeyguardManager 是否是这种情况(并且在那里有不同的通知显示设置)...或者询问 PowerManager 设备是否正在睡眠。除此之外,我想不到还有什么理论上可能影响行为的因素了。 - Martin Zeitler

0

当您发送消息时,如果是通用的而不是针对特定设备,则会出现此问题。

获取 FCM 令牌,并将消息发送到“单个设备选项”。

这样就可以解决问题了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接