重新回到最本源的需求:
- 开机自启(10s 内)。
- 防退出(无论几十个 Activity 怎么跳转,都不能退到桌面)。
- 保留原生 Launcher,工程模式鉴权后能正常使用原生桌面。
- 稳定、简单、容易落地。
其实,Android 系统原生就自带了专门解决这个场景的标准机制,根本不需要改动几百行 Framework 代码。以下为您提供一套极简、稳定、符合 Android 原生设计哲学的极轻量级方案。
极简核心思路:动态角色切换(Launcher 替换法)
核心秘密:Android 系统的“防退出”本质上就是不让用户回到别的桌面。 那么,让“具微遥控 APP”自己变成“系统默认桌面(Launcher)”,问题瞬间全部解决!
- 当你是桌面时,用户按 Home 键?回到你自己。
- 用户有几十个 Activity,狂按 Back 键把所有页面都 finish 完了?系统自动重新打开桌面(也就是你自己)。
- 根本不需要拦截 Back 键,不需要管有几十个还是几百个 Activity,因为栈空了系统天然就会回到当前桌面。
- 开机自启?Android 开机第一个启动的就是默认桌面,天然秒开,无需任何开机广播。
- 怎么进入原生桌面?代码动态切换默认桌面,一秒搞定。
方案具体实现(只需 3 步,零 Hack)
第一步:在 AndroidManifest.xml 中声明为 Home(桌面)
让具微遥控的 MainActivity 具备 Launcher 属性。
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!-- 核心:声明自己是桌面 -->
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
效果:系统原生支持多桌面。开机时,系统会直接拉起默认桌面。
第二步:ROM 出厂配置(仅需配置 1 个系统默认项)
因为设备上同时存在“原生 Launcher”和“具微遥控”,系统首次开机需要知道默认选谁。
在 ROM 源码的 frameworks/base/core/res/res/values/config.xml 中(或者通过 Overlay),指定具微遥控为开机首选桌面:
<!-- 将系统默认 Preferred Launcher 指向具微遥控 -->
<string name="config_customResolverActivity" translatable="false">com.remote.control/.ui.MainActivity</string>
(或者更标准的 AOSP 做法:在出厂 settings 数据库 frameworks/base/packages/SettingsProvider/res/values/defaults.xml 中把默认 Home 设置为 com.remote.control)。
效果:
- 开机自启:开机后 SurfaceFlinger 就绪,系统第一个渲染的就是具微遥控,3~5 秒直达。
- 几十个 Activity 防退出:无论内部 Activity 怎么跳转、怎么崩、按多少次 Back/Home 键,退到最后一定是退回“默认桌面”(即具微遥控主页)。完全不用写任何栈管理代码!
第三步:工程模式退出与还原(极简 API 调用)
具微遥控作为 系统 APP (Priv-App),拥有调用 PackageManager 特权 API 的权限。
1. 密码/证书验证通过 -> 切到原生桌面
当在工程模式中鉴权成功,需要去原生桌面时:一行代码拉起原生 Launcher。
fun switchToNativeLauncher(context: Context) {
// 1. 找到系统原生 Launcher 的包名(例如 AOSP 的 Launcher3)
val nativeLauncherIntent = Intent(Intent.ACTION_MAIN).apply {
addCategory(Intent.CATEGORY_HOME)
setPackage("com.android.launcher3") // 指定原生 Launcher 包名
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
// 2. 直接启动原生桌面
context.startActivity(nativeLauncherIntent)
}
2. 从原生桌面返回App
在原生桌面上,点击应用图标,即可随时回到App。
补充:隐藏状态栏/下拉菜单(防误触)
为了防止用户从顶部下拉状态栏去点“系统设置”逃逸,在具微遥控的 BaseActivity 里加上标准的全屏沉浸即可:
// Android 11~16 标准沉浸式全屏,几行搞定
class BaseActivity : AppCompatActivity() {
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
val controller = WindowInsetsControllerCompat(window, window.decorView)
controller.hide(WindowInsetsCompat.Type.systemBars()) // 隐藏导航栏与状态栏
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
}
新旧方案终极对比
| 评估维度 | 上一版复杂方案 (Task/Framework/SELinux 改写) | 本版极简方案 (动态 Launcher 法) |
|---|---|---|
| AOSP 源码修改量 | 修改 ATMS、WMS、PWM、SELinux 等几十处代码 | 仅修改 1 行配置(指定默认桌面),不改 Framework 逻辑 |
| 多 Activity 支持 | 需写 BaseActivity 拦截、栈拓扑监听、Task 修复 | 天然支持,Android 系统把 App 当桌面,栈空自动回 App 主页 |
| 系统稳定性 | 极高风险引入系统级 Bug,阻碍 Android 版本升级 | 零风险,完全运行在 Android 原生设计的标准轨道上 |
| 开机启动速度 | 需做 Direct Boot 等复杂调优 | 秒开(Android 优先初始化并拉起默认桌面) |
| 维护成本 | 需专用系统工程师常驻维护 | 普通 Android 开发者 1 天内即可完成交付 |
结论
“把你做成系统默认 Launcher” 是 Android 工业级终端、车载中控屏、POS 机最经典、最稳定、代码量最少的做法。无需任何复杂黑科技,完全满足您的 PRD 需求。