Android 13(API>26)解锁/重启后启动服务方案咨询
Android 13 设备解锁后自动执行任务的实现方案
方案一:动态注册解锁广播 + 开机广播触发初始化
该方案解决了API 26+无法在Manifest中注册隐式广播的限制,同时通过开机广播确保设备重启后能重新注册解锁广播,无需用户手动启动应用。
步骤1:声明必要权限
在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- 启动前台服务需添加以下权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ 通知权限 -->
步骤2:Manifest注册开机广播接收器
ACTION_BOOT_COMPLETED是API 26后少数允许在Manifest中注册的广播之一:
<receiver android:name=".BootCompletedReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> <!-- 适配部分厂商快速开机逻辑 --> </intent-filter> </receiver>
步骤3:实现开机广播接收器,动态注册解锁广播
收到开机广播后,立即注册ACTION_USER_PRESENT(设备解锁广播):
class BootCompletedReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (Intent.ACTION_BOOT_COMPLETED == intent.action || "android.intent.action.QUICKBOOT_POWERON" == intent.action) { // 注册设备解锁广播 val userPresentReceiver = UserPresentReceiver() val filter = IntentFilter(Intent.ACTION_USER_PRESENT) context.registerReceiver(userPresentReceiver, filter, Context.RECEIVER_EXPORTED) // 可选:开机完成后直接执行一次任务 scheduleTask(context) } } }
步骤4:实现解锁广播接收器,触发任务/服务
用户解锁设备时,触发任务执行逻辑:
class UserPresentReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (Intent.ACTION_USER_PRESENT == intent.action) { // 启动前台服务执行任务(或调度WorkManager) startForegroundService(context) } } private fun startForegroundService(context: Context) { val serviceIntent = Intent(context, TaskService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(serviceIntent) } else { context.startService(serviceIntent) } } }
步骤5:实现前台服务,执行任务后自动销毁
任务完成后立即停止服务,避免持续耗电:
class TaskService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // 创建前台通知(Android 8+ 强制要求) val notification = NotificationCompat.Builder(this, "task_channel") .setContentTitle("执行任务中") .setContentText("正在完成指定操作") .setSmallIcon(R.drawable.ic_notification) .build() // 创建通知渠道(Android 8+ 必须) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( "task_channel", "任务执行通知", NotificationManager.IMPORTANCE_LOW ) getSystemService(NotificationManager::class.java).createNotificationChannel(channel) } startForeground(1, notification) // 执行具体任务逻辑 executeTask() // 任务完成后停止服务 stopForeground(STOP_FOREGROUND_REMOVE) stopSelf() return START_NOT_STICKY } private fun executeTask() { // 替换为你的实际任务代码,如数据同步、文件处理等 Thread.sleep(3000) // 模拟任务耗时 } override fun onBind(intent: Intent): IBinder? = null }
方案二:WorkManager + 触发式任务调度
若不想依赖应用进程存活,可使用WorkManager调度任务,通过广播触发执行,系统会自动处理进程拉起逻辑。
步骤1:实现Worker类
class TaskWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { // 执行任务逻辑 executeTask() return Result.success() } private fun executeTask() { // 具体任务代码 Thread.sleep(3000) } }
步骤2:在解锁广播中调度任务
修改UserPresentReceiver的onReceive方法,替换为WorkManager调度逻辑:
private fun scheduleTask(context: Context) { val constraints = Constraints.Builder() .setRequiresDeviceIdle(false) .setRequiresCharging(false) .build() val workRequest = OneTimeWorkRequestBuilder<TaskWorker>() .setConstraints(constraints) .build() WorkManager.getInstance(context).enqueue(workRequest) }
关键注意事项
- Android 13+ 通知权限:前台服务需要
POST_NOTIFICATIONS权限,需在代码中主动申请用户授权。 - 进程存活限制:动态注册的广播依赖应用进程,若进程被系统杀死,广播会失效,开机广播会在设备重启后重新注册。
- 电池优化与厂商限制:部分国产厂商后台管控严格,需引导用户开启应用的「自启动权限」并加入电池优化白名单,确保广播正常接收。
内容的提问来源于stack exchange,提问作者tinyestgrape
相关产品推荐
相关产品推荐

