You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Forms应用开机自启动约2分钟后崩溃问题求助

问题描述

开发的Xamarin Forms应用通过Broadcast Receiver实现开机自启动,重启设备后应用能正常启动,但约2分钟后崩溃,且仅在开机自启动场景下出现该问题。

测试设备:三星Galaxy S8(Android 9)、部分Android TV设备

已尝试无效方案:

  • 启用前台服务
  • 将应用排除在电池优化外

相关代码与配置

AndroidManifest.xml配置

<uses-sdk android:targetSdkVersion="29" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.software.leanback" android:required="false" />
<application android:label="ABC" android:icon="@drawable/icon" android:banner="@drawable/banner">
    <receiver android:name=".MyCustomReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>
</application>

Broadcast Receiver代码

[BroadcastReceiver(Enabled = true, DirectBootAware = true, Exported = true)]
[IntentFilter(new[] { Intent.ActionBootCompleted }, Priority = (int)IntentFilterPriority.HighPriority)]
public class MyCustomReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        if(Intent.ActionBootCompleted.Equals(intent.Action))
        {
            Intent actIntent = new Intent(context, typeof(MainActivity));
            actIntent.AddFlags(ActivityFlags.NewTask);
            context.StartActivity(actIntent);
        }
    }
}

崩溃日志
dalvik.system.BaseDexClassLoader.findClass
BaseDexClassLoader.java, line 134
java.lang.ClassNotFoundException: Didn't find class " com.abc.app.MyCustomReceiver" on path: DexPathList[[zip file "/data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/base.apk"],nativeLibraryDirectories=[/data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/lib/arm64, /data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]

dalvik.system.BaseDexClassLoader.findClass BaseDexClassLoader.java:134
java.lang.ClassLoader.loadClass ClassLoader.java:379
java.lang.ClassLoader.loadClass ClassLoader.java:312
android.app.AppComponentFactory.instantiateReceiver AppComponentFactory.java:84
android.app.ActivityThread.handleReceiver ActivityThread.java:3561
android.app.ActivityThread.access$1300 ActivityThread.java:237
android.app.ActivityThread$H.handleMessage ActivityThread.java:1796
android.os.Handler.dispatchMessage Handler.java:106
android.os.Looper.loop Looper.java:214
android.app.ActivityThread.main ActivityThread.java:7045
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:493
com.android.internal.os.ZygoteInit.main ZygoteInit.java:964

android.app.ActivityThread.handleReceiver ActivityThread.java:3568
android.app.ActivityThread.access$1300 ActivityThread.java:237
android.app.ActivityThread$H.handleMessage ActivityThread.java:1796
android.os.Handler.dispatchMessage Handler.java:106
android.os.Looper.loop Looper.java:214
android.app.ActivityThread.main ActivityThread.java:7045
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:493
com.android.internal.os.ZygoteInit.main ZygoteInit.java:964

--------------------------------

java.lang.RuntimeException: Unable to instantiate receiver  com.abc.app.MyCustomReceiver: java.lang.ClassNotFoundException: Didn't find class " com.abc.app.MyCustomReceiver" on path: DexPathList[[zip file "/data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/base.apk"],nativeLibraryDirectories=[/data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/lib/arm64, /data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]
android.app.ActivityThread.handleReceiver ActivityThread.java:3568
android.app.ActivityThread.access$1300 ActivityThread.java:237
android.app.ActivityThread$H.handleMessage ActivityThread.java:1796
android.os.Handler.dispatchMessage Handler.java:106
android.os.Looper.loop Looper.java:214
android.app.ActivityThread.main ActivityThread.java:7045
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:493
com.android.internal.os.ZygoteInit.main ZygoteInit.java:964
Caused by: java.lang.ClassNotFoundException: Didn't find class " com.abc.app.MyCustomReceiver" on path: DexPathList[[zip file "/data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/base.apk"],nativeLibraryDirectories=[/data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/lib/arm64, /data/app/ com.abc.app-l5EOpz_TN-hTJakX5ZMe5Q==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]
dalvik.system.BaseDexClassLoader.findClass BaseDexClassLoader.java:134
java.lang.ClassLoader.loadClass ClassLoader.java:379
java.lang.ClassLoader.loadClass ClassLoader.java:312
android.app.AppComponentFactory.instantiateReceiver AppComponentFactory.java:84
android.app.ActivityThread.handleReceiver ActivityThread.java:3561

解决方案

1. 移除AndroidManifest.xml中手动添加的Receiver配置

Xamarin会通过[BroadcastReceiver]特性自动在生成的Manifest中注册Receiver,手动添加的<receiver>节点会导致重复注册,且android:name=".MyCustomReceiver"这种相对类名可能和Xamarin生成的全类名不匹配(日志中类名前的空格也可能由此导致)。直接删除Manifest里的以下内容:

<receiver android:name=".MyCustomReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

如果需要监听QUICKBOOT_POWERON,直接在C#的IntentFilter特性里添加:

[IntentFilter(new[] { Intent.ActionBootCompleted, Intent.ActionQuickbootPoweron }, Priority = (int)IntentFilterPriority.HighPriority)]

2. 确保Receiver类被打包进主Dex

Android 9及以上,开机广播触发时系统可能只加载主Dex文件,如果Receiver类被打包到次Dex中,就会出现ClassNotFoundException。在Xamarin中开启MultiDex并配置主Dex列表:

  • 在Android项目的Properties -> Android Options -> Advanced中勾选Enable MultiDex
  • 创建multidex-config.txt文件,添加Receiver的全类名:
com.abc.app.MyCustomReceiver
  • 在项目属性的Android Options -> Additional Options中添加:
--multi-dex-config=multidex-config.txt

3. 优化开机启动逻辑,避免进程被回收后触发Receiver异常

开机后直接启动Activity,应用进程可能在闲置时被系统回收,后续如果有广播再次触发Receiver,就会因类加载失败崩溃。改为启动前台服务来维持进程:

public override void OnReceive(Context context, Intent intent)
{
    if (Intent.ActionBootCompleted.Equals(intent.Action) || Intent.ActionQuickbootPoweron.Equals(intent.Action))
    {
        // 启动前台服务
        var serviceIntent = new Intent(context, typeof(StartupService));
        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            context.StartForegroundService(serviceIntent);
        }
        else
        {
            context.StartService(serviceIntent);
        }
        // 再启动Activity
        Intent actIntent = new Intent(context, typeof(MainActivity));
        actIntent.AddFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop);
        context.StartActivity(actIntent);
    }
}

前台服务StartupService的示例:

[Service(Exported = true, ForegroundServiceType = ForegroundService.TypeSpecialUse)]
public class StartupService : Service
{
    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        // 创建通知,维持前台服务状态
        var notification = new Notification.Builder(this, "startup_channel")
            .SetContentTitle("应用启动中")
            .SetContentText("正在维持进程")
            .SetSmallIcon(Resource.Drawable.icon)
            .Build();

        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            var channel = new NotificationChannel("startup_channel", "Startup Channel", NotificationImportance.Low);
            var notificationManager = GetSystemService(NotificationService) as NotificationManager;
            notificationManager.CreateNotificationChannel(channel);
        }

        StartForeground(1, notification);

        // 可以在延迟后停止前台服务,或者根据业务需求维持
        Task.Delay(TimeSpan.FromMinutes(5)).ContinueWith(t =>
        {
            StopForeground(true);
            StopSelf();
        });

        return StartCommandResult.Sticky;
    }

    public override IBinder OnBind(Intent intent)
    {
        return null;
    }
}

4. 检查类名中的空格问题

崩溃日志中类名前有空格" com.abc.app.MyCustomReceiver",确认项目的命名空间没有多余空格,同时清理项目并重新生成,避免编译时生成错误的类名。


内容的提问来源于stack exchange,提问作者Zaheer Mehmood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:47:14