Command-Line Tools for Android Apps: Essential Utilities for DevelopersCommand-line tools remain indispensable in Android development. They offer speed, repeatability, automation, and fine-grained control that graphical IDEs can’t always match. This article covers the core command-line utilities Android developers should know, how to use them, practical examples, and tips for integrating them into daily workflows and CI/CD pipelines.
Why use command-line tools?
- Command-line tools are faster for repetitive tasks and scripting.
- They enable CI/CD automation and reproducible builds.
- They provide low-level control for debugging, signing, and packaging.
- They’re lightweight and work well on remote servers and containers.
Core Android command-line tools
Android SDK tools (sdkmanager, avdmanager)
- sdkmanager installs and updates SDK components (platforms, build-tools, system-images).
- Example: sdkmanager “platform-tools” “platforms;android-33” “build-tools;33.0.2”
- avdmanager creates and manages Android Virtual Devices (emulators).
- Example: avdmanager create avd -n Pixel_API_33 -k “system-images;android-33;google_apis;x86”
adb (Android Debug Bridge)
- adb is essential for interacting with devices and emulators.
- Common tasks:
- List devices: adb devices
- Install/uninstall apps: adb install app.apk | adb uninstall com.example.app
- Shell access: adb shell
- Forward ports: adb forward tcp:8000 tcp:8000
- Pull/push files: adb pull /sdcard/log.txt ./log.txt | adb push config.json /sdcard/config.json
- Use adb for automated instrumentation testing and log collection (adb logcat).
fastboot
- fastboot performs low-level operations on bootloader mode (flashing images, unlocking bootloader).
- Example: fastboot flash boot boot.img
gradle / ./gradlew
- Gradle is the primary build system for Android. Use the Gradle Wrapper (./gradlew) for consistent builds.
- Common tasks:
- Build APK/AAB: ./gradlew assembleDebug | ./gradlew bundleRelease
- Run tests: ./gradlew test | ./gradlew connectedAndroidTest
- Clean: ./gradlew clean
- Configure build flavors, signing, and proguard/R8 rules in build.gradle files. Use CI to run ./gradlew assemble and ./gradlew test.
aapt / aapt2
- aapt (Android Asset Packaging Tool) handles packaging, resource processing, and generating R.java. aapt2 is the modern replacement with improved performance.
- Use for inspecting APK contents and resources:
- aapt dump badging app.apk
- aapt2 compile/ link during custom build steps
apksigner / jarsigner
- apksigner signs APKs with modern APK Signature Scheme v2/v3.
- Example: apksigner sign –ks mykeystore.jks app.apk
- jarsigner is older and less preferred for APKs; apksigner is recommended.
bundletool
- bundletool converts Android App Bundles (.aab) into device-specific APKs (split APKs, universal APKs) and can install them on devices.
- Generate APK Set: bundletool build-apks –bundle=app.aab –output=app.apks –ks=keystore.jks –ks-pass=file:ks.pass
- Install on device: bundletool install-apks –apks=app.apks
dexdump / baksmali / smali / dex2jar
- Tools for inspecting and disassembling DEX bytecode.
- dex2jar converts DEX to JAR for easier inspection.
- baksmali/smali disassemble/reassemble DEX files for reverse engineering or patching.
zipalign
- zipalign optimizes APK file alignment to improve runtime memory usage.
- Example: zipalign -v -p 4 input.apk output-aligned.apk
monitor, systrace, perfetto
- Performance and tracing tools:
- perfetto is the modern tracing system (use via command line or UI).
- systrace collects system and application trace information (older tool—Perfetto supersedes many use cases).
lint (Android Lint)
- Run Android Lint from command line: ./gradlew lint
- Configure checks, baseline files, and fail build on warnings where appropriate.
Developer utilities and supplementary tools
jq, sed, awk, grep
- Standard Unix text-processing tools for manipulating JSON, logs, and build outputs.
- Example: adb shell dumpsys activity activities | grep “mResumedActivity”
keytool
- Java keytool manages keystores, certificates, and keys required for signing.
- Generate key: keytool -genkeypair -alias mykey -keyalg RSA -keysize 2048 -validity 10000 -keystore mykeystore.jks
curl, httpie
- For testing APIs from devices or CI, especially when running instrumentation or emulator-hosted services.
openssl
- Inspect certificates, generate keys, and check TLS configurations for backend services used by the app.
Common workflows and examples
Building and installing debug APK on emulator/device
- Build APK: ./gradlew assembleDebug
- Locate APK: app-module/build/outputs/apk/debug/app-debug.apk
- Install: adb install -r app-debug.apk
- Run logs: adb logcat *:S MyAppTag:D
Creating CI pipeline snippet (example with Gradle and apksigner)
- Steps:
- Checkout code
- Install JDK and Android SDK components via sdkmanager
- ./gradlew assembleRelease
- zipalign the release APK
- apksigner sign the APK
- Run unit and instrumentation tests
Generating device-specific APKs from an AAB
- Build AAB: ./gradlew bundleRelease
- Generate APKs: bundletool build-apks –bundle=app-release.aab –output=app.apks –ks=keystore.jks –ks-pass=file:ks.pass
- Install: bundletool install-apks –apks=app.apks
Automating resource inspection and quick fixes
- Use aapt2 to compile resources in custom scripts, or run lint in CI and parse results with jq to fail builds on critical issues.
Debugging & reverse engineering via CLI
- Extract APK: unzip app.apk -d extracted_apk
- Inspect manifest: aapt dump xmltree app.apk AndroidManifest.xml
- Convert DEX to JAR: dex2jar classes.dex
- Disassemble: baksmali disassemble classes.dex -o smali_out
- Reassemble and sign after modifications using smali -> dex -> rebuild -> apksigner
Best practices
- Use the Gradle Wrapper (./gradlew) to ensure consistent Gradle versions across environments.
- Automate repetitive tasks with shell scripts or Makefiles; keep secrets out of repo (use CI secrets).
- Prefer apksigner and bundletool for modern signing and distribution workflows.
- Keep SDK components versioned in CI via sdkmanager and accept licenses non-interactively.
- Run lint and unit tests in CI; run connectedAndroidTest or emulator-based tests selectively due to flakiness and time.
- Use zipalign and ProGuard/R8 to optimize release builds.
Troubleshooting tips
- “device not found” with adb: ensure adb server is running (adb start-server), check USB debugging, accept host key on device.
- Emulator slow: use x86 system images with HAXM/Hypervisor Framework or enable virtualization (KVM on Linux).
- Signing errors: verify keystore path, alias, and passwords; use apksigner verify to check signatures.
- Build failures after dependency updates: run ./gradlew –refresh-dependencies and inspect dependency tree with ./gradlew app:dependencies.
Toolchain roadmap (what to learn next)
- Master Gradle build scripts and custom tasks (Kotlin DSL).
- Learn bundletool and Play Console artifact management (AAB, signing by Google Play).
- Deepen knowledge of Perfetto for performance tracing and adb-based profiling.
- Learn Dockerizing Android build environments and running emulators in CI.
- Explore advanced bytecode tools (smali/baksmali, ASM) for instrumentation and analysis.
Conclusion
Command-line tools are a force multiplier for Android developers — they enable automation, reproducibility, low-level debugging, and integration with CI/CD. Mastering adb, Gradle, bundletool, apksigner, aapt2, and a few Unix utilities will cover most development and release needs. Incorporate these tools into scripts and CI pipelines to save time, reduce errors, and maintain consistent builds.
Leave a Reply