前言
在 Android 14.0 设备定制中,遇到一个开机自启动第三方 APK 的需求:设备开机后自动拉起客制化 APP,且不能因为切换语言、修改字体大小、更换默认壁纸等系统设置而重复启动。通过在launcher中定义自启动app的方法基本上都会遇到修改系统设置时,再次去换起第三方apk的bug
最终在frameworks\base\packages\SystemUI\src\com\android\systemui\SystemUIService.java
服务中添加延迟启动方法修复bug
下面列举了所有试错方案和思路转换,从问题出现 → 多次踩坑 → 崩溃进 Recovery → 最终稳定方案,完整复盘整个实战过程。
一、需求与初始问题
1.1 需求
- Android 14.0 系统开机自启动第三方客制 APK
- 重启设备能正常自启
- 修改语言、字体大小、壁纸等系统设置不重复自启
1.2 最初实现(有问题)
在 Launcher 的 onCreate 中调用自启动方法:
startAppByPackageName(packageName);
1.3 第一个坑:系统设置一修改,APP 就重启
现象:
- 切换系统语言
- 修改字体大小 / 显示大小
- 修改默认壁纸
都会导致:Launcher 进程重启 → 重新走 onCreate → 自启动逻辑再次执行 → APP 被重复拉起
原因:这些操作属于系统全局配置变化,系统会重建 Launcher,并非真正的设备重启。
二、第一轮尝试:各种方案踩坑
2.1 方案 1:通过 ro.boot.id 判断只在真正开机时启动
思路:读取系统属性 ro.boot.id,认为只有冷开机才执行自启。
结果:第一次刷机后根本不自启,属性判断时机不对。
2.2 方案 2:监听开机广播 BOOT_COMPLETED
思路:只在收到开机广播时自启,避开 Launcher 重建。
结果:
- 修改系统设置不再重复自启 ✔
- 但只有刷机 / 恢复出厂第一次能自启
- 设备重启后无法自启 ❌
三、第二轮尝试:换位置实现自启
既然 Launcher 不行,尝试放到系统更底层:
3.1 尝试放到 PhoneWindowManager
- 开机广播中启动 APP
- 能解决设置变更不重复自启 ✔
- 但出现新问题:点击返回键会优先跳回客制 APP ❌
3.2 尝试放到 Activity 的 finish 逻辑
同样出现:页面返回、跳转都会被强行拉回客制 APP,严重影响体验。
3.3 最终放到 SystemUIService
frameworks\base\packages\SystemUI\src\com\android\systemui\SystemUIService.java
在 SystemUIService.java 的 onCreate 中直接启动:
Intent intent = new Intent();
intent.setComponent(new ComponentName(pkg, cls));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
表面效果很好:
- 重启能自启 ✔
- 修改系统设置不重复自启 ✔
但埋下超级大坑。
四、致命问题:多次重启 → 直接进 Recovery
4.1 客户反馈现象
- 正常使用没问题
- 连续手动重启设备几次
- 设备直接进入 Recovery 模式
- 提示:需要清除 data 分区才能进系统
4.2 日志分析(关键)
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.systemui
java.lang.RuntimeException: Unable to create service com.android.systemui.SystemUIService
Caused by: ActivityNotFoundException
4.3 根本原因(非常重要)
-
SystemUI 启动时机 早于 PMS 扫描
- SystemUI 是系统核心服务,启动极早
- PMS(PackageManagerService)还没扫描完
/system/priv-app - 此时启动客制 APP → Activity 不存在
-
空指针 / 异常导致 SystemUI 崩溃
-
系统触发 RescueParty 机制
- 核心进程连续崩溃达到阈值
- Android 判定系统损坏
- 强制进入 Recovery,要求清 data
这是 Android 系统的自我保护机制。
五、最终稳定方案:延迟启动 + 重试机制
5.1 核心思路
- 自启动逻辑放在 SystemUIService
- 不直接在 onCreate 启动
- 使用 Handler 延迟 + 重试,等 PMS 扫描完成
- 全 try-catch 保护,绝对不让 SystemUI 崩溃
5.2 最终代码(可直接使用,修改ComponentName里为你自己apk的包名类名)
\frameworks\base\packages\SystemUI\src\com\android\systemui\SystemUIService.java

// 放在 SystemUIService 的 onCreate 中
// Bind the dump service so we can dump extra info during a bug report
startServiceAsUser(
new Intent(getApplicationContext(), SystemUIAuxiliaryDumpService.class),
UserHandle.SYSTEM);
//czq Start Amicus MainActivity with delay and retry mechanism
mMainHandler.postDelayed(new Runnable() {
private int mRetryCount = 0;
private static final int MAX_RETRY_COUNT = 5;
private static final long RETRY_DELAY_MS = 3000; // 3秒重试一次
@Override
public void run() {
try {
Slog.e(SystemUIApplication.TAG, "Attempting to start Amicus MainActivity (retry " + mRetryCount + ")");
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.xxx.xxx", "com.xxx.xxx.MainActivity"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Slog.e(SystemUIApplication.TAG, "Successfully started Amicus MainActivity");
} catch (ActivityNotFoundException e) {
Slog.e(SystemUIApplication.TAG, "start com.butterfly.amicus.MainActivity fail:target Activity does not exist", e);
if (mRetryCount < MAX_RETRY_COUNT) {
mRetryCount++;
Slog.e(SystemUIApplication.TAG, "Retrying to start Amicus MainActivity in " + RETRY_DELAY_MS + "ms (attempt " + mRetryCount + "/" + MAX_RETRY_COUNT + ")");
mMainHandler.postDelayed(this, RETRY_DELAY_MS);
} else {
Slog.e(SystemUIApplication.TAG, "Max retry count reached. Giving up on starting Amicus MainActivity");
}
} catch (Exception e) {
Slog.e(SystemUIApplication.TAG, "start com.butterfly.amicus.MainActivity fail ", e);
}
}
}, 5000); //czq end 初始延迟5秒,给系统足够的启动时间
5.3 为什么这样写能解决所有问题
-
延迟 5s 启动给 PMS 足够时间扫描 priv-app
-
重试机制第一次找不到就等 3s 再试,最多试 5 次
-
全面异常捕获绝对不抛出异常 → SystemUI 不崩溃 → 不触发 RescueParty
-
放在 SystemUI不受 Launcher 重建影响 → 修改语言 / 壁纸 / 字体都不会重复自启
六、最终效果(全部满足)
- ✅ 设备重启 → 正常自启
- ✅ 刷机第一次开机 → 正常自启
- ✅ 恢复出厂 → 正常自启
- ✅ 切换语言、字体大小、壁纸 → 不重复自启
- ✅ 多次重启设备 → 不会进 Recovery
- ✅ SystemUI 稳定不崩溃、不异常
七、实战总结(非常关键)
-
不要在 Launcher onCreate 做开机自启系统设置变更会重建 Launcher,导致重复自启。
-
不要在核心服务 onCreate 直接启动第三方 APPPMS 还没扫描完,会报 Activity 不存在。
-
SystemUI 绝对不能崩溃崩溃多了直接触发 RescueParty 进 Recovery。
-
开机自启最稳方案SystemUIService + 延迟 + 重试 + 全 try-catch
八、常用抓包日志命令
adb logcat -v time SystemUI:E *:S
adb logcat -v time *:E | findstr /i "systemui fatal androidruntime caused by"