作为一名Android开发者,你可能遇到过这样的场景:系统默认的输入法不符合需求,或者想要预装一些自己的应用。这时候,定制系统镜像就显得尤为重要了。我最近在做一个智能家居项目,需要预装控制APP到系统中,这个过程让我深刻体会到定制系统镜像的价值。
定制系统镜像最大的好处就是可以完全掌控系统环境。你可以:
Android Studio的模拟器是个绝佳的测试平台。相比真机测试,模拟器可以快速验证修改效果,而且不用担心刷机变砖的风险。我在实际项目中发现,使用模拟器测试系统镜像,效率能提升3-5倍。
在开始之前,确保你的开发机满足以下要求:
我刚开始尝试时,用了一台8GB内存的笔记本,编译过程频繁卡死。后来换了32GB的台式机,编译时间从6小时缩短到1小时。所以硬件配置真的很重要。
获取源码有两种方式:
我推荐使用清华镜像,速度会快很多。具体命令如下:
bash复制mkdir ~/aosp
cd ~/aosp
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-12.0.0_r32
repo sync -j8
第一次同步源码可能需要几个小时,取决于你的网速。我在公司内网测试时,同步Android 12源码大约用了3小时。
源码下载完成后,需要设置编译环境:
bash复制source build/envsetup.sh
这个命令会加载一系列编译需要的环境变量和函数。我建议把这个命令加到你的.bashrc里,这样每次打开终端就不用重复执行了。
接下来是最关键的一步 - 选择编译目标:
bash复制lunch sdk_phone_x86_64
为什么选择sdk_phone_x86_64?因为Android Studio创建的模拟器默认就是这个架构。我刚开始尝试用aosp_x86_64-eng,结果生成的镜像在模拟器上跑不起来,浪费了一整天时间。
执行编译命令:
bash复制make -j$(nproc)
这里的-j参数指定并行编译任务数。我通常使用nproc自动获取CPU核心数。我的Ryzen 9 5900X有12核24线程,所以用-j24。
编译过程中可能会遇到各种错误。最常见的是内存不足,可以尝试减少-j参数的值。我在16GB内存的机器上通常用-j8。
编译完成后,镜像文件会生成在:
code复制out/target/product/emulator_x86_64/
关键镜像文件包括:
在Android Studio中创建模拟器时,要注意:
我习惯给模拟器命名带上日期,比如"Android12_x86_64_202306",方便管理多个版本。
找到模拟器的avd目录,通常在:
code复制~/.android/avd/<模拟器名称>.avd/
将编译生成的镜像文件复制到这里,并重命名:
注意:第一次运行时不要替换userdata.img,否则可能导致模拟器无法启动。
这个问题我遇到过好几次,通常是因为:
解决方案:
如果你修改了系统服务代码但没看到效果,可能是:
建议的编译命令:
bash复制make clean && make -j$(nproc)
对于单个模块,可以使用:
bash复制mmm frameworks/base/services/
有时候预装的应用在重启后会消失,这是因为:
确保在device.mk中添加:
code复制PRODUCT_PACKAGES += YourApp
要修改默认的系统属性,可以编辑:
code复制build/target/product/core_system.mk
比如修改默认时区:
code复制PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
persist.sys.timezone=Asia/Shanghai
如果你开发的应用需要系统权限,需要:
我在开发智能家居控制中心时,就遇到了需要系统权限才能控制硬件的问题,这个方案完美解决了。
编译时可以添加优化参数:
bash复制export TARGET_CPU_VARIANT=generic
export TARGET_ARCH_VARIANT=x86_64
make -j$(nproc) WITH_DEXPREOPT=true
这样生成的系统镜像运行速度会更快,但编译时间也会更长。我在开发机上测试,优化后的镜像启动时间缩短了约30%。
启动模拟器后,可以通过以下命令确认运行的是你编译的系统:
bash复制adb shell getprop ro.build.fingerprint
这个值应该和你编译时设置的版本一致。我习惯在编译前修改build/make/core/build_id.mk,加上自定义标识。
调试系统级修改时,日志非常重要:
bash复制adb logcat -b all -v threadtime > log.txt
我通常会配合grep过滤:
bash复制adb logcat | grep -i "your_tag"
使用Android Studio的Profiler工具可以分析系统性能:
我在优化系统服务时,就是通过Profiler发现了一个内存泄漏问题。
对于团队开发,建议设置自动化编译:
bash复制#!/bin/bash
repo sync -j8
source build/envsetup.sh
lunch sdk_phone_x86_64
make -j$(nproc) dist
可以将这个脚本放到Jenkins或GitHub Actions上,设置每日构建。我们团队现在就是每晚自动编译最新代码,第二天就能测试。
在最近的一个车载系统项目中,我们需要深度定制Android系统。通过修改frameworks/base/services/,我们实现了:
整个过程最大的收获是:一定要小步验证。每次修改后立即编译测试,不要等所有功能都开发完再测试。我吃过这个亏,一次提交了十几个修改,结果出了问题很难定位。
另一个建议是多使用git分支管理。我通常会:
这样即使某个功能开发失败,也不会影响其他工作。