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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 22:14:52