Apk解析之 —— AndroidManifest.xml
来源:互联网 发布:知乎 邮箱注册 编辑:程序博客网 时间:2024/05/29 12:30
本篇解析AndroidManifest.xml文件,参考文章:Reference
项目源码:ApkParser
Manifest文件结构
一. 头部信息
- 文件魔数:4bytes 0x00080003
- 文件大小:4bytes
二、String Chunk
这个Chunk主要存放的是AndroidManifest文件中所有的字符串信息
字符串是utf-16的宽字符,每个字符占2个字节,每个字符串块的前两个字节标识字符串的长度,以0x0000结尾,长度不包括尾部的结束符0x0000。
三、ResourceIdChunk
这个Chunk主要是存放的是AndroidManifest中用到的系统属性值
对应的资源Id(0x01xxxxxx),比如android:versionCode中的versionCode属性
Package ID相当于是一个命名空间,限定资源的来源,0x01属于系统资源命名空间,0x7f属于应用程序资源命名空间,所有位于[0x01, 0x7f]之间的Package ID都是合法的,而在这个范围之外的都是非法的Package ID。
Type ID是指资源的类型ID。资源的类型有animator、anim、color、drawable、layout、menu、raw、string和xml等等若干种,每一种都会被赋予一个ID。
Entry ID是指每一个资源在其所属的资源类型中所出现的次序。注意,不同类型的资源的Entry ID有可能是相同的,但是由于它们的类型不同,我们仍然可以通过其资源ID来区别开来。
系统资源对应id的xml文件所在路径:frameworks\base\core\res\res\values\public.xml
,版本越高的Sdk定义的ID项越多。
四、StartNamespaceChunk
这个Chunk主要包含AndroidManifest文件中的命令空间的内容,Android中的xml都是采用Schema格式的,所以肯定有Prefix和Uri的。(xml格式有两种:DTD和Schema)
五、StratTagChunk
这个Chunk主要是存放了AndroidManifest.xml中的标签信息了,也是最核心的内容,当然也是最复杂的内容
Entry的结构:
注意Entry.type不同,对应的Entry.data含义也不同,这些类型定义可以在AOSP源码的framework/base/include/androidfw/ResourceTypes.h
头文件中找到:
public static final int TYPE_NULL = 0x00;public static final int TYPE_REFERENCE = 0x01;public static final int TYPE_ATTRIBUTE = 0x02;public static final int TYPE_STRING = 0x03;public static final int TYPE_FLOAT = 0x04;public static final int TYPE_DIMENSION = 0x05;public static final int TYPE_FRACTION = 0x06;public static final int TYPE_DYNAMIC_REFERENCE = 0x07;public static final int TYPE_FIRSTINT = 0x10; // Beginning of integer flavors...public static final int TYPE_INT_DEC = 0x10; // n..n.public static final int TYPE_INT_HEX = 0x11; // 0xn..n.public static final int TYPE_INT_BOOLEAN = 0x12; // 0 or 1, "false" or "true"public static final int TYPE_FIRST_COLOR_INT = 0x1c; // Beginning of color integer flavors...public static final int TYPE_INT_COLOR_ARGB8 = 0x1c; // #aarrggbb.public static final int TYPE_INT_COLOR_RGB8 = 0x1d; // #rrggbb.public static final int TYPE_INT_COLOR_ARGB4 = 0x1e; // #argb.public static final int TYPE_INT_COLOR_RGB4 = 0x1f; // ##rgb.public static final int TYPE_LAST_COLOR_INT = 0x1f; // ..end of integer flavors.public static final int TYPE_LAST_INT = 0x1f; // ...end of integer flavors.
根据Entry.type获取Entry.data的数据:
public static String getAttributeData(AttributeEntry entry, StringChunk stringChunk) { String attrData; if (entry.type == TYPE_REFERENCE) { attrData = String.format("@%s%08x", getPackage(entry.data), entry.data); } else if (entry.type == TYPE_ATTRIBUTE) { attrData = String.format("?%s%08x", getPackage(entry.data), entry.data); } else if (entry.type == TYPE_STRING) { attrData = stringChunk.getString(entry.data); } else if (entry.type == TYPE_FLOAT) { attrData = String.valueOf(Float.intBitsToFloat((int)entry.data)); } else if (entry.type == TYPE_DIMENSION) { attrData = Float.toString(Float.intBitsToFloat((int) entry.data)) + getDimenUnit(entry.data); } else if (entry.type == TYPE_FRACTION) { attrData = Float.toString(Float.intBitsToFloat((int) entry.data)) + getFractionUnit(entry.data); } else if (entry.type == TYPE_DYNAMIC_REFERENCE) { attrData = "TYPE_DYNAMIC_REFERENCE"; // To be continue } else if (entry.type == TYPE_INT_DEC) { attrData = String.format("%d", entry.data); } else if (entry.type == TYPE_INT_HEX) { attrData = String.format("0x%08x", entry.data); } else if (entry.type == TYPE_INT_BOOLEAN) { attrData = entry.data == 0 ? "false" : "true"; } else if (entry.type == TYPE_INT_COLOR_ARGB8) { attrData = String.format("#%08x", entry.data); } else if (entry.type == TYPE_INT_COLOR_RGB8) { attrData = String.format("#ff%06x", 0xffffff & entry.data); } else if (entry.type == TYPE_INT_COLOR_ARGB4) { attrData = String.format("#%04x", 0xffff & entry.data); } else if (entry.type == TYPE_INT_COLOR_RGB4) { attrData = String.format("#f%03x", 0x0fff & entry.data); } else { attrData = String.format("<0x%08x, type 0x%08x>", entry.data, entry.type); } return attrData;}
六、EndTagChunk
EndTagChunk的结构和StartTagChunk类似,只是少了
七、EndNamespaceChunk
EndNamespaceChunk与StartNamespaceChunk对应,结构也完全相同。
八、格式化输出Xml文档
按读入的顺序遍历StratTagChunk和EndTagChunk就可以把文档对象格式化为Xml格式:
/** * Convert MfFile object to XML string. * @return xml */public String toXmlString() { StringBuilder builder = new StringBuilder(4096); int depth = 0; builder.append("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n"); for (TagChunk tagChunk : tagChunks) { if (tagChunk instanceof StartTagChunk) { builder.append(createStartTagXml((StartTagChunk) tagChunk, depth)); ++depth; } else if (tagChunk instanceof EndTagChunk) { --depth; builder.append(createEndTagXml((EndTagChunk) tagChunk, depth)); } } return builder.toString();}
九、END
- Apk解析之 —— AndroidManifest.xml
- Java解析 APK AndroidManifest.xml
- 使用AXMLParser解析apk中的AndroidManifest.xml
- PHP 解析 APK 中的 AndroidManifest.xml
- Apk AndroidManifest.xml收集
- 批量解析apk的AndroidManifest.xml获得Pagename(Python)
- AndroidManifest.xml 文件之详细解析
- 解析AndroidManifest.xml之AXMLParser.java
- AndroidManifest.xml 文件之详细解析
- Android之AndroidManifest.xml文件解析
- Android学习之AndroidManifest.xml文件解析
- Android之 AndroidManifest.xml 文件解析
- AndroidManifest.xml文件解析之category大全
- Android之AndroidManifest.xml文件解析
- 【转载】Android之AndroidManifest.xml文件解析
- Python——使用ElementTree解析AndroidManifest.xml文件
- Android apk AndroidManifest.xml 解密
- AndroidManifest.xml解析
- [基于Video4Linux的视频采集模块开发
- MySQL索引优化
- Webservice04---java与XML的转换
- Annotation简要用法(Java反射)
- linux socket通讯如何获取本地的源端口号
- Apk解析之 —— AndroidManifest.xml
- 网络判断
- 【英语】秋风吹---9月英语
- Java泛型中的通配符
- 前端性能优化----yahoo前端性能团队总结的35条黄金定律
- Hibernate多对多操作
- 24 Game
- 写程序学ML:决策树算法原理及实现(三)
- 弹性分布式数据集:一种对内存集群计算的容错抽象(一)