Xamarin Android应用被杀掉状态下接收FCM推送崩溃求助
我之前也碰到过一模一样的问题!这种情况大概率是因为应用被杀掉时,FCM发送的是「通知消息」而不是「数据消息」,系统会直接处理通知,不会走到你的OnMessageReceived方法,而且如果你的通知点击逻辑没处理好,就容易触发崩溃。下面给你拆解原因和解决办法:
问题核心原因
当Android应用被彻底杀死(进程终止)时:
- 如果FCM发送的是通知类型消息(包含
notification字段),系统会直接接管通知的展示,不会唤醒你的FirebaseMessagingService,也就不会执行OnMessageReceived里的代码。 - 用户点击这条系统展示的通知时,系统会尝试启动你的应用主Activity,但如果你的Activity在启动时依赖了还未初始化的资源(比如Xamarin Forms的核心组件、依赖服务等),就会直接崩溃。
- 而应用在前台/后台时,
OnMessageReceived会被正常调用,你可以自行处理通知逻辑,所以不会出问题。
具体解决步骤
1. 让后端发送「纯数据消息」
优先让后端调整FCM消息结构,去掉notification字段,只保留data字段。这种情况下,即使应用被杀掉,系统也会唤醒你的FirebaseMessagingService,执行OnMessageReceived,你可以在方法内自行创建并展示通知,完全掌控逻辑。
示例数据消息结构:
{ "to": "你的设备Token", "data": { "title": "新通知提醒", "content": "这是一条自定义数据消息", "page": "DetailPage", "id": "123" } }
2. 修复通知点击的启动逻辑(如果必须用通知消息)
如果业务上必须发送通知类型消息,那就要确保主Activity被系统启动时,能正确处理通知数据,且不会因未初始化资源崩溃:
在Android项目的MainActivity中重写OnCreate,先完成Xamarin Forms初始化,再处理通知数据:
protected override void OnCreate(Bundle savedInstanceState) { // 先完成基础初始化,确保Forms环境就绪 base.OnCreate(savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); LoadApplication(new App()); // 处理通知点击传递的参数 if (Intent.Extras != null) { foreach (var key in Intent.Extras.KeySet()) { var value = Intent.Extras.GetString(key); // 根据自定义字段执行逻辑,比如导航到指定页面 if (key == "page" && value == "DetailPage") { // 通过MessagingCenter通知Forms端处理导航 MessagingCenter.Send<object, string>(this, "NavigateToDetail", Intent.Extras.GetString("id")); } } } }
3. 检查Firebase服务的配置正确性
确认你的FirebaseMessagingService子类已经在AndroidManifest.xml中正确注册:
<service android:name=".MyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
4. 捕获崩溃日志定位问题
如果还是不确定崩溃原因,可以在Android项目中添加全局异常捕获,把崩溃日志写入本地文件:
创建自定义Application类:
[Application] public class MyApp : Application { public MyApp(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { } public override void OnCreate() { base.OnCreate(); // 捕获未处理异常 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser; } private void AndroidEnvironment_UnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e) { // 写入崩溃日志到本地存储 var logPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "crash.log"); File.WriteAllText(logPath, e.Throwable.ToString()); e.Handled = true; } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var logPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "crash.log"); File.WriteAllText(logPath, e.ExceptionObject.ToString()); } }
崩溃后取出crash.log文件,就能看到具体的崩溃堆栈信息,精准定位问题。
内容的提问来源于stack exchange,提问作者Sai Sunkari
相关产品推荐
相关产品推荐

