Skip to content

relikd/AndroidXML

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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 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

let parser = try AndroidXML(path: "some/AndroidManifest.xml").parseXml()
print(try parser.xmlString())

Manual XML Parser

let xml = try! AndroidXML(data: [...]).parseXml()
try xml.iterElements({ startTag, attributes in
	print("<\(startTag)>")
	for (name, val) in try? attributes.asList() {
		print("\t", name, "=", val.resolve(xml.stringPool))
	}
}) { endTag in
	print("</\(endTag)>")
}

Resource Table Lookup

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

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.

About

Pure Swift library for parsing Android binary XML files

Topics

Resources

License

Stars

Watchers

Forks

Languages