在 Android 系统定制中,常见一个问题:某个预装应用没有注册 BOOT_COMPLETED 广播接收器,但产品要求它在设备开机后自动启动。
如果无法修改 APK(无源码、签名限制、第三方交付),可以在 Framework 层做兜底拉起。
一、需求背景
目标应用包名:
- com.longzhiye.custom
目标效果:
- 系统完成 BOOT_COMPLETED 分发后,自动启动该应用
- 仅在系统用户(USER_SYSTEM)执行,避免多用户重复拉起
二、改动总览
本次修改集中在:
- frameworks/base/services/core/java/com/android/server/am/UserController.java
核心改动有 3 个:
三、关键实现解析
1)新增常量配置
// Longzhiye app package to force-start after boot when APK has no BOOT_COMPLETED receiver.
private static final String BOOT_AUTO_LAUNCH_PACKAGE = "com.longzhiye.custom";
private static final long BOOT_AUTO_LAUNCH_DELAY_MS = 100;
说明:
- BOOT_AUTO_LAUNCH_PACKAGE:目标包名
- BOOT_AUTO_LAUNCH_DELAY_MS:延迟执行时间,避免与开机阶段任务抢占时序
2)插入 BOOT_COMPLETED 后触发点
mBootCompleted = true;
scheduleBootAutoLaunchApp(userId);
这一步非常关键:
在系统确认 BOOT_COMPLETED 处理完成后,进入自动拉起流程。
3)仅系统用户执行并延迟启动
private void scheduleBootAutoLaunchApp(@UserIdInt int userId) {
if (userId != UserHandle.USER_SYSTEM) {
return;
}
mHandler.postDelayed(() -> startBootAutoLaunchApp(userId), BOOT_AUTO_LAUNCH_DELAY_MS);
}
设计目的:
- 仅允许 USER_SYSTEM 执行,避免多用户重复触发
- 使用 postDelayed 让启动动作更平滑,减少开机瞬时冲突
4)启动逻辑与兜底处理
private void startBootAutoLaunchApp(@UserIdInt int userId) {
final Context context = mInjector.getContext();
try {
Intent launchIntent = context.getPackageManager()
.getLaunchIntentForPackage(BOOT_AUTO_LAUNCH_PACKAGE);
if (launchIntent == null) {
launchIntent = new Intent(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
launchIntent.setPackage(BOOT_AUTO_LAUNCH_PACKAGE);
}
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivityAsUser(launchIntent, UserHandle.of(userId));
Slogf.i(TAG, "Boot auto-launch: started " + BOOT_AUTO_LAUNCH_PACKAGE);
} catch (Exception e) {
Slogf.e(TAG, "Boot auto-launch: failed to start " + BOOT_AUTO_LAUNCH_PACKAGE, e);
}
}
实现要点:
- 优先使用 getLaunchIntentForPackage() 获取应用主入口
- 若返回空,回退为 ACTION_MAIN + CATEGORY_LAUNCHER
- 添加 FLAG_ACTIVITY_NEW_TASK,满足系统服务上下文启动 Activity 要求
- 使用 startActivityAsUser() 指定用户启动
- 全量异常捕获并记录日志,便于排查启动失败原因
四、方案优势
- 不改 APK:适合预装闭源应用
- 改动集中:只改 Framework 单一模块
- 可观测性强:有明确成功/失败日志
- 风险可控:用户过滤 + 延迟调度 + 异常兜底
五、注意事项
六、验证建议
开机后检查日志:
- 成功:Boot auto-launch: started com.longzhiye.custom
- 失败:Boot auto-launch: failed to start com.longzhiye.custom




