Xamarin.Forms应用集成FCM后被杀死时无法处理接收推送问题咨询
我查阅了各类教程、其他Stack Overflow帖子,以及Android开发者、Firebase官方文档均未找到解决方案,尝试了几乎所有可行方案,目前时间和精力都已告急,正在修复此前正常运行但现已失效的通知系统。
我使用Azure Notification Hubs向FCM等多个推送平台分发通知,我的FCM项目仅适配Android端,应用基于Xamarin.Forms构建,所有依赖均使用最新版NuGet包(Xamarin.Forms 5.x.x.x、Firebase.Messaging 122.0等)。
目前应用处于运行或后台状态时,通过继承实现FirebaseMessagingService的自定义服务可以完美接收远程消息。但应用被杀死后(任务切换界面上滑移除应用),再发送消息时Logcat会输出如下日志:
broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg= (has extras) }
我了解Google在API 26及以上版本修改了隐式接收器的运行规则,而com.google.android.c2dm.intent.RECEIVE这个action不在豁免列表中,因此我不清楚该如何在后台监听处理这类消息。我在2019年7月的相关帖子中看到,应用被杀死时收到的FCM消息应该会直接展示到通知栏。很多应用都支持被杀死时推送通知,说明这不是普遍问题,希望能获得最新的指导方案。
这个广播被取消是因为隐式接收器规则变更导致的吗?还是我有其他配置错误?
我使用搭载Android 10的OnePlus 7 Pro测试,怀疑可能是类似华为、小米等厂商设备特有的电池优化限制导致的问题。
我的应用目标API level为29,最低兼容API 21。
我已为主Activity和接收器开启了Direct Boot Awareness,确保设备开机后用户尚未打开应用时,接收器也能拦截对应intent:
<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>
我的主Activity配置了启动页相关intent-filter:
<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" />
我在Manifest的<application>标签中添加了如下meta-data配置:
<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/..." />
这些配置在应用后台接收通知时完全正常,说明配置本身没有问题。
编辑1:
发布问题后我又做了进一步排查调试,移除了监听c2dm.intent.RECEIVE action的自定义BroadcastReceiver后发现:
- 应用被杀死时发送的远程消息确实可以通过Google官方提供的FirebaseInstanceIdReceiver接收(该接收器是官方FCM集成流程的默认组件,我已移除了之前提到的NotificationReceiver服务)
- 我自定义实现的FirebaseMessagingService会被启动
- 但FirebaseMessagingService的OnMessageReceived重载方法不会被触发
*******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); } } ...
内容的提问来源于stack exchange,提问作者Andrew H

