Формат AndroidManifest.xml #
ВНИМАНИЕ! Статья содержит неактуальные данные.
В настоящее время для работы с AndroidManifest.xml лучше использовать специализированный инструмент Apktool.
Вопрос:
Какой формат у файла AndroidManifest.xml, который находится в .apk-архивах для Android’а?
Ответ:
Своеобразный бинарный XML:
Мне удалось более-менее распотрошить этот формат. За основу своих исследований я взял утилиту axml2xml.pl написанную на Перле, автор которой несколько запутался в структуре файла и подошёл к разбору чисто эмпирически. Также я попробовал библиотеку для WbXML-файлов libwbxml версии 0.10.8, трудно сказать почему (опустим мои мучения связанные с её компиляцией под Win32), но она не хочет читать этот формат.
На самом деле файл состоит из набора кусочков (chunks), каждый из которых имеет небольшой обязательный заголовок из 8 байт - два слова по 16-бит и одно 32-бит. Первое слово - тип кусочка, второе - размер заголовка кусочка, он может включать дополнительные данные заголовка, соответственно минимальный размер 8 байт. Третье слово - общий размер кусочка включая данные после заголовка кусочка, минимальный размер тоже 8 байт. В начале файла AndroidManifest.xml стоит кусочек с типом 0x0003, длинной заголовка кусочка в 8 байт и общим размером во весь файл, все остальные кусочки расположены единым списком внутри него, и, похоже, что больше вложенных друг в друга кусочков нет. В других файлах, другие начальные типы, и могут быть вложенные кусочки (с принципом “вложения” до конца ещё не разобрался).
Схематично файл можно представить так:
[ Начало файла
[ Таблица строк ]
[ Неизвестный кусочек ]
[ Начало области имени ]
[ Начало тега ]
...
[ Конец тега ]
[ Конец области имени ]
]
Обнаруженные и идентифицированные типы кусочков такие:
- 0x0003 - Начало файла (file begin);
- 0x0001 - Таблица строк (string table);
- 0x0100 - Начало области имени (namespace);
- 0x0101 - Конец области имени (namespace);
- 0x0102 - Начало XML-тега (tag);
- 0x0103 - Конец XML-тега (tag).
Не удалось определить только кусочек с типом “0x0180”.
У типа “Начало XML-тега” присутствует набор атрибутов различных типов данных, я их обозначил так:
- 0x01000008 - [reference] Ссылка на ресурс, по всей видимости описанный в файле resources.arsc;
- 0x03000008 - [string] Номер строки из таблицы строк;
- 0x10000008 - [select] Число используемое для выбора из списка предопределённых констант;
- 0x11000008 - [integer] Целое 32-битное число;
- 0x12000008 - [boolean] Булевское значение true (0xffffffff) или false (0x00000000).
Результатом моих изысканий стала консольная программа которая преобразует бинарный XML в нормальный текстовый XML, а также позволяет просматривать структуру файла. Программа работает как с отдельным файлом, так и с находящимся внутри apk-архива.
Кроме самого AndroidManifest.xml в архиве можно прочитать и другие файлы того же формата, например, resources.arsc или xml-файлы из подкаталога “res”. Исходные тексты программы прилагаются. Надеюсь скоро кто-нибудь полностью расшифрует этот формат.
Командная строка #
Чтобы обработать отдельный XML-файл программу надо запускать так:
AndroidXML.exe [опции] [исследуемый файл.xml]
Чтобы обработать файл внутри APK-упаковки, так:
AndroidXML.exe [опции] [файл упаковки.apk] [исследуемый файл внутри]
Если не указать “исследуемый файл”, то по-умолчанию будет взят AndroidManifest.xml. Вместо apk-файла можно указать zip-файл, собственно apk - это и есть zip-архив.
Опции командной строки #
- /debug - Вывод информации о структуре кусочков;
- /pause - Останов после работы программы, чтобы консольное окно не закрывалось;
- /relax - Игнорирование небольших “ошибок” в структуре параметров XML-тегов при разборе файла.
Загрузка #
Пример работы программы в режиме XML #
<?xml version="1.0" encoding="utf-8"?>
<manifest
android:versionCode="234"
android:versionName="2.3.4"
package="com.gameloft.android.Gloft11US">
<uses-permission
android:name="android.permission.VIBRATE">
</uses-permission>
<application
android:label="7f040011"
android:icon="7f020000">
<activity
android:label="7f040011"
android:name="Gloft11US"
android:screenOrientation="1"
android:configChanges="240">
<intent-filter>
<action
android:name="android.intent.action.MAIN">
</action>
<category
android:name="android.intent.category.LAUNCHER">
</category>
</intent-filter>
</activity>
</application>
<uses-permission
android:name="android.permission.FULLSCREEN">
</uses-permission>
</manifest>
Пример работы программы в режиме просмотра структуры #
Parsing file AndroidManifest.xml in package: C:\Users\Nikolay\Downloads\games\1 vs 100 (2.3.4).apk
0. Offset 0 : Chunk type 0x0003, header size 8 bytes, chunk size 1804 bytes
File.
<?xml version="1.0" encoding="utf-8"?>
1. Offset 8 : Chunk type 0x0001, header size 28 bytes, chunk size 924 bytes
Strings 25 (extra 0x00000000, 0x00000000, 0x00000080, 0x00000000)
0. "versionName"
1. "versionCode"
2. "name"
3. "icon"
4. "label"
5. "configChanges"
6. "screenOrientation"
7. "android"
8. "http://schemas.android.com/apk/res/android"
9. ""
10. "package"
11. "manifest"
12. "com.gameloft.android.Gloft11US"
13. "2.3.4"
14. "uses-permission"
15. "android.permission.VIBRATE"
16. "application"
17. "activity"
18. "Gloft11US"
19. "intent-filter"
20. "action"
21. "android.intent.action.MAIN"
22. "category"
23. "android.intent.category.LAUNCHER"
24. "android.permission.FULLSCREEN"
2. Offset 932 : Chunk type 0x0180, header size 8 bytes, chunk size 36 bytes
Unknown.
Data (28 bytes):
0x1c 0x02 0x01 0x01 0x1b 0x02 0x01 0x01 0x03 0x00 0x01 0x01 0x02 0x00 0x01 0x01
0x01 0x00 0x01 0x01 0x1f 0x00 0x01 0x01 0x1e 0x00 0x01 0x01
3. Offset 968 : Chunk type 0x0100, header size 16 bytes, chunk size 24 bytes
number 2
param1 0xffffffff
param2 0x00000007 (namespace)
param3 0x00000008 (url)
Name space begin. xmlns:android="http://schemas.android.com/apk/res/android"
4. Offset 992 : Chunk type 0x0102, header size 16 bytes, chunk size 96 bytes
number 2
param1 0xffffffff
param2 0xffffffff
param3 0x0000000b (tag name)
<manifest [0x00140014, attributes=3, 0x00000000]
android:versionCode="234" [select]
android:versionName="2.3.4" [string]
package="com.gameloft.android.Gloft11US" [string]>
5. Offset 1088 : Chunk type 0x0102, header size 16 bytes, chunk size 56 bytes
number 6
param1 0xffffffff
param2 0xffffffff
param3 0x0000000e (tag name)
<uses-permission [0x00140014, attributes=1, 0x00000000]
android:name="android.permission.VIBRATE" [string]>
6. Offset 1144 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 6
param1 0xffffffff
param2 0xffffffff
param3 0x0000000e (tag name)
</uses-permission>
7. Offset 1168 : Chunk type 0x0102, header size 16 bytes, chunk size 76 bytes
number 7
param1 0xffffffff
param2 0xffffffff
param3 0x00000010 (tag name)
<application [0x00140014, attributes=2, 0x00000000]
android:label="7f040011" [reference]
android:icon="7f020000" [reference]>
8. Offset 1244 : Chunk type 0x0102, header size 16 bytes, chunk size 116 bytes
number 10
param1 0xffffffff
param2 0xffffffff
param3 0x00000011 (tag name)
<activity [0x00140014, attributes=4, 0x00000000]
android:label="7f040011" [reference]
android:name="Gloft11US" [string]
android:screenOrientation="1" [select]
android:configChanges="240" [number]>
9. Offset 1360 : Chunk type 0x0102, header size 16 bytes, chunk size 36 bytes
number 15
param1 0xffffffff
param2 0xffffffff
param3 0x00000013 (tag name)
<intent-filter [0x00140014, attributes=0, 0x00000000]>
10. Offset 1396 : Chunk type 0x0102, header size 16 bytes, chunk size 56 bytes
number 16
param1 0xffffffff
param2 0xffffffff
param3 0x00000014 (tag name)
<action [0x00140014, attributes=1, 0x00000000]
android:name="android.intent.action.MAIN" [string]>
11. Offset 1452 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 16
param1 0xffffffff
param2 0xffffffff
param3 0x00000014 (tag name)
</action>
12. Offset 1476 : Chunk type 0x0102, header size 16 bytes, chunk size 56 bytes
number 17
param1 0xffffffff
param2 0xffffffff
param3 0x00000016 (tag name)
<category [0x00140014, attributes=1, 0x00000000]
android:name="android.intent.category.LAUNCHER" [string]>
13. Offset 1532 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 17
param1 0xffffffff
param2 0xffffffff
param3 0x00000016 (tag name)
</category>
14. Offset 1556 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 18
param1 0xffffffff
param2 0xffffffff
param3 0x00000013 (tag name)
</intent-filter>
15. Offset 1580 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 19
param1 0xffffffff
param2 0xffffffff
param3 0x00000011 (tag name)
</activity>
16. Offset 1604 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 20
param1 0xffffffff
param2 0xffffffff
param3 0x00000010 (tag name)
</application>
17. Offset 1628 : Chunk type 0x0100, header size 16 bytes, chunk size 24 bytes
number 21
param1 0xffffffff
param2 0x00000007 (namespace)
param3 0x00000008 (url)
Name space begin. xmlns:android="http://schemas.android.com/apk/res/android"
18. Offset 1652 : Chunk type 0x0102, header size 16 bytes, chunk size 56 bytes
number 21
param1 0xffffffff
param2 0xffffffff
param3 0x0000000e (tag name)
<uses-permission [0x00140014, attributes=1, 0x00000000]
android:name="android.permission.FULLSCREEN" [string]>
19. Offset 1708 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 21
param1 0xffffffff
param2 0xffffffff
param3 0x0000000e (tag name)
</uses-permission>
20. Offset 1732 : Chunk type 0x0101, header size 16 bytes, chunk size 24 bytes
number 21
param1 0xffffffff
param2 0x00000007 (namespace)
param3 0x00000008 (url)
Name space end. xmlns:android="http://schemas.android.com/apk/res/android"
21. Offset 1756 : Chunk type 0x0103, header size 16 bytes, chunk size 24 bytes
number 22
param1 0xffffffff
param2 0xffffffff
param3 0x0000000b (tag name)
</manifest>
22. Offset 1780 : Chunk type 0x0101, header size 16 bytes, chunk size 24 bytes
number 22
param1 0xffffffff
param2 0x00000007 (namespace)
param3 0x00000008 (url)
Name space end. xmlns:android="http://schemas.android.com/apk/res/android"
Succeeded.