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+2while(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]
代码分析:

原创粉丝点击