| name | apktool |
| description | Decode, modify, and rebuild Android APK files with the `apktool` CLI (v3.x). Use when reverse-engineering an APK, decompiling resources/manifest to readable XML and smali, editing strings/layouts/AndroidManifest.xml/smali bytecode, rebuilding an APK after edits, signing a rebuilt APK so it installs, or installing system framework files. Triggers on mentions of 'apktool', 'decompile APK', 'decode APK', 'rebuild APK', 'smali', 'baksmali', 'AndroidManifest editing', 'resources.arsc', or 'reverse engineer Android app'. Covers the full decode → edit → build → align → sign loop and the common 'app not installed' / framework-resource errors. |
apktool
Overview
apktool decodes a binary Android APK into human-readable resources (XML, PNGs, AndroidManifest.xml) and disassembled Dalvik bytecode (smali), lets you edit them, then rebuilds a working APK. It does not give you Java source — for that you need a decompiler (jadx). Use apktool to inspect/patch resources and smali, and to repackage.
Core mental model: apktool <command> [options] <input>. The lifecycle is a loop:
decode (d) → edit files → build (b) → zipalign → sign → install
The #1 gotcha: apktool strips the original signature. A freshly built APK will not install ("App not installed" / INSTALL_PARSE_FAILED_NO_CERTIFICATES) until you align and re-sign it. Building is never the last step — signing is. See Signing.
Commands
| Command | Purpose |
|---|
apktool d <apk> | Decode APK → folder of resources + smali |
apktool b <dir> | Build edited folder → APK (in <dir>/dist/) |
apktool if <apk> | Install a framework APK (e.g. framework-res.apk) |
apktool version | Print version |
Global flags: -v/--verbose, -q/--quiet. Run apktool d / apktool b with no args to see per-command options.
Decode
apktool d app.apk
apktool d app.apk -o out_dir
apktool d -f app.apk -o out_dir
apktool d -s app.apk
apktool d -r app.apk
What you get:
AndroidManifest.xml — decoded to plain XML
res/ — layouts, drawables, values/strings.xml, etc.
smali/, smali_classes2/, … — disassembled bytecode (one folder per classes.dex)
apktool.yml — metadata (version codes, SDK, do-not-compress list). Keep it — build reads it; building fails with NoSuchFileException: ./apktool.yml if run from the wrong directory.
assets/, lib/, unknown/ — passed through
Edit
Build
apktool b app
apktool b app -o patched.apk
apktool b -f app
Run from outside the decoded dir (or pass the dir). Output lands in <dir>/dist/ by default.
Signing (REQUIRED after every build)
A built APK is unsigned and won't install. Align first, then sign. The modern tool is apksigner (Android SDK build-tools); jarsigner (bundled with the JDK) is the fallback.
1. Generate a debug keystore once (reuse it forever):
keytool -genkeypair -v -keystore ~/.android-debug.keystore \
-alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 \
-storepass android -keypass android \
-dname "CN=Android Debug,O=Android,C=US"
2a. Preferred — apksigner (handles alignment ordering for you):
zipalign -p -f 4 patched.apk patched-aligned.apk
apksigner sign --ks ~/.android-debug.keystore \
--ks-pass pass:android --out patched-signed.apk patched-aligned.apk
apksigner verify patched-signed.apk
2b. Fallback — jarsigner (JDK only, no Android SDK needed):
jarsigner -keystore ~/.android-debug.keystore -storepass android \
patched.apk androiddebugkey
zipalign -f 4 patched.apk patched-signed.apk
With jarsigner, zipalign comes after signing. With apksigner, zipalign comes before. Getting this order wrong produces a corrupt/unaligned APK.
apktool, apksigner, and zipalign are not on this machine's PATH (only keytool/jarsigner from openjdk are). zipalign/apksigner ship in Android SDK build-tools/<version>/; add that dir to PATH or use full paths.
3. Install:
adb install -r patched-signed.apk
Frameworks
If decoding fails with Can't find framework resources for package of id: N, the APK references a vendor/system framework you must install first:
apktool if framework-res.apk
apktool d app.apk
Frameworks are cached in ~/.local/share/apktool/framework/ (or ~/Library/apktool/framework/ on macOS). Tag with -t <tag> to keep vendor sets separate; clear by deleting that dir.
Common errors
| Symptom | Cause / fix |
|---|
"App not installed", INSTALL_PARSE_FAILED_NO_CERTIFICATES | Unsigned APK — align + sign (see above). |
INSTALL_FAILED_UPDATE_INCOMPATIBLE | Signature differs from installed app — adb uninstall <pkg> first. |
NoSuchFileException: ./apktool.yml | Ran build outside the decoded dir, or apktool.yml was deleted. Pass the decoded dir. |
Can't find framework resources for package of id | Install the framework APK with apktool if first. |
Build fails on res/ after editing XML | Malformed XML or a resource ID you removed is still referenced — check the failing file path in the error. |
brut.androlib...could not decode arsc | Corrupt/obfuscated resources.arsc; try -r to skip resources, or a newer apktool. |
| Crash at runtime after smali edit but build succeeded | Smali is structurally valid but logically wrong (e.g. .locals/register count too low). Re-check register usage. |
Notes
- apktool ≠ decompiler. For readable Java, use
jadx/jadx-gui alongside it.
- Keep the original APK; diffing decoded trees (
diff -r orig/ patched/) is the fastest way to verify a patch.
- Bundle/split APKs (
.apks, .aab) aren't directly handled — extract base APK first (e.g. bundletool).