Inspecting an APK¶
Everything on this page reads the decoded AndroidManifest.xml and, where needed, the resource table.
The examples assume an opened APK:
Triage¶
print(f"Package: {apk.get_package_name()}")
print(f"Version: {apk.get_version_name()} ({apk.get_version_code()})")
print(f"SDK: min {apk.get_min_sdk_version()}, target {apk.get_target_sdk_version()}")
print(f"Label: {apk.get_application_label()}")
print(f"Debuggable: {apk.get_application_debuggable()}")
print(f"Backup: {apk.get_application_allow_backup()}")
print(f"Multidex: {apk.is_multidex()}")
print(f"ABIs: {apk.get_supported_abis()}")
let package = apk.get_package_name().unwrap_or_default();
println!("Package: {package}");
println!(
"Version: {} ({})",
apk.get_version_name().unwrap_or_default(),
apk.get_version_code().unwrap_or_default()
);
println!(
"SDK: min {}, target {}",
apk.get_min_sdk_version().unwrap_or_default(),
apk.get_target_sdk_version()
);
println!(
"Label: {}",
apk.get_application_label().unwrap_or_default()
);
println!("Debuggable: {:?}", apk.get_application_debuggable());
println!("Backup: {:?}", apk.get_application_allow_backup());
println!("Multidex: {}", apk.is_multidex());
println!("ABIs: {:?}", apk.get_supported_abis());
Output of the Python version for apkstest.apk (Rust prints Options with {:?}):
Package: io.github.delvinru.apkstest
Version: 1.0.7 (7)
SDK: min 21, target 35
Label: APKS Test
Debuggable: None
Backup: None
Multidex: False
ABIs: ['x86_64']
Boolean manifest attributes come back as they are written: "true", "false", or None when the attribute is absent, so you can tell an explicit android:debuggable="false" from a missing one.
get_supported_abis() lists the ABIs found under lib/. For XAPK / APKM / APKS files it also includes the ABIs of config.<abi>.apk splits.
Is it launchable?¶
An app is launchable when an activity (or activity alias) handles MAIN with the LAUNCHER or INFO category. get_main_activities() follows the same rules as Android's ApplicationPackageManager: activity aliases count, and activities with android:enabled="false" are skipped. get_main_activity() returns the first one.
You get activity names as written in the manifest, so they may be relative (.MainActivity). am start -n accepts both forms.
Device targets¶
targets = [
name
for name, matches in [
("TV", apk.is_leanback()),
("Wear OS", apk.is_wearable()),
("Android Automotive", apk.is_automotive()),
("ChromeOS", apk.is_chromebook()),
("Android XR", apk.is_xr()),
]
if matches
]
print(f"Targets: {', '.join(targets) or 'phone / tablet'}")
print(f"Features: {sorted(apk.get_features())}")
let targets: Vec<&str> = [
("TV", apk.is_leanback()),
("Wear OS", apk.is_wearable()),
("Android Automotive", apk.is_automotive()),
("ChromeOS", apk.is_chromebook()),
("Android XR", apk.is_xr()),
]
.into_iter()
.filter_map(|(name, matches)| matches.then_some(name))
.collect();
println!("Targets: {targets:?}");
| Method | True when <uses-feature> declares |
|---|---|
is_leanback() |
android.software.leanback or android.hardware.type.television |
is_wearable() |
android.hardware.type.watch |
is_automotive() |
android.hardware.type.automotive |
is_chromebook() |
android.hardware.type.pc |
is_xr() |
android.software.xr.api.spatial or android.software.xr.api.openxr |
Any manifest attribute¶
Getters exist for the common attributes. For everything else, get_attribute_value(tag, name) returns the attribute of the first matching tag, and get_all_attribute_values(tag, name) returns it for every matching tag. Pass attribute names without the android: prefix.
# any attribute of the first matching tag, by name without the "android:" prefix
print(apk.get_attribute_value("application", "networkSecurityConfig"))
print(apk.get_attribute_value("application", "usesCleartextTraffic"))
# every value of an attribute across all matching tags
print(apk.get_all_attribute_values("uses-permission", "name"))
Resource references¶
Many manifest values are references like @string/app_name. Getters such as get_application_label() resolve them through resources.arsc. For anything else, use get_resource_value():
File resources resolve to their path inside the archive. Release builds often shorten these paths (for example res/7j.png), so don't expect res/mipmap-*/ic_launcher.png to exist.
If resources.arsc is missing or corrupted on purpose, parsing still succeeds: references stay unresolved, and you can still read the manifest, DEX files and signatures.
The full manifest¶
The output is the decoded XML with resource references resolved, the same as apk-info axml prints.