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

起因 

(此方法只适用于没有做odex优化的版本.比如eng,user需要禁止odex优化)

        目前公司framework层的工作一直比较麻烦,具体做法是在linux下直接用SourceInsight编辑,然后mm编译framework模块.编辑也没个智能提示,语法检查之类的,最主要framework这么庞大的东西,编起来也麻烦.处理一个问题,往往要多次mm.浪费时间,效率低,试想在竞争如此激烈的今天,效率低下是不能容忍的.哭

过程

android编译过程

        先来看张图吧,了解一下android project的编译过程

android framework 调试方法(快速编译+利用ide特性)_第1张图片

图里没什么重点,最重要的就是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 framework 调试方法(快速编译+利用ide特性)_第2张图片

我们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

其它的,可以自己添加,需要什么找什么敲打


替换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 framework 调试方法(快速编译+利用ide特性)_第3张图片

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 framework 调试方法(快速编译+利用ide特性)_第4张图片

PackageManagerService不愧是核心服务,好多class文件惊恐

替换class文件,一条命令搞定

android framework 调试方法(快速编译+利用ide特性)_第5张图片

该生成我们手机上能执行的文件了,(转化成dex格式)也是一条命令搞定


把这个生成的servicesdex.jar改名为services.jar并push到手机上,然后reboot.抓取日志,发现生效了微笑

这里要提一下,这些架包都是需要签名的,不过可以用我之前的方式和谐掉,替换一下libdvm.so.一劳永逸.

具体可以看一下链接

framework修改无法重启

android framework 调试方法(快速编译+利用ide特性)_第6张图片


注意事项

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界面,方便使用 得意


你可能感兴趣的:(android framework 调试方法(快速编译+利用ide特性))