Android应用强制停止后无法接收FCM通知求助
问题描述
FCM消息推送在iOS和Web端正常,但Android平台应用被强制停止(终止)时无法接收通知,出现错误日志:
broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10000000 pkg= (has extras) }
应用处于前台/后台时接收正常,Google Play商店版本也存在此问题。
相关配置代码如下:
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="com.example.permission.C2D_MESSAGE"/> <permission android:name="com.example.permission.C2D_MESSAGE" android:protectionLevel="signature"/> <application android:label="Example" android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" /> <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="example_notification" /> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <intent-filter> <action android:name="FLUTTER_NOTIFICATION_CLICK" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <meta-data android:name="flutterEmbedding" android:value="2" /> </application> </manifest>
main.dart关键代码
@pragma('vm:entry-point') Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { debugPrint("Handling a background message: ${message.messageId}"); DartPluginRegistrant.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await setupFlutterNotifications(); showFlutterNotification(message); print('Handling a background message ${message.messageId}'); } // 其余setupFlutterNotifications、showFlutterNotification等代码略
解决方案
1. 完善AndroidManifest的FCM组件配置
你的Manifest缺少FCM核心服务和系统级广播接收器的声明,这是应用被强制停止后能被唤醒接收推送的关键。在<application>标签内添加以下内容:
<!-- FCM消息处理服务 --> <service android:name="com.google.firebase.messaging.FirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <!-- 令牌刷新服务 --> <service android:name="com.google.firebase.iid.FirebaseInstanceIdService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT" /> </intent-filter> </service> <!-- 系统级C2DM广播接收器,用于应用停止时接收推送唤醒信号 --> <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>
${applicationId}会自动替换为你的应用包名,无需手动修改。
2. 优化后台消息处理逻辑
- 移除
_firebaseMessagingBackgroundHandler中重复的Firebase.initializeApp调用,FirebaseMessaging.onBackgroundMessage已经自动初始化Firebase核心服务,重复调用可能导致冲突。 - 确保
setupFlutterNotifications的初始化逻辑不会重复执行,避免后台唤醒时出现异常。
修改后的_firebaseMessagingBackgroundHandler:
@pragma('vm:entry-point') Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { debugPrint("Handling a background message: ${message.messageId}"); DartPluginRegistrant.ensureInitialized(); await setupFlutterNotifications(); showFlutterNotification(message); print('Handling a background message ${message.messageId}'); }
3. 处理厂商后台限制
部分国产Android厂商(小米、华为、OPPO等)有严格的后台唤醒限制,即使配置正确,应用被强制停止后也可能无法接收推送。需要引导用户:
- 给应用开启「自启动权限」
- 在电池优化中设置为「不优化」
- 将应用锁定到后台多任务列表
4. 确认推送消息类型
FCM分为通知消息和数据消息:
- 通知消息:应用后台时由系统直接展示,强制停止后系统仍会接收并展示;若用自定义组件展示,需确保消息格式包含
notification字段。 - 数据消息:必须由应用后台处理器处理,依赖正确的Manifest配置和厂商权限才能在应用停止时唤醒应用。
确保服务器端推送的消息包含notification字段,或同时包含data字段,且格式符合FCM规范。
5. 验证签名与包名一致性
Google Play商店版本需确保签名证书与Firebase控制台配置一致,包名也必须完全匹配,否则FCM服务会拒绝推送请求。
内容的提问来源于stack exchange,提问作者KerimY
相关产品推荐
相关产品推荐

