android framework之旅(三)编译调试单个模块
在开发过程中,我们需要不断修改代码,并进行调试,而源码的整体编译耗时太长,我们不可能每次测试的时候都要重新生成镜像,重新烧系统,那我估计人会发疯的,所以这两天研究了下怎么单独编译模块并push到真机看到效果,过程还是比较曲折的,记录一下~
环境
操作系统:ubuntu 16.04
开发板:NanoPC T3
源码版本:5.1.1
编译单个模块
为了验证我们的工作,我在Laucher的onCreate方法中加了这么一句话:
System.out.println("test tag add by lxf");
首先还是初始化环境和选择目标版本:
source build/envsetup.sh
lunch <自己要编译的版本>
执行初始化之后在当前目录我们可以得到一些其他指令,比较常用的就是mm和mmm指令(其实是我只用过这两个),mm表示编译当前目录,mmm表示编译指定目录,只要目录下又Android.mk文件即可。
比如我们编译桌面模块(我使用开发板的桌面为Launcher2,有的为Launcher3):
mmm packages/apps/Launcher2/
编译过程中会提示你具体的生成目录:
...
Install: out/target/product/nanopi3/system/priv-app/Launcher2/Launcher2.apk
...
Install: out/target/product/nanopi3/system/priv-app/Launcher2/arm/Launcher2.odex
odex文件简单来说就是android为了优化启动速度而将classes.dex文件提取出来的一个产物,详情可以参考百度百科。我们知道classes.dex文件是由java文件编译后打包而成的,因为我并没有修改res文件,所以我就只把odex文件push到手机对应目录,发现然并卵,又把odex和apk文件都push进去,依然看不到我想要的效果。
无奈开始上网求助,发现各种教程都是直接push生成的apk,于是开始找不生成odex的编译方法,于是发现了这个:
解决方法:
1.不生成odex,只生成apk,将 LOCAL_DEX_PREOPT 的值改为 false 即可。
即 build\core\package.mk 中156行改为 LOCAL_DEX_PREOPT := false。
照上述修改后,全部重新编译,后续就可以mm单独编译apk方便调试了。
2.如果时间紧,又不想全编重新编译怎么办?
在相应的apk代码路径的Android.mk文件中加入WITH_DEXPREOPT := false。
添加后mm重新编译生成apk即可。
第一种方法我没有尝试,因为我不想全部重新编译,渣电脑太费时间了;第二种方法尝试了下但编译不成功,提示错误:
build/core/main.mk:528: WITH_DEXPREOPT has been modified: false
build/core/main.mk:528: previous value: true
build/core/main.mk:528: *** The following variables have been changed: WITH_DEXPREOPT。 停止。
于是只能另谋出路,最终在外文网上找到这么一条指令:
mm WITH_DEXPREOPT=false
测试成功,只生成了原始的apk文件,并没有抽取生成odex,将开发板对应目录下的odex和apk文件都删除后,将该apk文件push进去,重启看到如下日志:
04-20 07:20:36.600 523-523/com.android.Launcher2 I/System.out: test tag add by lxf
如果无法删除开发板系统文件并提示为只读权限,可以使用如下命令将开发板重新挂载为可读写模式:
adb remount
Push到设备
最后附上push相关的所有命令:
adb remount
adb shell rm system/priv-app/Launcher2/Launcher2.apk
adb shell rm -r system/priv-app/Launcher2/arm
adb push /home/lxf/Launcher2.apk system/priv-app/Launcher2
adb reboot