最近履新任职到新公司,刚到 +1 给我安排了一个他口中 “地狱难度” 任务,从 AOSP 把 Settings 模块剥离到 Android Studio 能独立运行独立打包 APK。
接到这个任务我确实是蒙的,刚来环境还没熟悉给我安排一个这么高难度的任务,但是转念一想如果要在舒适区也不会来现在这个公司了,我就当是我入职试用期的考核,不成功便成仁,硬头皮接下来了。
之前做系统应用开发一般都是拾人牙慧,都是别的团队摘好了解耦完毕的,属于是前人栽树后人乘凉,今天我也要做一把这个前人了。
先来看阶段性的效果吧
通过上图我们已经能看到 从 AOSP 剥离的 settings 模块已经解耦能跑起来独立 apk,页面也拉起来了。
- 拆解的意义
解耦的事情比较难做,但是我们还在做,那做了好处和回报在哪儿呢?
| 对比维度 | 原生 AOSP 内置 Settings | 解耦独立版 Settings APK | 拆解 / 解耦的核心价值 |
|---|---|---|---|
| 编译与开发效率 | 必须完整 AOSP 环境、全源码编译;修改后常需重刷系统 | 可在普通 Android Studio 工程独立开发 / 编译;秒编译、秒安装调试 | 开发效率提升 10~50 倍,脱离巨型源码树 |
| 版本升级与迭代 | 只能随系统 OTA 升级;不能单独热更 / 覆盖 | 可像普通 App 一样单独升级、覆盖安装、灰度发布 | 迭代速度极快,Bug / 功能不依赖系统版本 |
| 跨 Android 版本兼容 | 强绑定对应 API Level,跨版本基本不可用 | 一套代码可适配多 Android 版本(10~14),接口做兼容层 | 一次开发多版本复用,大幅减少维护成本 |
| 定制与扩展能力 | 深度耦合系统隐藏 API、internal 类、Framework 私有接口 | 解耦后通过标准 SDK API + 桩库 / 兼容层实现系统能力 | 定制更安全、更可控,不污染系统源码 |
| 交付与部署方式 | 只能内置到 system.img;无法单独分发 | 可作为独立 APK 预装 / 下载安装;支持多设备 / 多项目复用 | 灵活交付:厂商预装、企业 MDM、第三方设备都可用 |
| 代码解耦与稳定性 | 与 SystemUI、Framework、其他系统 App 强耦合 | 边界清晰、依赖明确;问题只在本模块内,不扩散 | 稳定性更高、问题易定位,改一处不牵一发而动全身 |
| 权限与安全 | 必须 platform 签名、系统权限;易被系统升级覆盖 | 可自定义包名(如 com.oem.settings)、独立签名;不被系统覆盖 | 安全可控、防覆盖,适合企业 / 定制场景 |
| 适用场景 | 仅原生 AOSP / 官方 ROM 使用 | OEM 定制、车机 / 电视 / 平板、行业设备、企业 MDM、第三方 ROM | 场景全覆盖,从手机到 IoT 都能用 |
| 系统裁剪与瘦身 | 必须保留在 /system 分区,占用空间 | 可移至 /product、/vendor 或不预制,按需安装 | 支持系统轻量化裁剪,释放空间 |
- 拆解的难度
| 难度等级 | 难点 | 为什么难 | 后果 |
|---|---|---|---|
| ⭐⭐⭐⭐⭐ | 大量依赖 @hide 隐藏 API /framework 内部接口 | 官方 SDK 没有,反射不稳定,版本碎片化严重 | 代码跑不起来、功能残缺、高版本闪退 |
| ⭐⭐⭐⭐⭐ | 强依赖 系统签名 & 系统权限 | 普通 APK 拿不到 android.permission.WRITE_SECURE_SETTINGS 等 | 大部分设置项点击无效、闪退 |
| ⭐⭐⭐⭐ | 依赖系统私有类:com.android.internal.* | 非公开 API,各厂商 ROM 都不一样 | 编译不过、运行异常 |
| ⭐⭐⭐⭐ | 与 SystemUI、SystemServer、SettingsProvider 深度耦合 | 广播、服务、ContentObserver 互相绑定 | 亮度、音量、网络、账户功能异常 |
| ⭐⭐⭐ | 依赖 AOSP 编译系统(Soong / Android.bp/ Ninja) | 无法直接在 AS 编译,依赖路径复杂 | 无法打成独立 APK |
| ⭐⭐⭐ ⭐⭐ | 资源冲突、包名冲突、R 类冲突 | 系统资源 com.android:id/ 无法访问 | 布局错乱、崩溃 |
| ⭐⭐ | 多设备适配(手机 / 平板 / 车机) | 不同设备资源、条件编译不同 | 界面错乱、功能缺失 |
| ⭐⭐ | 依赖系统内置服务(网络、蓝牙、NFC、账户) | 普通三方 App 无权限调用 | 对应设置项不可用 |
- 环境
LineageOS(源码)
breakfast akita (设备)
-
拆解的知识储备
需要较强的
- Settings
- Gradle
- .kts
- kotlin
- protocl buffer
- .bp
- 依赖注入(annotationProcessor)
- aconfig
- aidl
等知识储备,以及海量的文件 module 的依赖解耦关系处理。
-
拆解思路
-
总体原则
1 先解决 gradle 等依赖和静态检查问题
2 再解 run 工程不过报错的问题
3 最后解决运行时 crash 问题
-
具体实施
-
Settings 独立建仓 ,创建一个空工程,确认 gradle 版本 , 构建 toml 编写通用依赖 androidx kotlin 等
-
创建 app 主 module , 移植 /android/lineage/packages/apps/Settings 的 src res libs protos 到其中
-
解构 settingsLib ,settingsLib 在 /android/lineage/frameworks/base/packages/SettingsLib 目录,该包包含 58 个子 module 需要处理 58 个 module 的依赖关系 ,子module中还存在子嵌套,初步先完成 58 个子 module .bp to .gradle 构建,找不到的依赖先注释
-
/lineage/external/setupcompat(开机向导)
-
/lineage/external/setupdesign(开机向导)
-
Iconloaderlib (launcher3)
-
Wmshellshared (wmshell)
-
Wifitrackerlib (WIFI)
-
需要完成 Android resource linking failed 的修复,存在大量的 resource 资源缺失分为三类:
A androidPrv 类
B @android: 报错 is private
C Not found 资源类
style color strings dimen drawable attr 共计约上千处私有报错完成对其平替或者注释不影响编译
-
大量私有 style 平替成 material style
-
其他:
apk 在 系统中的位置
/android/lineage/out/target/product/akita/system_ext/priv-app/Settings
framework.jar 在系统整编后的位置
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates
out/target/common/obj/JAVA_LIBRARIES/framework-minus-apex_intermediates
签名用 AOSP debug 签名
处理完上述 10 个问题 apk 基本能正常 build 其中资源问题花了我两天时间,解耦的难点也在考验毅力和耐心,因为你在不停的解决报错,这个解决后下面还有无穷无尽的报错等你处理,比较考验心态的是这个无底洞不不知道什么时候才算解决完毕,可能解决下一个就完成了,也可能后续还有999+报错等着你,但是自己有耐心毅力再加上现在有AI的辅助,一定是可以成功。