android|android framework 调试方法(快速编译+利用ide特性)

起因(此方法只适用于没有做odex优化的版本.比如eng,user需要禁止odex优化)
目前公司framework层的工作一直比较麻烦,具体做法是在linux下直接用SourceInsight编辑,然后mm编译framework模块.编辑也没个智能提示,语法检查之类的,最主要framework这么庞大的东西,编起来也麻烦.处理一个问题,往往要多次mm.浪费时间,效率低,试想在竞争如此激烈的今天,效率低下是不能容忍的.
过程 android编译过程
先来看张图吧,了解一下android project的编译过程
android|android framework 调试方法(快速编译+利用ide特性)
文章图片


图里没什么重点,最重要的就是java class file 会通过dx 转换为android 自己设计的dex文件. 这个是快速编译和调试的基础.
编译过程总是先得到class文件,然后转换成dex,最后再做签名对齐等操作.可以看到class才是实质,其它的都是点缀而已,如果我们修改了*.java代码,最先变动的是class文件.
打个比方,我改动了PackageManagerService.java.那么首先是根据我修改的java代码生成新的PackageManagerService.class,然后才是转换为dex格式的services.jar包.
如果我们要修改service.jar里的PackageManagerService,只要得到PackageManagerService.java修改后对应的class文件即可.是不是很简单.有了这个class文件,
之后的转dex格式,签名什么的就易如反掌了.搞过java的都知道,class是java代码的目标文件,里面存放的是java byte code.直接在虚拟机里的可执行代码.


得到class文件
好吧,到这里,可以新建一个java项目,目的是为了得到修改framework的class文件.现在是在eclipse下开发,所以能够用上ide的特性了.


首先会发现很多符号找不到的错误,具体一点就是没有代码里需要的架包.
不妨再看看我们普通的一个android项目吧,里面都有一个android.jar的架包,打开这个架包发现里面都是class文件(见下图).这货很明显就是一个java library jar.
android|android framework 调试方法(快速编译+利用ide特性)
文章图片


我们apk代码里很多的import都是来自这里的.有了架包,那些找不到符号的错误都可以烟消云散了


说道架包,android源码编译的时候会在out/target/common/obj/JAVA_LIBRARIES目录下生成很多jar包.这里有我们需要的架包文件(文件夹就是架包名,架包都是class-full-debug.jar),用到了哪个就拷贝哪个.
这里我列一下必备的几个:

android-common_intermediates android.policy_intermediates core_intermediates framework_intermediates services_intermediates

还有注意加上sdk下面的android.jar 【android|android framework 调试方法(快速编译+利用ide特性)】其它的,可以自己添加,需要什么找什么



替换class文件
这个简单说一下,用winrar或者7-zip打开需要修改的jar包,例如service.jar(这个是架包,在手机里不可用.手机里可用时需要dx tools处理的),把我们编译好的class文件替换原有的就ok了,命令行下可以用7-zip来做方便快捷, 一条zip.exe a classfile or dir target.jar命令搞定. 生成dex格式文件
这个也简单,详见dx tool.装了sdk 和 adt的在命令行下dx看一下参数. for example 我这里以packagemanagerservice.java举例:
先看看java项目的基本配置
android|android framework 调试方法(快速编译+利用ide特性)
文章图片


src之上都是需要的架包,src下的包名与要修改的架包下的同名class路径一致.
我在PackageManagerService.java里添加了一行log代码

public ApplicationInfo getApplicationInfo(String packageName, int flags) { // writer synchronized (mPackages) { Log.v( TAG, "getApplicationInfo " + packageName + ": " + " add by chenxuesong"); //加上了本人的大名 PackageParser.Package p = mPackages.get(packageName); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getApplicationInfo " + packageName + ": " + p); if (p != null) { // Note: isEnabledLP() does not apply here - always return info return PackageParser.generateApplicationInfo(p, flags); } if ("android".equals(packageName)||"system".equals(packageName)) { return mAndroidApplication; } if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { return generateApplicationInfoFromSettingsLPw(packageName, flags); } } return null; }


clean 一下 project生成class文件.
android|android framework 调试方法(快速编译+利用ide特性)
文章图片


PackageManagerService不愧是核心服务,好多class文件
替换class文件,一条命令搞定
android|android framework 调试方法(快速编译+利用ide特性)
文章图片


该生成我们手机上能执行的文件了,(转化成dex格式)也是一条命令搞定
android|android framework 调试方法(快速编译+利用ide特性)
文章图片


把这个生成的servicesdex.jar改名为services.jar并push到手机上,然后reboot.抓取日志,发现生效了
这里要提一下,这些架包都是需要签名的,不过可以用我之前的方式和谐掉,替换一下libdvm.so.一劳永逸.
具体可以看一下链接
framework修改无法重启

android|android framework 调试方法(快速编译+利用ide特性)
文章图片




注意事项 1.jdk的版本需要1.6,1.7生成的class在dx生成dex格式的时候会提示 Dx bad class file magic (cafebabe) or version (0033.0000)2.架包的顺序也很重要,可以自己在右键build path里手动调整. 3.有时候换了jdk1.6还是失败,需要手动设置一下eclipse的jdk版本 window-preference-java-compiler如果还不行就设置一下project project-properties-java compiler.
结尾 后续会出一个批处理文件的版本和mfc下的ui界面,方便使用


    推荐阅读