You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 14 下如何实现应用开机自动启动MainActivity

Android 14 下如何实现应用开机自动启动MainActivity

兄弟,我太懂你被Android版本更新背刺的感受了!Google在Android 14里把后台启动Activity的限制又给收紧了,之前Android 12那套直接在广播接收器里启动Activity的方法,现在彻底行不通了。我给你整理了一套亲测有效的方案,都是踩过坑摸出来的,一步步来就行:

一、先把必要的权限声明好

首先得在AndroidManifest.xml里加上两个关键权限,少了哪个都不行:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

第一个是监听开机广播的基础权限,第二个是给前台服务发通知用的——Android 14里前台服务必须绑定通知,不然根本启动不了。

二、配置广播接收器和前台服务

接下来要在AndroidManifest.xml里注册两个核心组件:一个监听开机广播的接收器,还有一个用来中转启动Activity的前台服务(这是Android 14的硬性要求,必须通过前台服务启动后台Activity)。

注册开机广播接收器

<receiver
    android:name=".BootCompletedReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        <!-- 加这个是为了兼容一些国产设备的快速开机广播,避免漏触发 -->
    </intent-filter>
</receiver>

注册前台服务

<service
    android:name=".BootStartService"
    android:foregroundServiceType="dataSync"
    android:exported="false" />

这里的foregroundServiceTypedataSync就够了,完全符合开机启动的场景。

三、写广播接收器的逻辑

这个接收器的作用特别简单:收到开机广播后,立刻启动前台服务,绝对不能在这里直接启动MainActivity!Android 14会直接拦你,连个报错提示都不给。

class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // 判断是不是开机相关的广播
        if (Intent.ACTION_BOOT_COMPLETED == intent.action || Intent.ACTION_QUICKBOOT_POWERON == intent.action) {
            // 启动前台服务
            val serviceIntent = Intent(context, BootStartService::class.java)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(serviceIntent)
            } else {
                context.startService(serviceIntent)
            }
        }
    }
}

四、前台服务里启动MainActivity

这才是关键!因为前台服务属于“前台状态”,系统允许它启动Activity。我们在服务里先搞定通知(必须步骤),再启动MainActivity。

class BootStartService : Service() {
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // 第一步:创建通知渠道和通知,Android 8.0及以上必须
        val channelId = "boot_start_channel"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "开机启动通知",
                NotificationManager.IMPORTANCE_HIGH
            )
            val notificationManager = getSystemService(NotificationManager::class.java)
            notificationManager.createNotificationChannel(channel)
        }
        // 构建通知,记得换成你自己的应用图标
        val notification = NotificationCompat.Builder(this, channelId)
            .setContentTitle("我的应用正在启动")
            .setContentText("马上打开主页面啦")
            .setSmallIcon(R.mipmap.ic_launcher)
            .build()
        // 启动前台服务,绑定通知
        startForeground(1, notification)

        // 第二步:启动MainActivity,必须加FLAG_ACTIVITY_NEW_TASK标记
        val activityIntent = Intent(this, MainActivity::class.java)
        activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        startActivity(activityIntent)

        // 启动完Activity就可以停止前台服务和自身了
        stopForeground(STOP_FOREGROUND_REMOVE)
        stopSelf()

        return START_NOT_STICKY
    }

    override fun onBind(intent: Intent?): IBinder? = null
}

五、别忘了动态申请通知权限

Android 13及以上,通知权限是需要用户手动授权的,所以第一次打开应用时,要主动申请这个权限,不然前台服务的通知发不出去,服务启动失败,Activity也启动不了。

在MainActivity里加这段逻辑:

class MainActivity : AppCompatActivity() {
    private val NOTIFICATION_PERMISSION_REQUEST_CODE = 1001

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 检查并申请通知权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.POST_NOTIFICATIONS
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.POST_NOTIFICATIONS),
                    NOTIFICATION_PERMISSION_REQUEST_CODE
                )
            }
        }
    }

    // 处理权限申请结果
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == NOTIFICATION_PERMISSION_REQUEST_CODE) {
            if (grantResults.isNotEmpty() && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(
                    this,
                    "请开启通知权限哦,不然开机自动启动功能用不了~",
                    Toast.LENGTH_LONG
                ).show()
            }
        }
    }
}

几个必须踩的坑(哦不,必须注意的点!)

  • 应用必须被用户手动打开过至少一次:Android 10及以上,系统只会给用户主动打开过的应用发送开机广播,刚安装完直接重启设备,应用是收不到广播的!
  • 绝对不能直接在广播接收器里启动Activity:Android 14的后台启动限制非常严,这么做100%会被系统拦截,连日志都可能不给你打。
  • 测试技巧:不用每次都真的重启设备,用adb命令模拟开机广播就行,终端里输入:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED -n 你的应用包名/.BootCompletedReceiver

把“你的应用包名”换成你自己的包名(比如com.example.mybootapp),就能快速测试效果了。

内容来源于stack exchange

火山引擎 最新活动