AndroidManifest解析
来源:互联网 发布:大数据 架构 编辑:程序博客网 时间:2024/06/05 15:01
第一、头部信息
1、文件魔数:四个字节
2、文件大小:四个字节
第二、String Chunk(存放文件中所有字符串信息)
1、ChunkType:stringchunk类型:0x001c0001
2、chunksize:stringchunk大小:四个字节
3、stringcount:stringchunk中字符串个数,四个字节
4、stylecount:stringchunk样式的个数,四个字节,实际解析中该值为0
5、unknown:未知区域,四个字节,解析过程中需要略过
6、stringpooloffset:字符串池的偏移值,四个字节,是相对于stringchunk头部位置的
7、stylepooloffset:样式池的偏移值,四个字节,这里没有style,所以该字段可忽略
8、stringoffsets:每个字符串的偏移值,所以他的大小应该是:stringcount*4字节
9、styleoffsets:每个样式的偏移值,所以他的大小应该是stylecount*4个字节
后面就开始是字符串内容和样式的内容了。
代码解析:
1、首先把androidmanifest.xml文件读到一个byte数组中;
2、解析头部信息;
3、解析StringChunk信息;
注意:
0.一个字符对应两个字节时,还是开始的两个字节是字符串的长度;
1.四个字节的unknown字段需要略过;
2.在解析字符串内容的时候,字符串内容的结束符是:0x0000;
3.每个字符串开始的前两个字节是字符串长度;
4.用一个全局的字符列表存储这些字符串的值,后面会用索引来获取这些字符串的值。
//就用了stringpooloffset?!byte[] firstStringSizeByte=Utils.copy(chunkStringContentByte,0,2);//读取第一个字符串大小int firstStringSize=Utils.byte2short(firstStringByte)*2;//把结束符也读进去byte[] firstStringContentByte=Utils.copyByte(chunkStringContentByte,2,firstStringSize+2);stringContentList.add(Utils.filterStringNull(firstStringContent));//所有的字符串都放到stringContentList中int endStringIndex=2+firstStringSize+2;while(stringContentList.size()<chunkStringCount){ int stringSize=Utils.byte2short(Utils.copyByte(chunkStringContentByte,endStringIndex,2))*2; String str=new String(Utils.copyByte(chunkStringContentByte,endStringIndex+2,stringSize+2)); stringContentList.add(Utils.filterStringNull(str)); endStringIndex+=(2+stringSize+2);}
注意:为什么存在字符串偏移值,这里还要使用字符串池偏移来获取所有字符串到ArrayList中呢
第三、解析ResourceIdchunk
1、chunktype:ResourceIdChunk类型,四个固定字节:0x00080108
2、Chunksize:ResourceIdchunk的大小,四个字节
3、ResourceIds:ResourceId的内容,这里大小是Resourcechunk大小(先减去头部大小8个字节)除以4(ResourceId占四个字节啊!)
代码:
/** * 解析Resource Chunk * @param byteSrc */public static void parseResourceChunk(byte[] byteSrc){ byte[] chunkTagByte = Utils.copyByte(byteSrc, resourceChunkOffset, 4); byte[] chunkSizeByte = Utils.copyByte(byteSrc, resourceChunkOffset+4, 4); int chunkSize = Utils.byte2int(chunkSizeByte); //这里需要注意的是chunkSize是包含了chunkTag和chunkSize这两个字节的,所以需要剔除 byte[] resourceIdByte = Utils.copyByte(byteSrc, resourceChunkOffset+8, chunkSize-8); ArrayList<Integer> resourceIdList = new ArrayList<Integer>(resourceIdByte.length/4); for(int i=0;i<resourceIdByte.length;i+=4){ int resId = Utils.byte2int(Utils.copyByte(resourceIdByte, i, 4)); System.out.println("id:"+resId+",hex:"+Utils.bytesToHexString(Utils.copyByte(resourceIdByte, i, 4))); resourceIdList.add(resId); } nextChunkOffset = (resourceChunkOffset+chunkSize);}
只是把ResourceId全部添加到ArrayList里就可以了吗,没有任何索引信息啊
第四、解析StartNamespaceChunk
1、chunktype:固定四个字节:0x00100100
2、chunksize:chunk的大小,四个字节
3、LineNumber:在androidmanifest文件中的行号,四个字节
4、unknown:未知区域,四个字节
5、prefix:命名空间的前缀(在字符串中的索引值),比如:android
6、命名空间的URI(在字符串中的索引值):比如:http://schemas.android.com/apk/res/android
public static void parseStartNamespaceChunk(byte[] byteSrc){ //获取ChunkTag byte[] chunkTagByte = Utils.copyByte(byteSrc, 0, 4); System.out.println(Utils.bytesToHexString(chunkTagByte)); //获取ChunkSize byte[] chunkSizeByte = Utils.copyByte(byteSrc, 4, 4); int chunkSize = Utils.byte2int(chunkSizeByte); System.out.println("chunk size:"+chunkSize); //解析行号 byte[] lineNumberByte = Utils.copyByte(byteSrc, 8, 4); int lineNumber = Utils.byte2int(lineNumberByte); System.out.println("line number:"+lineNumber); //解析prefix(这里需要注意的是行号后面的四个字节为FFFF,过滤) byte[] prefixByte = Utils.copyByte(byteSrc, 16, 4); int prefixIndex = Utils.byte2int(prefixByte); String prefix = stringContentList.get(prefixIndex); System.out.println("prefix:"+prefixIndex); System.out.println("prefix str:"+prefix); //解析Uri byte[] uriByte = Utils.copyByte(byteSrc, 20, 4); int uriIndex = Utils.byte2int(uriByte); String uri = stringContentList.get(uriIndex); System.out.println("uri:"+uriIndex); System.out.println("uri str:"+uri); uriPrefixMap.put(uri, prefix); prefixUriMap.put(prefix, uri);}
这下看来有字符串池偏移就够了啊,得到全部str到ArrayList,这里就可以直接给出索引值了啊
第五、startTagChunk
这个Chunk主要是存放了AndroidManifest.xml中的标签信息,也是最核心的内容
1、chunktype:chunk的类型,固定四个字节:0x00100102
2、chunksize:chunk大小,固定四个字节
3、LineNumber:对应于AndroidManifest中的行号,四个字节
4、unknown:未知区域,四个字节
5、NamespaceUri:这个标签用到的命名空间的Uri,比如用到了android这个前缀,那么就需要用http://schemas.android.com/apk/res/android这个Uri去获取,四个字节
6、Name:标签名称(在字符串中的索引值),四个字节
7、Flags:标签的类型,四个字节,比如是开始标签还是结束标签等
8、AttributeCount:标签包含的属性个数,四个字节
9、ClassAtrribute:标签包含的类属性,四个字节
10,Atrributes:属性内容,每个属性算是一个Entry,这个Entry固定大小是大小为5的字节数组:
[Namespace,Uri,Name,ValueString,Data]
代码分析:
- AndroidManifest解析
- AndroidManifest解析
- AndroidManifest解析
- AndroidManifest解析
- AndroidManifest.xml解析
- AndroidManifest.xml 文件解析
- AndroidManifest.xml解析
- AndroidManifest.xml简单解析
- AndroidManifest.xml解析
- AndroidManifest.xml解析
- AndroidManifest.xml解析
- AndroidManifest.xml文件解析
- AndroidManifest.xml 解析
- androidManifest.xml 解析
- AndroidManifest.xml文件解析
- AndroidManifest.xml文件解析
- AndroidManifest.xml文件解析
- AndroidManifest.xml文件解析
- Refletion2017.9.12
- jdk源码三 RandomAccess接口用法
- Python操作Access数据库
- Python 的platform模块 识别运行环境操作系统
- 学习一个二分图
- AndroidManifest解析
- 红黑树
- C++—String类
- 若干的数字串所有不同子串的和 后缀自动机
- android插件化(Instrumentation调用顺序)
- C++ Markup
- Maven项目开发____Maven依赖大全(Maven Spring依赖,Struts依赖,Hibernate依赖,等依赖pom)
- 手机端在不同手机上的返回键返回位置
- Bootstrap一些特殊要求