终极编译出来的Xml二进制文件是一系列的chunk构成的,每一个chunk都有一个头部,用来形貌chunk的元信息。同时,整个Xml二进制文件又可以当作一块总的chunk,它有一个类型为ResXMLTree_header的头部。
ResXMLTree_header界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * Header that appears at the front of every data chunk in a resource. */struct ResChunk_header{ // Type identifier for this chunk. The meaning of this value depends // on the containing chunk. uint16_t type; // Size of the chunk header (in bytes). Adding this value to // the address of the chunk allows you to find its associated data // (if any). uint16_t headerSize; // Total size of this chunk (in bytes). This is the chunkSize plus // the size of any data associated with the chunk. Adding this value // to the chunk allows you to completely skip its contents (including // any child chunks). If this value is the same as chunkSize, there is // no data associated with the chunk. uint32_t size;}; /** * XML tree header. This appears at the front of an XML tree, * describing its content. It is followed by a flat array of * ResXMLTree_node structures; the hierarchy of the XML document * is described by the occurrance of RES_XML_START_ELEMENT_TYPE * and corresponding RES_XML_END_ELEMENT_TYPE nodes in the array. */struct ResXMLTree_header{ struct ResChunk_header header;};ResXMLTree_header内嵌有一个类型为ResChunk_header的头部。毕竟上,每一种头部类型都会内嵌有一个类型为ResChunk_header的基础头部,并且这个ResChunk_header都是作为第一个成员变量出现的。这样在分析二进制Xml文件的时间,只必要读出前面巨细为sizeof(ResChunk_header)的数据块,并且通过辨认其中的type值,就可以知道实际正在处理处罚的chunk的详细类型。
对于ResXMLTree_header头部来说,内嵌在它内里的ResChunk_header的成员变量的值如下所示:
type:便是RES_XML_TYPE,形貌这是一个Xml文件头部。
headerSize:便是sizeof(ResXMLTree_header),表现头部的巨细。
size:便是整个二进制Xml文件的巨细,包罗头部headerSize的巨细。
Step 4. 写入字符串资源池
原来界说在Xml文件中的字符串已经在Step 1和Step 2中网络完毕,因此,这里就可以将它们写入到终极网络到二进制格式的Xml文件中去。留意,写入的字符串是严酷按照它们在字符串资源池中的次序写入的。比方,对于main.xml来说,依次写入的字符串为“orientation”、“layout_width”、“layout_height”、“gravity”、“id”、"text"、"android"、“http://schemas.android.com/apk/res/android”、“LinearLayout”和“Button”。之以是要严酷按照这个次序来写入,是由于接下来要将前面Step 1网络到的资源ID数组也写入到二进制格式的Xml文件中去,并且要保持这个资源ID数组与字符串资源池前六个字符串的对应关系。
写入的字符串池chunk同样也是具有一个头部的,这个头部的类型为ResStringPool_header,它界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:
/** * Definition for a pool of strings. The data of this chunk is an * array of uint32_t providing indices into the pool, relative to * stringsStart. At stringsStart are all of the UTF-16 strings * concatenated together; each starts with a uint16_t of the string's * length and each ends with a 0x0000 terminator. If a string is > * 32767 characters, the high bit of the length is set meaning to take * those 15 bits as a high word and it will be followed by another * uint16_t containing the low word. * * If styleCount is not zero, then immediately following the array of * uint32_t indices into the string table is another array of indices * into a style table starting at stylesStart. Each entry in the * style table is an array of ResStringPool_span structures. */struct ResStringPool_header{ struct ResChunk_header header; // Number of strings in this pool (number of uint32_t indices that follow // in the data). uint32_t stringCount; // Number of style span arrays in the pool (number of uint32_t indices // follow the string indices). uint32_t styleCount; // Flags. enum { // If set, the string index is sorted by the string values (based // on strcmp16()). SORTED_FLAG = 1<<0, // String pool is encoded in UTF-8 UTF8_FLAG = 1<<8 }; uint32_t flags; // Index from header of the string data. uint32_t stringsStart; // Index from header of the style data. uint32_t stylesStart;};内嵌在ResStringPool_header内里的ResChunk_header的成员变量的值如下所示:
接下来,我们就重点说说什么是字符串样式。假设有一个字符串资源池,它有五个字符串,分别是"apple"、“banana”、“orange”、“<b>man</b><i>go</i>”和“pear”。留意到第四个字符串“<b>man</b><i>go</i>”,它实际表现的是一个字符串“mango”,不过它的前三个字符“man”通过b标签来形貌为粗体的,而后两个字符通过i标签来形貌为斜体的。这样实际上在整个字符串资源池中,包罗了七个字符串,分别是"apple"、“banana”、“orange”、“mango”、“pear”、“b”和“i”,其中,第四个字符串“mango”来有两个sytle,第一个style表现第1到第3个字符是粗体的,第二个style表现第4到第5个字符是斜体的。
字符串与其样式形貌是逐一对应的,也就是说,如果第i个字符串是带有样式形貌的,那么它的样式形貌就位于样式内容块第i个位置上。以上面的字符串资源池为例,由于第4个字符中带有样式形貌,为了保持字符串与样式形貌的逐一对应关系,那么也必要假设前面3个字符串也带有样式形貌的,不过必要将这3个字符串的样式形貌的个数设置为0。也就是说,在这种环境下,字符串的个数便是7,而样式形貌的个数便是4,其中,第1到第3个字符串的样式形貌的个数便是0,而第4个字符串的样式形貌的个数便是2。
假设一个字符串有N个样式形貌,那么它在样式内容块中,就对应有N个ResStringPool_span,以及一个ResStringPool_ref,其中,N个ResStringPool_span位于前面,用来形貌每一个样式,而ResStringPool_ref表现一个竣事占位符。比方,对于上述的“mango”字符串来说,它就对应有2个ResStringPool_span,以及1个ResStringPool_ref,而对于"apple"、“banana”和“orange”这三个字符串来说,它们对应有0个ResStringPool_span,但是对应有1个ResStringPool_ref,末了三个字符串“pear”、“b”和"i"对应有0个ResStringPool_span和0个ResStringPool_ref。
`ResStringPool_span`和`ResStringPool_ref`界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * Reference to a string in a string pool. */struct ResStringPool_ref{ // Index into the string pool table (uint32_t-offset from the indices // immediately after ResStringPool_header) at which to find the location // of the string data in the pool. uint32_t index;}; /** * This structure defines a span of style information associated with * a string in the pool. */struct ResStringPool_span{ enum { END = 0xFFFFFFFF }; // This is the name of the span -- that is, the name of the XML // tag that defined it. The special value END (0xFFFFFFFF) indicates // the end of an array of spans. ResStringPool_ref name; // The range of characters in the string that this span applies to. uint32_t firstChar, lastChar;};由于ResStringPool_ref在这里出现的作用就是充当样式形貌竣事占位符,因此,它唯一的成员变量index的取值就固定为ResStringPool_span::END。
再来看ResStringPool_span是怎样表现一个样式形貌的。以字符串“mango”的第一个样式形貌为例,对应的ResStringPool_span的各个成员变量的取值为:
ResXMLTree_node和ResXMLTree_namespaceExt界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * Basic XML tree node. A single item in the XML document. Extended info * about the node can be found after header.headerSize. */struct ResXMLTree_node{ struct ResChunk_header header; // Line number in original source file at which this element appeared. uint32_t lineNumber; // Optional XML comment that was associated with this element; -1 if none. struct ResStringPool_ref comment;}; /** * Extended XML tree node for namespace start/end nodes. * Appears header.headerSize bytes after a ResXMLTree_node. */struct ResXMLTree_namespaceExt{ // The prefix of the namespace. struct ResStringPool_ref prefix; // The URI of the namespace. struct ResStringPool_ref uri;};对于main.xml文件来说,在它的定名空间chunk中,内嵌在第一个ResXMLTree_node内里的ResChunk_header的各个成员变量的取值如下所示:
ResXMLTree_attrExt、ResXMLTree_attribute和ResXMLTree_endElementExt界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * Extended XML tree node for start tags -- includes attribute * information. * Appears header.headerSize bytes after a ResXMLTree_node. */struct ResXMLTree_attrExt{ // String of the full namespace of this element. struct ResStringPool_ref ns; // String name of this node if it is an ELEMENT; the raw // character data if this is a CDATA node. struct ResStringPool_ref name; // Byte offset from the start of this structure where the attributes start. uint16_t attributeStart; // Size of the ResXMLTree_attribute structures that follow. uint16_t attributeSize; // Number of attributes associated with an ELEMENT. These are // available as an array of ResXMLTree_attribute structures // immediately following this node. uint16_t attributeCount; // Index (1-based) of the "id" attribute. 0 if none. uint16_t idIndex; // Index (1-based) of the "class" attribute. 0 if none. uint16_t classIndex; // Index (1-based) of the "style" attribute. 0 if none. uint16_t styleIndex;}; struct ResXMLTree_attribute{ // Namespace of this attribute. struct ResStringPool_ref ns; // Name of this attribute. struct ResStringPool_ref name; // The original raw string value of this attribute. struct ResStringPool_ref rawValue; // Processesd typed value of this attribute. struct Res_value typedValue;}; /** * Extended XML tree node for element start/end nodes. * Appears header.headerSize bytes after a ResXMLTree_node. */struct ResXMLTree_endElementExt{ // String of the full namespace of this element. struct ResStringPool_ref ns; // String name of this node if it is an ELEMENT; the raw // character data if this is a CDATA node. struct ResStringPool_ref name;};内嵌在第一个ResXMLTree_node内里的ResChunk_header的各个成员变量的取值如下所示:
/** * Representation of a value in a resource, supplying type * information. */struct Res_value{ // Number of bytes in this structure. uint16_t size; // Always set to 0. uint8_t res0; // Type of the data value. enum { // Contains no data. TYPE_NULL = 0x00, // The 'data' holds a ResTable_ref, a reference to another resource // table entry. TYPE_REFERENCE = 0x01, // The 'data' holds an attribute resource identifier. TYPE_ATTRIBUTE = 0x02, // The 'data' holds an index into the containing resource table's // global value string pool. TYPE_STRING = 0x03, // The 'data' holds a single-precision floating point number. TYPE_FLOAT = 0x04, // The 'data' holds a complex number encoding a dimension value, // such as "100in". TYPE_DIMENSION = 0x05, // The 'data' holds a complex number encoding a fraction of a // container. TYPE_FRACTION = 0x06, // Beginning of integer flavors... TYPE_FIRST_INT = 0x10, // The 'data' is a raw integer value of the form n..n. TYPE_INT_DEC = 0x10, // The 'data' is a raw integer value of the form 0xn..n. TYPE_INT_HEX = 0x11, // The 'data' is either 0 or 1, for input "false" or "true" respectively. TYPE_INT_BOOLEAN = 0x12, // Beginning of color integer flavors... TYPE_FIRST_COLOR_INT = 0x1c, // The 'data' is a raw integer value of the form #aarrggbb. TYPE_INT_COLOR_ARGB8 = 0x1c, // The 'data' is a raw integer value of the form #rrggbb. // The 'data' is a raw integer value of the form #aarrggbb. TYPE_INT_COLOR_ARGB8 = 0x1c, // The 'data' is a raw integer value of the form #rrggbb. TYPE_INT_COLOR_RGB8 = 0x1d, // The 'data' is a raw integer value of the form #argb. TYPE_INT_COLOR_ARGB4 = 0x1e, // The 'data' is a raw integer value of the form #rgb. TYPE_INT_COLOR_RGB4 = 0x1f, // ...end of integer flavors. TYPE_LAST_COLOR_INT = 0x1f, // ...end of integer flavors. TYPE_LAST_INT = 0x1f }; uint8_t dataType; // Structure of complex data values (TYPE_UNIT and TYPE_FRACTION) enum { // Where the unit type information is. This gives us 16 possible // types, as defined below. COMPLEX_UNIT_SHIFT = 0, COMPLEX_UNIT_MASK = 0xf, // TYPE_DIMENSION: Value is raw pixels. COMPLEX_UNIT_PX = 0, // TYPE_DIMENSION: Value is Device Independent Pixels. COMPLEX_UNIT_DIP = 1, // TYPE_DIMENSION: Value is a Scaled device independent Pixels. COMPLEX_UNIT_SP = 2, // TYPE_DIMENSION: Value is in points. COMPLEX_UNIT_PT = 3, // TYPE_DIMENSION: Value is in inches. COMPLEX_UNIT_IN = 4, // TYPE_DIMENSION: Value is in millimeters. COMPLEX_UNIT_MM = 5, // TYPE_FRACTION: A basic fraction of the overall size. COMPLEX_UNIT_FRACTION = 0, // TYPE_FRACTION: A fraction of the parent size. COMPLEX_UNIT_FRACTION_PARENT = 1, // Where the radix information is, telling where the decimal place // appears in the mantissa. This give us 4 possible fixed point // representations as defined below. COMPLEX_RADIX_SHIFT = 4, COMPLEX_RADIX_MASK = 0x3, // The mantissa is an integral number -- i.e., 0xnnnnnn.0 COMPLEX_RADIX_23p0 = 0, // The mantissa magnitude is 16 bits -- i.e, 0xnnnn.nn COMPLEX_RADIX_16p7 = 1, // The mantissa magnitude is 8 bits -- i.e, 0xnn.nnnn COMPLEX_RADIX_8p15 = 2, // The mantissa magnitude is 0 bits -- i.e, 0x0.nnnnnn COMPLEX_RADIX_0p23 = 3, // Where the actual value is. This gives us 23 bits of // precision. The top bit is the sign. COMPLEX_MANTISSA_SHIFT = 8, COMPLEX_MANTISSA_MASK = 0xffffff }; // The data for this item, as interpreted according to dataType. uint32_t data; void copyFrom_dtoh(const Res_value& src);};一个属性的值颠末分析之后,也就是颠末前面编译Xml资源的第3个操纵之后,就用一个Res_value来表现。 比方,对于名称为“orientation”的属性的值“vertical”来说,颠末分析之后,它就会用一个Res_value来表现,这个Res_value的各个成员变量的值如下所示:
对于一个Xml文件来说,它除了有定名空间和平常标签类型的Node之外,尚有一些称为CDATA类型的Node,比方,假设一个Xml文件,它的一个Item标签的内容如下所示:
...... <Item>This is a normal text</Item> ......那么字符串“This is a normal text”就称为一个CDATA,它在二进制Xml文件中用一个ResXMLTree_node和一个ResXMLTree_cdataExt来形貌,如图16所示:
ResXMLTree_cdataExt界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * Extended XML tree node for CDATA tags -- includes the CDATA string. * Appears header.headerSize bytes after a ResXMLTree_node. */struct ResXMLTree_cdataExt{ // The raw CDATA character data. struct ResStringPool_ref data; // The typed value of the character data if this is a CDATA node. struct Res_value typedData;};内嵌在上面的ResXMLTree_node的ResChunk_header的各个成员变量的取值如下所示:
在图17所示的资源项中,一共有12个资源项,但是只有10项是具有值字符串的,它们分别是“res/drawable-ldpi/icon.png”、“res/drawable-mdpi/icon.png”、“res/drawable-hdpi/icon.png”、“res/layout/main.xml”、“res/layout/sub.xml”、“Activity”、“Sub Activity”、“Start sub-activity in process”、“Start sub-activity in new process”和“Finish activity”。
Package资源项元信息数据块头部是用一个ResTable_package来界说的。ResTable_package界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * A collection of resource data types within a package. Followed by * one or more ResTable_type and ResTable_typeSpec structures containing the * entry values for each resource type. */struct ResTable_package{ struct ResChunk_header header; // If this is a base package, its ID. Package IDs start // at 1 (corresponding to the value of the package bits in a // resource identifier). 0 means this is not a base package. uint32_t id; // Actual name of this package, \0-terminated. char16_t name[128]; // Offset to a ResStringPool_header defining the resource // type symbol table. If zero, this package is inheriting from // another base package (overriding specific values in it). uint32_t typeStrings; // Last index into typeStrings that is for public use by others. uint32_t lastPublicType; // Offset to a ResStringPool_header defining the resource // key symbol table. If zero, this package is inheriting from // another base package (overriding specific values in it). uint32_t keyStrings; // Last index into keyStrings that is for public use by others. uint32_t lastPublicKey;};嵌入在ResTable_package内部的ResChunk_header的各个成员变量的取值如下所示:
在Android资源中,有一种资源类型称为Public,它们一样寻常是界说在res/values/public.xml文件中,情势如下所示:
<?xml version="1.0" encoding="utf-8"?><resources> <public type="string" name="string3" id="0x7f040001" /></resources>这个public.xml用来告诉Android资源打包工具aapt,将类型为string的资源string3的ID固定为0x7f040001。为什么必要将某一个资源项的ID固定下来呢?一样寻常来说,当我们将本身界说的资源导出来给第三方应用步伐利用时,为了包管以后修改这些导出资源时,仍旧包管第三方应用步伐的兼容性,就必要给那些导出资源一个固定的资源ID。
每当Android资源打包工具aapt重新编译被修改过的资源时,都会重新给这些资源赋予ID,这就大概会造成同一个资源项在两次差别的编译中被赋予差别的ID。这种环境就会给第三方应用步伐步伐带来贫苦,由于后者一样寻常是假设一个ID对应的永久是同一个资源的。因此,当我们将本身界说的资源导出来给第三方应用步伐利用时,就必要通过public.xml文件将导出来的资源的ID固定下来。
我们用一个例子来说public.xml文件的作用,思量下面这个strings.xml文件:
<?xml version="1.0" encoding="utf-8"?><resources> <string name="string1">String 1</string> <string name="string3">String 3</string></resources>假设Android资源打包工具aapt为字符串资源项string1和string3分配到的资源ID如下所示:
public final class R { // ... public static final class string { public static final int string1=0x7f040000; public static final int string3=0x7f040001; }}这时间第三方应用步伐就会以为0x7f040001引用的永久是字符串“String 3”。
假设将来的某一天,我们必要在strings.xml文件中增加一个新的字符串,如下所示:
<?xml version="1.0" encoding="utf-8"?><resources> <string name="string1">String 1</string> <string name="string2">String 2</string> <string name="string3">String 3</string></resources>如果没有上述的public.xml文件,那么Android资源打包工具aapt为字符串资源项string1、 string2和string3分配的资源ID就会如下所示:
public final class R { // ... public static final class string { public static final int string1=0x7f040000; public static final int string2=0x7f040001; public static final int string3=0x7f040002; // New ID! Was 0x7f040001 }}这就完蛋了,这时间第三方应用步伐通过0x7f040001引用到的字符串变成了“String 2”。
如果我们利用上述的public.xml文件将字符串“String 3”固定为0x7f040001,那么Android资源打包工具aapt为字符串资源项string1、 string2和string3分配的资源ID就会如下所示:
public final class R { // ... public static final class string { public static final int string1=0x7f040000; public static final int string2=0x7f040002; public static final int string3=0x7f040001; // Resource ID from public.xml }}这样第三方应用步伐通过0x7f040001引用到的字符串仍旧是“String 3”。
类型规范数据块用来形貌资源项的设置差异性。通过这个差异性形貌,我们就可以知道每一个资源项的设置状态。知道了一个资源项的设置状态之后,Android资源管理框架在检测到装备的设置信息发生变革之后,就可以知道是否必要重新加载该资源项。类型规范数据块是按照类型来构造的,也就是说,每一种类型都对应有一个类型规范数据块。
类型规范数据块的头部是用一个ResTable_typeSpec来界说的。ResTable_typeSpec界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * A specification of the resources defined by a particular type. * * There should be one of these chunks for each resource type. * * This structure is followed by an array of integers providing the set of * configuation change flags (ResTable_config::CONFIG_*) that have multiple * resources for that configuration. In addition, the high bit is set if that * resource has been made public. */struct ResTable_typeSpec{ struct ResChunk_header header; // The type identifier this chunk is holding. Type IDs start // at 1 (corresponding to the value of the type bits in a // resource identifier). 0 is invalid. uint8_t id; // Must be 0. uint8_t res0; // Must be 0. uint16_t res1; // Number of uint32_t entry configuration masks that follow. uint32_t entryCount; enum { // Additional flag indicating an entry is public. SPEC_PUBLIC = 0x40000000 };};嵌入在ResTable_typeSpec内里的ResChunk_header的各个成员变量的取值如下所示:
类型资源项数据块用来形貌资源项的详细信息, 这样我们就可以知道每一个资源项名称、值和设置等信息。类型资源项数据同样是按照类型和设置来构造的,也就是说,一个具有N个设置的类型一共对应有N个类型资源项数据块。
类型资源项数据块的头部是用一个`ResTable_type`来界说的。ResTable_type界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * A collection of resource entries for a particular resource data * type. Followed by an array of uint32_t defining the resource * values, corresponding to the array of type strings in the * ResTable_package::typeStrings string block. Each of these hold an * index from entriesStart; a value of NO_ENTRY means that entry is * not defined. * * There may be multiple of these chunks for a particular resource type, * supply different configuration variations for the resource values of * that type. * * It would be nice to have an additional ordered index of entries, so * we can do a binary search if trying to find a resource by string name. */struct ResTable_type{ struct ResChunk_header header; enum { NO_ENTRY = 0xFFFFFFFF }; // The type identifier this chunk is holding. Type IDs start // at 1 (corresponding to the value of the type bits in a // resource identifier). 0 is invalid. uint8_t id; // Must be 0. uint8_t res0; // Must be 0. uint16_t res1; // Number of uint32_t entry indices that follow. uint32_t entryCount; // Offset from header where ResTable_entry data starts. uint32_t entriesStart; // Configuration this collection of entries is designed for. ResTable_config config;};嵌入在ResTable_type内里的ResChunk_header的各个成员变量的取值如下所示:
由于不存在类型为drawable、设置为ldpi,并且名称为logo的资源项,因此,在图31中,ResTable_type反面的uint32_t数组和ResTable_entry数组的巨细是不相当的,并且没有相应的ResTable_entry的uint32_t数组元素的值会被设置为ResTable_type::NO_ENTRY。
每一个资源项数据都是通过一个 ResTable_entry来界说的。
ResTable_entry界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * This is the beginning of information about an entry in the resource * table. It holds the reference to the name of this entry, and is * immediately followed by one of: * * A Res_value structure, if FLAG_COMPLEX is -not- set. * * An array of ResTable_map structures, if FLAG_COMPLEX is set. * These supply a set of name/value mappings of data. */struct ResTable_entry{ // Number of bytes in this structure. uint16_t size; enum { // If set, this is a complex entry, holding a set of name/value // mappings. It is followed by an array of ResTable_map structures. FLAG_COMPLEX = 0x0001, // If set, this resource has been declared public, so libraries // are allowed to reference it. FLAG_PUBLIC = 0x0002 }; uint16_t flags; // Reference into ResTable_package::keyStrings identifying this entry. struct ResStringPool_ref key;};ResTable_entry的各个成员变量的取值如下所示:
在图33中,紧跟在ResTable_entry反面的是一个ResTable_map_entry,用来形貌反面要写入到的ResTable_map的信息。假设一个Bag资源项有N个bag,那么在ResTable_map_entry就有N个ResTable_map。
ResTable_map_entry界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * This is a reference to a unique entry (a ResTable_entry structure) * in a resource table. The value is structured as: 0xpptteeee, * where pp is the package index, tt is the type index in that * package, and eeee is the entry index in that type. The package * and type values start at 1 for the first item, to help catch cases * where they have not been supplied. */struct ResTable_ref{ uint32_t ident;}; /** * Extended form of a ResTable_entry for map entries, defining a parent map * resource from which to inherit values. */struct ResTable_map_entry : public ResTable_entry{ // Resource identifier of the parent mapping, or 0 if there is none. ResTable_ref parent; // Number of name/value pairs that follow for FLAG_COMPLEX. uint32_t count;};ResTable_map_entry是从ResTable_entry继续下来的,我们首先看ResTable_entry的各个成员变量的取值:
Bag资源项的每一个bag都用一个ResTable_map来表现。
ResTable_map界说在文件frameworks/base/include/utils/ResourceTypes.h中,如下所示:struct ResTable_map{ // The resource identifier defining this mapping's name. For attribute // resources, 'name' can be one of the following special resource types // to supply meta-data about the attribute; for all other resource types // it must be an attribute resource. ResTable_ref name; ..... // This mapping's value. Res_value value;};ResTable_map只有两个成员变量,其中:
资源索引表头部利用一个ResTable_header来表现。ResTable_header界说在文件
frameworks/base/include/utils/ResourceTypes.h中,如下所示:/** * Header for a resource table. Its data contains a series of * additional chunks: * * A ResStringPool_header containing all table values. * * One or more ResTable_package chunks. * * Specific entries within a resource table can be uniquely identified * with a single integer as defined by the ResTable_ref structure. */struct ResTable_header{ struct ResChunk_header header; // The number of ResTable_package structures. uint32_t packageCount;};嵌入在ResTable_header内部的ResChunk_header的各个成员变量的取值如下所示:
在前面的第八步中,我们已经将全部的资源项及其所对应的资源ID都网络起来了,因此,这里只要将直接将它们写入到指定的R.java文件去就可以了。比方,假设分配给类型为layout的资源项main和sub的ID为0x7f030000和0x7f030001,那么在R.java文件,就会分别有两个以main和sub为名称的常量,如下所示:
public final class R { ...... public static final class layout { public static final int main=0x7f030000; public static final int sub=0x7f030001; } ......}