Android 9+设备Flutter/Kotlin应用开机自启失败问题求助
Flutter/Kotlin 应用 Android 9+ 开机自启不显示问题
我希望我的Flutter/Kotlin应用能在Android 9及以上设备开机时自动启动并显示界面。尝试使用BroadcastReceiver实现,但只收到日志,应用无法可视化启动。
已配置内容
1. 清单文件添加权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2. 声明BroadcastReceiver
<receiver android:name=".BootBroadcastReceiver" android:enabled="true" android:exported="false" android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
3. BroadcastReceiver 实现类
import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager import androidx.work.WorkRequest class BootBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent != null) { if(intent.action == Intent.ACTION_BOOT_COMPLETED) { Log.d("BootBroadcastReceiver", "Boot completed. Scheduling app launch.") // 计划延迟启动应用 val workRequest: WorkRequest = OneTimeWorkRequest.Builder(AppLaunchWorker::class.java).build() context?.let { WorkManager.getInstance(it).enqueue(workRequest) } } } } }
4. AppLaunchWorker 实现类
import android.content.Context import android.content.Intent import androidx.work.Worker import androidx.work.WorkerParameters import io.flutter.embedding.android.FlutterActivity class AppLaunchWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { override fun doWork(): Result { // 系统启动后启动FlutterActivity val launchIntent = FlutterActivity.createDefaultIntent(applicationContext) launchIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK // 非交互上下文启动Activity必需 applicationContext.startActivity(launchIntent) return Result.success() } }
问题现象
能在日志中看到 Log.d("BootBroadcastReceiver", "Boot completed. Scheduling app launch.") 的输出,但应用界面并未弹出显示。
解决方案
1. 适配Android 9+后台启动限制
从Android 9(API 28)开始,系统严格限制后台应用启动Activity的行为,WorkManager的doWork()属于后台线程,直接启动Activity会被系统拦截。可调整启动逻辑:
override fun doWork(): Result { val activityManager = applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val tasks = activityManager.appTasks if (tasks.isNotEmpty()) { // 若应用已有任务栈,直接将其移到前台 tasks[0].moveToFront() } else { // 无任务栈时启动默认入口 val launchIntent = applicationContext.packageManager.getLaunchIntentForPackage(applicationContext.packageName) launchIntent?.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED applicationContext.startActivity(launchIntent) } return Result.success() }
需额外添加权限:
<uses-permission android:name="android.permission.REORDER_TASKS" />
2. 修正BroadcastReceiver的exported属性
ACTION_BOOT_COMPLETED是系统发送的广播,需要组件允许外部(系统)访问,将android:exported="false"改为:
android:exported="true"
3. 申请电池优化豁免权限
部分厂商的电池优化策略会阻止应用后台启动,需添加权限并引导用户授权:
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
在应用首次启动时发起请求:
val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) intent.data = Uri.parse("package:" + packageName) startActivity(intent)
4. 跳过WorkManager,直接在BroadcastReceiver启动
尝试去掉WorkManager,直接在onReceive中启动Activity(注意onReceive执行时间限制):
override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { Log.d("BootBroadcastReceiver", "Boot completed. Launching app.") val launchIntent = context?.packageManager?.getLaunchIntentForPackage(context.packageName) launchIntent?.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED context?.startActivity(launchIntent) } }
5. 检查Flutter启动Intent
替换FlutterActivity.createDefaultIntent为应用默认启动Intent,避免Intent配置错误:
val launchIntent = applicationContext.packageManager.getLaunchIntentForPackage(applicationContext.packageName)
内容的提问来源于stack exchange,提问作者Théo LOURY
相关产品推荐
相关产品推荐

