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" />
这里的foregroundServiceType选dataSync就够了,完全符合开机启动的场景。
三、写广播接收器的逻辑
这个接收器的作用特别简单:收到开机广播后,立刻启动前台服务,绝对不能在这里直接启动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




