Files
AndroidXML/README.md
2025-11-25 22:46:14 +01:00

91 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AndroidXML
Pure Swift library for parsing binary XML files such as found in Android apk files.
## About
Written from scratch and closely following the original C++ source code ([ResourceTypes.h], [ResourceTypes.cpp]).
Names have been adapted to a more Swiftly syntax.
Import of `Foundation` is optional which should makes the library cross-platform compatible (though I have not tested other than macOS).
Since the AXML format is not documented anywhere apart from the source code you cannot rely on the structure to work forever.
Especially, pay attention to other binary XML formats which have [been spotted](https://www.cclsolutionsgroup.com/post/android-abx-binary-xml) on Android.
I do not think ABX is currently used for `.apk` files, only system files.
However, If that should change I would need to make some adjustments to this library.
## Example Usage
### Automatic XML String Conversion
```swift
let parser = try AndroidXML(path: "some/AndroidManifest.xml").parseXml()
print(try parser.xmlString())
```
### Manual XML Parser
```swift
let xml = try! AndroidXML(data: [...]).parseXml()
try xml.iterElements({ startTag, attributes in
print("<\(startTag)>")
for (name, val) in attributes {
print("\t", name, "=", val.resolve(xml.stringPool))
}
}) { endTag in
print("</\(endTag)>")
}
```
### Resource Table Lookup
```swift
let lookupId = 0x7F100000
let xml = try! AndroidXML(path: "some/resources.arsc").parseTable()
let res = try! xml.getResource(TblTableRef(lookupId))!
let pkgPool = res.package.stringPool(for: .Keys)!
for x in res.entries {
let val = x.entry.value!
print(pkgPool.getString(x.entry.key), val.resolve(xml.stringPool), x.config.screenType.density)
}
```
### Manual Table Parsing
```swift
let xml = try AndroidXML(path: "some/resources.arsc").parseTable()
for pkg in try xml.getPackages() {
let pool = pkg.stringPool(for: .Keys)!
try pkg.iterTypes { spec, types in
//print("----- \(spec.id) ------")
for type in types {
try type.iterValues { idx, entry in
if entry.isComplex {
//print("::.::.complex", pool.getString(entry.key), entry.valueMap!.parent.asHex)
for x in entry.valueMap!.entries {
let _ = x.name.asHex
let _ = x.value.resolve(xml.stringPool)
}
} else {
let _ = pool.getString(entry.key)
let _ = entry.value!.resolve(xml.stringPool)
}
}
}
}
}
```
## Developer Note
There are a few places I could not properly test becaues none of my test files triggered the condition.
For example, handling dynamic attributes and dynamic references.
I've added some `assert` (ignored in release builds) to trigger as soon as a specific condition is met.
If you encounter a file, which triggers such a condition, reach out so I can finalize the library.
[ResourceTypes.h]: https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/include/androidfw/ResourceTypes.h
[ResourceTypes.cpp]: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/libs/androidfw/ResourceTypes.cpp