A reusable Android developer toolkit for Rust — the presentation-free plumbing that project-aware Android CLIs share.
androkit was extracted from dab so
that tools like adev and dab
don't each reimplement ADB wrangling, APK parsing, and Gradle project discovery.
- adev (crates.io) — a project-aware Android developer CLI that walks into any repo and knows its
test,install,launch, andcleancommands. - dab (crates.io) — an Android device/ADB CLI for installing, inspecting, and managing apps and devices.
Building a tool on androkit? Open a PR to add it here.
The library never prints, colors, or prompts. Every function returns data
([serde]-serializable structs or plain values) or a Result; the calling CLI
owns all rendering and interaction.
| Module | What it does |
|---|---|
adb |
Device discovery, app lifecycle (install, launch, stop, clear), logcat, screenshots/recording, permissions, Wi-Fi/USB. |
apk |
APK / XAPK / APKM metadata extraction (aapt/aapt2 with a ZIP-structure fallback). |
manifest |
Source AndroidManifest.xml parsing — finds the launcher activity and declared package. |
gradle |
Locate and invoke the Gradle wrapper, with a tasks-introspection fallback. |
project |
Static project discovery: modules, build variants, applicationId, launcher activity — without running Gradle. Results are cached and invalidated by build-file mtimes. |
model |
serde-serializable data types shared across the above. |
exec |
Command-execution helpers (captured + streaming). |
use androkit::project;
let project = project::discover(std::path::Path::new("."))?;
println!("app id: {:?}", project.application_id);
println!("variants: {:?}", project.variants.iter().map(|v| &v.name).collect::<Vec<_>>());
if let Some(variant) = &project.default_variant {
println!("install task: {}", project.install_task(variant)); // installDevDebug
println!("test task: {}", project.unit_test_task(variant)); // testDevDebugUnitTest
}
# Ok::<(), anyhow::Error>(())project::discover parses settings.gradle[.kts] and each module's
build.gradle[.kts] statically (no JVM warmup) so the inner loop stays fast. It
handles the conventional Groovy and Kotlin DSL shapes. Known limitations,
surfaced rather than hidden:
- Build types
debugandreleaseare always assumed to exist. - Product-flavor
applicationIdoverrides/suffixes are not applied to the base id. - Deeply dynamic Gradle (variables,
buildSrcconventions) may need thegradle::Gradle::tasksintrospection fallback.
- Rust 1.74+
adbonPATHfor theadbmodule;aapt/aapt2for full APK metadata.
MIT