Xamarin Android应用划掉后无法接收Data-only推送通知求助
应用被划掉关闭后无法接收Firebase Data-only消息的解决方案
问题描述
应用在前台/后台(最小化)时,OnMessageReceived能正常调用并显示通知,但划掉或关闭全部后无法接收Data-only消息,其他商业应用关闭后却能正常接收。使用Xamarin.Firebase.Messaging NuGet包,已签名APK安装在三星S23上,调用Legacy API返回成功但无通知。
现有配置
Android清单
<application android:label="MyTestingApp" android:theme="@style/MainTheme"> <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" /> <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="${applicationId}" /> </intent-filter> </receiver> </application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
自定义FirebaseMessagingService
[Service(Exported = false, Enabled = true, DirectBootAware =true)] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })] public class MyMessagingService : FirebaseMessagingService{ }
MainActivity的OnStart方法
const int requestLocationId = 0; string[] notiPermission = { Manifest.Permission.PostNotifications }; string[] wakePermission = { Manifest.Permission.WakeLock }; if ((int)Build.VERSION.SdkInt < 33) return; if (activity.CheckSelfPermission(Manifest.Permission.PostNotifications) != Permission.Granted) { activity.RequestPermissions(notiPermission, requestLocationId); activity.RequestPermissions(wakePermission, requestLocationId); }
Postman测试请求体
{ "to": "dpm-g36NSEaC5XFadT3ZnY:APA91bEIarlCxz6UEpyY7CYeBsnCSBpXApW6gHEOiVrvk0URkRP4FCqAHmApPFH4KQLDMfYhkkOTTUZ7ZEsRlyKzCPPS9CuLtet9pXi8_DUflE6h_g-iqtD_9DcVQ4amyb1CCfW05vN2", "CollapseKey": "1", "data": { "body": "Hello,Good Morning! . Have a gr8 day ahead! message_web", "title": "Good Morning!)", "image": "https://images.pexels.com/photos/2055100/pexels-photo-2055100.jpeg", "notificationSmallIcon": "macrokiosk.boldwallet.drawable.logo", "notificationSmallIconColor": "#00ff00", "notificationLargeIcon" : "https://media.istockphoto.com/id/1352603244/photo/shot-of-an-unrecognizable-businessman-working-on-his-laptop-in-the-office.jpg?s=1024x1024&w=is&k=20&c=mTABddPRSU1r_hCBpknMjJbCIrJAicjjXGSU42rx-YI=", "click_action": "web", "actionResult": "https://google.com/" } }
额外环境信息
- Google Play Services版本:118.2.0.5
- 依赖包:
Xamarin.AndroidX.Core 1.12.0.4 Xamarin.AndroidX.Lifecycle.Common 2.7.0.1 Xamarin.Essentials 1.7.3 Xamarin.CommunityToolkit 2.0.2 Xamarin.Firebase.Messaging 123.3.1.1 Xamarin.Forms 5.0.0.2478 Xamarin.GooglePlayServices.Base 118.0.1
解决方案
1. 适配三星设备的后台权限策略
三星对后台进程有严格管控,需手动设置:
- 打开「设置」→「应用」→找到目标应用→「电池和设备维护」→「电池」→「后台限制」→设为「无限制」
- 同一页面开启「自动运行」权限,允许应用后台自启动
2. 优化FirebaseMessagingService配置
修改服务属性,确保进程被杀后能被系统唤醒,并重写消息处理逻辑:
[Service(Exported = true, Enabled = true, DirectBootAware = true)] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })] [IntentFilter(new[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new[] { "${applicationId}" })] public class MyMessagingService : FirebaseMessagingService { public override void OnMessageReceived(RemoteMessage message) { base.OnMessageReceived(message); if (message.Data != null && message.Data.Count > 0) { ShowNotification(message.Data); } } private void ShowNotification(IDictionary<string, string> data) { var title = data.ContainsKey("title") ? data["title"] : "通知"; var body = data.ContainsKey("body") ? data["body"] : ""; var channelId = "default_channel"; var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager; // Android 8.0+创建通知渠道 if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { var channel = new NotificationChannel(channelId, "默认通知", NotificationImportance.High) { Description = "应用通知渠道" }; notificationManager.CreateNotificationChannel(channel); } var intent = PackageManager.GetLaunchIntentForPackage(PackageName); intent.AddFlags(ActivityFlags.ClearTop); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable); var notificationBuilder = new NotificationCompat.Builder(this, channelId) .SetSmallIcon(Resource.Drawable.logo) // 替换为本地图标资源 .SetContentTitle(title) .SetContentText(body) .SetAutoCancel(true) .SetPriority(NotificationCompat.PriorityHigh) .SetContentIntent(pendingIntent); notificationManager.Notify(0, notificationBuilder.Build()); } public override void OnNewToken(string token) { base.OnNewToken(token); Log.Debug("FCM Token", token); // 打印最新Token,确保测试用Token有效 } }
3. 完善Android清单配置
显式声明自定义服务,补充必要的IntentFilter:
<application android:label="MyTestingApp" android:theme="@style/MainTheme" android:allowBackup="true"> <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" /> <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="${applicationId}" /> </intent-filter> </receiver> <service android:name=".MyMessagingService" android:exported="true"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> </intent-filter> </service> </application>
4. 修复权限请求逻辑
按Android版本区分权限请求,确保兼容性:
const int requestNotiId = 1; const int requestWakeId = 2; // Android 13+申请通知权限 if ((int)Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu) { if (CheckSelfPermission(Manifest.Permission.PostNotifications) != Permission.Granted) { RequestPermissions(new[] { Manifest.Permission.PostNotifications }, requestNotiId); } } // Android 12及以下申请唤醒锁权限 if ((int)Build.VERSION.SdkInt <= BuildVersionCodes.S_V2) { if (CheckSelfPermission(Manifest.Permission.WakeLock) != Permission.Granted) { RequestPermissions(new[] { Manifest.Permission.WakeLock }, requestWakeId); } }
5. 切换到FCM V1 API(替代Legacy API)
Legacy API已逐步弃用,改用V1 API并设置高优先级:
{ "message": { "token": "你的设备最新Token", "data": { "body": "测试消息内容", "title": "测试标题" }, "android": { "priority": "high" } } }
内容的提问来源于stack exchange,提问作者leo
相关产品推荐
相关产品推荐

