Android 直接渲染本地二进制文件探究

编写: gubaozhen

1. 实现目标

1.用户将android工程中未经编译的assets、res文件夹拷贝至设备SD卡中,即可通过预览工具预览资源文件中配置的layout布局及动画.

2.需要解决的技术点
将明文的xml文件转成编译后的二进制文件
解决方案:改写aapt源码编译成一个提权后可以在非root手机上运行的二进制文件,从而实现手机端打包

当将二进制xml加载进来后,凡是涉及到外部引用的属性我们得到的只是一串ID,要根据这个ID找到正确的对应的值


2. 解决方案

android apk打包流程:

1、打包资源文件,生成R.java文件
2、处理aidl文件,生成相应java 文件
3、编译工程源代码,生成相应class 文件
4、转换所有class文件,生成classes.dex文件
5、打包生成apk
6、对apk文件进行签名
7、对签名后的apk文件进行对其处理

理解android资源编译打包及查找机制:

一个工程经过编译打包之后其values目录下的所有文件以及R.java都会被压到resources.arsc文件中,我们需要解析这个文件

打开resources.arsc会看到这样的内容(截取部分):

解析:

对应结构:
http://blog.csdn.net/luoshengyang/article/details/8744683

AAPT打包过程中会赋予每一个非assets资源一个ID值,这些ID值以常量的形式定义在一个R.java文件中。
将所有XML元素的标签、属性名称、属性值和内容所涉及到的字符串及18个维度的配置信息压缩到resources.arsc文件中,此文件用来描述那些具有ID值的资源的配置信息,它的内容就相当于是一个资源索引表。

通过文档读懂resources.arsc的结构后,自己去手写一个解析方案的成本无疑是巨大的。android本身的解析方案是写在native层的,难以复用。

目标转换到ApkTool工具上。
ApkTool是一个常用的反编译工具,其代码开源在https://github.com/iBotPeaches/Apktool

反编译APK必然要涉及到解析其中的资源文件,所以去研究ApkTool的源码后发现,其核心代码是用java写的,虽然并没有专门针对android平台,但是当我们改掉其中的apache引用包和一些不合适的api后可以移植到android上使用。

于是抽出并改写其中的resources.arsc解析逻辑后,我们便可以拿到对应的资源了。

在拿到资源表后,还要解决资源匹配的问题,android资源具有18个维度的配置:
见表2:
http://developer.android.com/intl/zh-cn/guide/topics/resources/providing-resources.html#DensityQualifier

当通过一个ID去加载资源时要根据当前手机配置去决定加载哪个维度的资源,资源匹配规则总结如下:

1.清除包含任何与手机配置有冲突的属性的资源文件夹,dpi相关、screen size不在范围内
2.选择手机配置中最高优先级的属性
3.有包含上述属性的文件夹吗? 如果没有,跳转步骤2,选择下一优先级高的属性;如果有,继续步骤4
4.清除不包含此属性的所有文件夹
5.重复步骤2和3,直到步骤4中只剩下一个文件夹则返回

通过以上方法我们已经可以拿到所有资源,并且通过ID和当前手机配置信息去找到合适的资源去加载。

接下来要去修正inflate出来的view以及动画中错误的属性值。
自定义view可以在其构造方法中解决。

系统view如RelativeLayout、ImageView等等需要去重写LayoutInflater类中相关的方法。

Animator则通过分析其对应的XmlResourceParser与AttributeSet的对应关系来解决。