我一直在阅读各种教程、其他 SO 线程以及官方 Android 开发人员和 Firebase 文档,但无济于事。我已经尝试了几乎所有的方法,但我已经耗尽了精力和时间,因为我正在修复以前可以工作但现在不再工作的通知系统。
我正在使用 Azure 通知中心将通知分发到 FCM 以及其他推送通知平台。我的 FCM 项目仅针对 Android。我的应用程序是使用所有依赖项的最新 NuGet 包版本(Xamarin.Forms 5.x.x.x、Firebase.Messaging 122.0 等)在 Xamarin.Forms 中构建的。
目前,应用程序运行时接收的远程消息或在后台通过继承和实现 FirebaseMessagingService 的自定义服务完美地工作。一旦应用程序被终止(任务切换器 -> 滑动应用程序),在发送更多消息后,我开始看到包含以下内容的 Logcat 消息:
广播意图回调: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg= (有额外内容) }
我了解 Google 改变了 API 26 及更高版本中隐式接收器的工作方式,我的理解是此操作(com.google.android.c2dm.intent.RECEIVE
)未包含在例外列表中,因此我不知道如何在后台监听和处理消息。我最近在 2019 年 7 月在其他线程中读到,在应用程序被终止时收到的 FCM 消息应该直接发送到通知托盘。这不会是一个普遍存在的问题,因为许多应用程序在被杀死时都会发送通知,因此我希望获得一些当前信息来指导我找到解决方案。
这个意图广播是否由于隐式接收器更改而被取消,或者我做错了什么?
我正在运行 Android 10 的 OnePlus 7 Pro 上进行测试,所以我想知道这是否是其他人在华为和小米等 OEM 设备上提到的电池优化问题。
我的应用程序的目标 Android API 级别 29,最低 API 21
我为我的主要活动和接收器启用了直接启动感知,以确保接收器在启动时和用户打开应用程序之前拦截我的应用程序的意图:
<receiver android:directBootAware="true" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND" android:name=".NotificationReceiver">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="<package>" />
</intent-filter>
</receiver>
我的主要活动包括作为启动活动的意图过滤器:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name=".MainActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
我请求以下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
我定义了以下内容meta-data
我的清单中的标签<application>
tag:
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/..."/>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/..." />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/..." />
这些值非常适合在后台收到的通知,因此我知道它们配置正确。
Edit 1:
自从发布以来,我做了更多的挖掘和调试,我确实看到了这一点,如果我的自定义 BroadcastReceiver 也没有监听我的应用程序的 c2dm.intent.RECEIVE 操作:
- 实际上是通过Google提供的内部FirebaseInstanceIdReceiver获取我在应用程序被终止时发送的远程消息,该内部FirebaseInstanceIdReceiver是记录的FCM设置的一部分(我删除了前面提到的NotificationReceiver服务)
- 正在开始我的 FirebaseMessagingService 的自定义实现(请参见下面的屏幕截图)
- 没有触发我的 FirebaseMessagingService 中的 OnMessageReceived 过载(请参见下面的屏幕截图)
当应用程序被终止时收到 FCM 远程消息时的 logcat https://i.stack.imgur.com/udGtk.png
*****FirebaseService 部分代码:
[Service(DirectBootAware = true, Exported = true, Enabled = true)]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class MyFirebaseService : FirebaseMessagingService
{
public MyFirebaseService()
{
}
public override ComponentName StartService(Intent service)
{
Log.Info("GCM", $"MyFirebaseService started from intent {service}");
return base.StartService(service);
}
public override void OnMessageReceived(RemoteMessage message)
{
var notification = message.GetNotification();
Log.Info("GCM", $"Received remote message from FCM. Has notification: {notification != null}, has data: {message.Data != null}");
if (notification != null)
{
message.Data.TryGetValue("route", out string route);
SendNotification(notification.Title, notification.Body, route);
}
else
{
ParseDataNotification(message);
}
}
...