A complete, self-contained reference for modifying Android APKs — from decompilation to adding features, signing, testing, and local delivery. Covers split APKs, GApps, signing schemes, and dynamic analysis. No Xposed/LSPatch dependency.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
A complete, self-contained reference for modifying Android APKs — from decompilation to adding features, signing, testing, and local delivery. Covers split APKs, GApps, signing schemes, and dynamic analysis. No Xposed/LSPatch dependency.
Apktool < 2.9.0 — Cannot handle API 34+ resources. Decompilation of Android 14+ APKs will crash with obscure AAPT errors or produce corrupted resources.arsc output.
Apktool < 2.6.0 — Uses legacy AAPT (v1) instead of AAPT2. Causes massive resource recompilation failures with any app using AndroidX, Material Components, or modern resource features.
smali < 3.0.5 — Cannot disassemble DEX format 038+ (Android 13+). baksmali will fail with "Unsupported DEX format" on any app compiled with minSdkVersion 33+.
jarsigner (any version) — Only produces v1 (JAR) signatures. Modern Android (7.0+) requires at minimum v2 signatures. Using jarsigner will result in INSTALL_PARSE_FAILED_NO_CERTIFICATES or silent signature rejection.
# Step 1: Analyze with jadx first (understand what you're modifying)
jadx-gui target.apk # GUI for exploration
# or
jadx -d analysis_output/ target.apk # CLI
# Step 2: Decompile with apktool
apktool d target.apk -o decompiled/ -f
# -f = force overwrite existing output directory
# --api 35 = force target API level (use if resource errors occur)
# Step 3: Make modifications
# - Edit smali files in decompiled/smali*/ (Java bytecode)
# - Edit resources in decompiled/res/ (layouts, strings, drawables)
# - Edit AndroidManifest.xml (permissions, components)
# - Edit assets/ (bundled files, web content)
# Step 4: Recompile
apktool b decompiled/ -o rebuilt.apk
# Use --use-aapt2 flag if not on 2.11.0 (now default)
# Step 5: Align (CRITICAL - must be BEFORE signing)
zipalign -v -p 4 rebuilt.apk rebuilt_aligned.apk
# Step 6: Sign
apksigner sign --ks ~/.android/debug.keystore \
--ks-pass pass:android \
--key-pass pass:android \
rebuilt_aligned.apk
# Step 7: Verify
apksigner verify --verbose --print-certs rebuilt_aligned.apk
# Step 8: Install
adb install -r rebuilt_aligned.apk
2.2 Important Decompilation Flags
# Force specific API level (fixes many resource resolution issues)
apktool d target.apk -o out/ -f --api 35
# Ignore missing resources (new in 2.11.x, for XAPK/base APK decompilation)
apktool d target.apk -o out/ -f --ignore-missing-resources
# Keep original sources only (skip resources, faster)
apktool d target.apk -o out/ -f -s
# Decode only resources (skip smali, for resource-only mods)
apktool d target.apk -o out/ -f -r
# For Samsung/Android 15 framework JARs with DEX format 039
apktool d framework.jar -api 29 -o out/
# Use a custom framework file (for OEM system APKs)
apktool if /path/to/oem-framework.apk
apktool d system_app.apk -o out/ -f
# Step 1: Extract splits from bundle format
# .apks and .apkm are just ZIP files
mkdir splits/ && cd splits/
unzip ../input.apks # or .apkm
# This produces: base.apk, split_config.*.apk, toc.pb, etc.
# For .xapk, same approach:
unzip ../input.xapk
# Step 2: Merge into a single "fat APK" using APKEditor
java -jar APKEditor.jar m -i base.apk split_config.arm64_v8a.apk \
split_config.xxhdpi.apk split_config.en.apk -o merged.apk
# APKEditor intelligently merges resource tables from all splits.
# The resulting merged.apk is self-contained for decompilation.
# Step 3: Decompile the merged APK
apktool d merged.apk -o decompiled/ -f
# Step 4: Make your modifications (smali, resources, manifest)
# Step 5: Recompile
apktool b decompiled/ -o modified_base.apk
# Step 6: Align and sign (see Section 4)
zipalign -v -p 4 modified_base.apk modified_base_aligned.apk
apksigner sign --ks ~/.android/debug.keystore \
--ks-pass pass:android --key-pass pass:android \
modified_base_aligned.apk
3.3 Re-installing Modified Split APKs
Option A: Replace base APK only (recommended when possible)
If you only modified the base APK (most common scenario), you can keep the original split APKs:
# Uninstall the app first (signature mismatch will block update)
adb uninstall com.example.app
# Install base + original splits together
adb install-multiple modified_base_aligned.apk \
splits/split_config.arm64_v8a.apk \
splits/split_config.xxhdpi.apk \
splits/split_config.en.apk
Option B: Re-sign ALL APKs with the same key
If splits fail because of signature mismatch (some splits embed signature checks):
# Sign every APK with the same keystore
for apk in modified_base_aligned.apk splits/split_config.*.apk; do
apksigner sign --ks ~/.android/debug.keystore \
--ks-pass pass:android --key-pass pass:android \
"$apk"
done
# Install all at once
adb install-multiple modified_base_aligned.apk splits/split_config.*.apk
APKEditor may not merge all lib/ directories from arch splits
Manually copy missing .so files into merged APK's lib/ before decompiling
Resource conflicts during merge
Two splits define same resource ID with different values
Merge only base + arch split first, then add density/language splits one at a time
toc.pb metadata mismatch
Modified APK doesn't match original bundle metadata
Don't use bundletool for installation — use adb install-multiple directly
Feature module splits
Some splits contain code (not just resources)
Decompile the feature split separately, understand its code, and merge smali directories
Base APK decompilation produces null resources
Known apktool issue with some split APK bases
Merge with APKEditor first, or use --ignore-missing-resources flag
4. Signing: Schemes, Pitfalls, and Fix Procedures
4.1 APK Signature Schemes Explained
Scheme
Since
Mechanism
Tamper Resistance
v1 (JAR signing)
API 1 (all Android)
Signs individual file entries inside META-INF/
Weak — can strip and re-sign without app knowing
v2 (APK Signature Scheme v2)
API 24 (Android 7.0)
Binary signature block before ZIP central directory; verifies entire APK
Strong — any byte modification (even metadata) invalidates it
v3 (APK Signature Scheme v3)
API 28 (Android 9.0)
Same as v2 + supports key rotation via proof-of-rotation lineage
Same integrity + allows changing signing keys
v4 (APK Signature Scheme v4)
API 30 (Android 11)
Merkle hash tree stored separately; enables streaming verification during incremental installs
Same integrity + incremental install support
Critical rule: v2/v3 are whole-APK signatures. Modifying even a single byte of smali code, a single resource string, or even the ZIP comment field invalidates them. This is why every recompilation requires a full re-sign.
Android verification order: v4 → v3 → v2 → v1 (falls back through each level).
4.2 apksigner vs jarsigner — Why jarsigner Is Dead
Feature
apksigner
jarsigner
Signature schemes
v1, v2, v3, v4
v1 only
Whole-APK verification
Yes
No
Key rotation support
Yes (v3)
No
Required for API 24+
Yes
No — will be rejected
Alignment awareness
Yes
No
Source
Android SDK Build Tools
JDK
NEVER use jarsigner for APK signing. Period. It produces v1-only signatures that modern Android (7.0+) silently rejects or explicitly denies installation.
4.3 Proper Signing Procedure
# === Creating a Custom Keystore (one-time) ===
keytool -genkey -v -keystore ~/release.keystore \
-alias myapp \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# You'll be prompted for:
# - Keystore password (use something STRONG and memorable)
# - Key password (same or different)
# - Your name, organization, city, state, country code
# Store the keystore and passwords securely — you CANNOT change the key later
# === Using the Android Debug Keystore (for testing only) ===
# Location: ~/.android/debug.keystore
# Password: android
# Alias: androiddebugkey
# This keystore is identical on ALL Android SDK installations.
# DO NOT use for production — apps signed with it cannot be published or updated.
# === Full Signing Workflow ===
# Step 1: Align the APK (MUST be before signing)
zipalign -v -p 4 rebuilt.apk rebuilt_aligned.apk
# Step 2: Sign with apksigner (all three schemes for maximum compatibility)
apksigner sign \
--ks ~/release.keystore \
--ks-key-alias myapp \
--ks-pass pass:your_keystore_password \
--key-pass pass:your_key_password \
--v1-signing-enabled true \
--v2-signing-enabled true \
--v3-signing-enabled true \
rebuilt_aligned.apk
# Note: v4 is NOT signed here — it's computed on-demand during installation
# Step 3: Verify the signature
apksigner verify --verbose --print-certs rebuilt_aligned.apk
# Expected output:
# Verifies
# Verified using v1 scheme (JAR signing): true
# Verified using v2 scheme (APK Signature Scheme v2): true
# Verified using v3 scheme (APK Signature Scheme v3): true
# Number of signers: 1
# Step 4: Optional — Check what schemes are present
apksigner verify --print-certs -v rebuilt_aligned.apk
Disable MIUI optimization, or enable "Install via USB" in Developer Options
App installs but immediately crashes
Runtime signature self-check (PackageManager.getPackageInfo() with GET_SIGNATURES)
See Section 9.3 (Frida signature bypass) or patch smali signature check
SecurityException: Signature not valid
App explicitly checks caller signature
Patch the smali signature check, or use signature spoofing (see 6.4)
INSTALL_FAILED_INVALID_APK
APK corrupted or malformed after recompilation
Check for AAPT2 errors during build, verify zip integrity
Play Store says "App not installed"
Custom signature not recognized by Play Store
Expected — Play Store only accepts Google-signed updates for apps it manages
Splits fail with INSTALL_FAILED_SESSION_INVALID
Splits signed with different keys
Sign ALL splits with the same keystore before install-multiple
4.5 Key Rotation with v3 Signing
If you need to change signing keys (e.g., you lost your keystore):
# Sign with the NEW key, providing the OLD key's lineage
apksigner sign \
--ks new-release.keystore \
--ks-key-alias newkey \
--ks-pass pass:new_password \
--v1-signing-enabled true \
--v2-signing-enabled true \
--v3-signing-enabled true \
--lineage /path/to/lineage-file \
rebuilt_aligned.apk
# To extract lineage from the OLD keystore:
apksigner sign \
--ks old-release.keystore \
--ks-key-alias oldkey \
--ks-pass pass:old_password \
--v3-signing-enabled true \
--lineage /path/to/lineage-file \
--next-signer new-release.keystore newkey pass:new_password \
dummy.apk
Caveat: Key rotation only works if the app was PREVIOUSLY signed with v3. If the original app only has v1/v2, you're out of luck — you must uninstall and reinstall.
# Error 1: Missing AndroidX resources
error: resource 'com.example:id/material_textinput' not found
# Error 2: Styleable attribute not found
error: style attribute 'attr/layout_constraintBaseline_toBaselineOf' not found
# Error 3: AAPT2 crash
ERROR: AAPT2 aapt2(...) exited with code 1
brut.androlib.AndrolibException
# Error 4: Duplicate resource
error: resource 'style/Theme.MaterialComponents' has already been defined
# Error 5: Missing framework resource
error: resource '@android:configui_configFlags' not found
5.2 Systematic Dependency Resolution
Step 1: Install ROM-specific frameworks
For most third-party apps, Apktool's bundled framework (since 2.5.0) is sufficient. But for system apps, OEM apps, or apps that reference framework resources not in AOSP, you need:
# Install the standard Android framework (usually automatic)
apktool if framework-res.apk
# Pull framework files from a rooted device
adb pull /system/framework/ ./device_frameworks/
# Install OEM-specific frameworks
# Samsung:
apktool if device_frameworks/sec_platform_library.jar
apktool if device_frameworks/com.samsung.device.jar
apktool if device_frameworks/frameworksSamsungSDK.jar
# Xiaomi/MIUI:
apktool if device_frameworks/framework-miui-res.apk
apktool if device_frameworks/MiuiSdk.jar
apktool if device_frameworks/framework-mi.jar
# Huawei:
apktool if device_frameworks/HWExtension.jar
apktool if device_frameworks/hwsdk.jar
# OnePlus/Oplus:
apktool if device_frameworks/oplus-framework.jar
apktool if device_frameworks/oplus-res.apk
# Check what frameworks are currently installed
ls ~/.local/share/apktool/framework/
Step 2: Install shared library APKs
Some apps depend on vendor-shared library APKs:
# Find shared library APKs on device
adb shell pm list packages -f | grep shared
adb shell pm list packages -f | grep library
# Pull and install as framework
adb pull /system/app/SomeSharedLib/SomeSharedLib.apk
apktool if SomeSharedLib.apk
Step 3: Force API level to resolve resource conflicts
# If resources from newer APIs aren't found
apktool d target.apk -o out/ -f --api 35
# If dealing with legacy frameworks
apktool d target.apk -o out/ -f --api 29
Step 4: Use the ignore flag for known non-critical missing resources
# New in Apktool 2.11.x
apktool d target.apk -o out/ -f --ignore-missing-resources
5.3 AndroidX-Specific Issues
Issue A: Cross-library resource references
AndroidX migrated all android.support.* classes to androidx.* namespaces. This causes two major categories of issues:
Cross-library resource references: AndroidX libraries reference resources across package boundaries. When decompiled, these may resolve incorrectly.
R8-obfuscated resource names: When R8 shrinks an app, it may remove unused AndroidX resources. On recompilation, the remaining code may reference resources that were stripped.
Fix: Ensure Apktool 2.11.0+ is used (correctly handles AndroidX cross-references). For R8-obfuscated apps, manually add the required library .aar files as frameworks.
Issue B: Obfuscation
R8/ProGuard/DexGuard can strip resources. This is extremely hard to resolve automatically—your best options are:
Decompile the original APK without modification and immediately recompile (if that fails too, it's a tool limitation)
Manually add the missing resource definition to res/values/ files
Use --ignore-missing-resources and accept that some features may break
5.4 AAPT2 Error Catalog
Error
Cause
Fix
resource has already been defined
Duplicate resource entry in AAPT2
Apktool 2.11.0+ handles most cases. If persists, search for duplicate definitions in res/values/*.xml
failed to compile values files
Style/attr references to undefined resources
Check attrs.xml, styles.xml, themes.xml for references to removed resources
malformed compiled jar
Samsung DEX format 039 in framework
apktool d -api 29
no resource identifier found for attribute
Missing library dependency
Install the required library APK as framework
invalid file path
Windows path length limit or special characters in resources
Move project to short path, rename files
unmarshalling resource table
Corrupted resources.arsc in original APK
Try --ignore-missing-resources, or use APKEditor to decompile instead
Error: java.nio.BufferOverflowException
Very large resource table (>2GB)
Use 64-bit Java and increase heap: JAVA_OPTS="-Xmx4g" apktool b ...
6. GApps-Dependent APKs: Patching & Workarounds
6.1 The GApps Dependency Problem
Apps that depend on Google Play Services are the hardest to patch because:
Split APK hell: Play Services is distributed as ~100+ dynamic feature modules via split APKs
Runtime signature verification: Both the OS and other GApps verify Play Services' signature at runtime
DroidGuard attestation: Google's attestation service is deeply integrated into Play Services core
Automatic updates: The Play Store auto-updates Play Services, overwriting any patches
Play Integrity API: Modern apps use Play Integrity to verify device and app integrity — impossible to fully bypass on emulators
Bottom line: Do NOT try to directly patch com.google.android.gms. It's a losing battle. Instead, use the approaches in the following sections.
6.2 Strategy 1: MicroG (Recommended for GApps-Free Patching)
MicroG is a lightweight, open-source replacement for Google Play Services.
# MicroG provides:
# - Location services (via UnifiedNlp / OpenStreetMap backends)
# - Push notifications (via ntfy or custom push servers)
# - Device registration
# - Maps API (via OpenStreetMap)
# - Limited Google account support
# MicroG does NOT provide:
# - Play Integrity passing
# - Full DroidGuard attestation
# - SafetyNet compatibility
# - All Google API parity
# - Some Play Games features
# Setup MicroG:
# 1. Download GmsCore.apk from https://github.com/microg/GmsCore/releases
# Or use "MicroG RE" (Redesign for ReVanced) for better compatibility
# 2. Install on your device/emulator
# 3. Install a push notification provider (e.g., ntfy)
# 4. Configure signature spoofing (see 6.4)
Patches for: YouTube, YouTube Music, Google Photos, etc.
Handles signature bypass, ad removal, background play, etc.
Manual patching of GApps:
The key challenge: GApps perform runtime signature verification. They check their own signature against a known Google certificate fingerprint and refuse to function if the signature doesn't match.
# The patching approach:
# 1. Decompile the app
apktool d google_app.apk -o decompiled/
# 2. Find the signature verification code
# Search smali for these patterns:
# getPackageInfo
# GET_SIGNATURES
# PackageManager
# MessageDigest
# equals (for signature comparison)
# toByteArray (for signature byte extraction)
# 3. Patch or NOP the signature check
# Common pattern in smali:
# const-string v0, "308203e3..."
# invoke-virtual {v0}, Ljava/lang/String;->getBytes()[B
# invoke-static {...}, Ljava/security/MessageDigest;->getInstance(...)L...
# # Replace with: const/4 v_result, 0x1 (return true/valid)
6.4 Strategy 3: Signature Spoofing
What it does: Makes MicroG's signature appear as the real Google Play Services signature to other apps.
AXP.OS, /e/OS, CalyxOS: Built-in with per-app control
Magisk module approach (for stock ROMs):
Patches framework.jar at runtime to allow apps to declare spoofing support
MicroG declares spoofing support in its manifest
Other apps query MicroG's signature and receive Google's signature bytes
# Install signature spoofing Magisk module:
# Search for "FakeGApps" or "sigspoof" in Magisk Modules repository
# Or use: https://github.com/microg/android_packages_apps_GmsCore/wiki/Installation
6.5 Strategy 4: Play Integrity Bypass (2025 State)
Tool
Type
Works On
Status
TrickyStore
Magisk module
Android 8+ (with Zygisk)
Active — spoofs device attestation key
Play Integrity Fix NEXT
Magisk module
Android 8+ (with Zygisk)
Active — aims for valid attestation
PIFork
Magisk module
Pre-Android 13
Active fork by osm0sis
Stack for passing Play Integrity (2025):
Root via Magisk / KernelSU / APatch
Install ZygiskNext
Install Play Integrity Fix (or NEXT/fork)
Install TrickyStore + TrickyStore Addon
Do NOT put com.google.android.gms on Magisk DenyList
CRITICAL LIMITATION: Play Integrity does NOT pass on any emulator. Emulators are detected via hardware attestation checks that cannot be spoofed in software. For Play Integrity testing, you MUST use a physical device.
7. Testing Without a Physical Device
7.1 Emulator Selection Matrix
Emulator
Root Support
ARM Translation
GApps Support
Best For
Verdict
Android Studio AVD
Magisk via rootAVD
Native (ARM images) / Translated (x86)
Google APIs / Google Play images
Dev, security testing, patch verification
Best choice
Genymotion
Built-in basic root
libhoudini (not included by default since 3.x)
Requires manual GApps flash
Professional CI/CD testing
Good for automated testing
Waydroid
Magisk via script
libndk_translation (SSE 4.2 required)
Manual via waydroid_script
Linux desktop Android apps
Good for Linux users
BlueStacks
Difficult, no Magisk
Built-in
Pre-installed
Gaming only
Not recommended for dev work
Nox
Clunky, unreliable
Built-in
Partial
Gaming/automation
Not recommended for dev work
7.2 Setting Up Android Studio AVD for APK Testing
# Step 1: Install Android Studio
# Download from https://developer.android.com/studio
# Step 2: Create an AVD (Virtual Device)
# Android Studio → Tools → Device Manager → Create Device
# Recommended configuration:
# - Device: Pixel 7 (or any recent phone profile)
# - System Image: API 35 (Android 15), x86_64 (for speed)
# OR ARM64 if testing ARM-specific native libs
# - RAM: 4096 MB minimum (8192 MB preferred)
# - AVD Name: "test_device_api35"
# Step 3: Root the AVD with rootAVD
pip3 install rootAVD
rootAVD -s test_device_api35 # Root by AVD name
# Step 4: Verify root
emulator -avd test_device_api35 -no-snapshot-load
adb shell su -c "id"
# Expected: uid=0(root) gid=0(root)
# Step 5: Install Magisk modules (if needed)
# Push module zip to device and flash via Magisk app
adb push module.zip /sdcard/Download/
# Then flash in Magisk Manager app on the emulator
# Step 6: Install your patched APK
adb install -r patched.apk
# For split APKs:
adb install-multiple base.apk split_config.arm64_v8a.apk split_config.en.apk
# Force downgrade if version conflict:
adb install -r -d -t patched.apk
# Clean install if signature mismatch:
adb uninstall com.example.app
adb install patched.apk
7.3 GApps Testing on Emulator
Option A: AVD with Google APIs image
# Create AVD with "Google APIs" system image
# Android Studio → Device Manager → Create Device
# Choose system image: "Google APIs" (not "Google Play")
# This includes Play Services but allows more flexibility
# Caveat: Pre-installed Google Play Services CANNOT be replaced
# with patched versions because the system expects Google's signature
Option B: AVD without Google APIs + MicroG (recommended for GApps-free testing)
# Create AVD with "No Google APIs" / AOSP system image
# This gives you a clean slate
# Install MicroG:
adb install GmsCore.apk
adb install ntfy.apk # Push notification provider
# Install your patched app:
adb install patched.apk
# Verify MicroG self-check:
# Open MicroG app → Self-check → All should be green (except Play Integrity)
7.4 x86 vs ARM Translation Issues
Android Studio AVD:
x86_64 images: ~10x faster than ARM emulation. Uses native x86 execution.
ARM64 images: Slower but runs ARM native libraries directly.
ARM translation: When running x86_64 image with ARM APKs, the emulator translates ARM instructions to x86 transparently.
Problem: Some native libraries (anti-tamper, anti-debug, DRM) detect the translation layer and refuse to run.
Fix: Use ARM64 system images when testing apps with ARM-specific native code that performs translation detection.
Genymotion:
Runs x86 images by default
libhoudini for ARM translation (not included since Genymotion 3.x)
When to use: Local-only testing on redroid, Waydroid, your own devices, emulators.
When NOT to use: Distributing APKs to others, publishing to Play Store.
8.1.2 Custom Keystore for Reproducible Signing
# One-time creation
keytool -genkey -v \
-keystore ~/apk-testing.keystore \
-alias testing \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# You'll be prompted for:
# - Keystore password (use something STRONG and memorable)
# - Key password (same or different)
# - Your name, organization, city, state, country code
#
# BACKUP THIS FILE. If you lose it, you'll have to uninstall and reinstall every app you ever signed.
8.1.3 The Critical Order: zipalign THEN sign
# CORRECT ORDER:
zipalign -v -p 4 rebuilt.apk rebuilt_aligned.apk # Step 1: ALIGN first
apksigner sign --ks key.keystore aligned.apk # Step 2: SIGN second
# WRONG ORDER (will break v2/v3 signatures):
apksigner sign --ks key.keystore rebuilt.apk # Signing first
zipalign -v -p 4 rebuilt.apk aligned.apk # Then aligning BREAKS the signature!
Why: v2/v3 signatures are computed over the entire APK binary, including the position of entries within the ZIP. zipalign moves entries around to 4-byte boundaries, which invalidates any signature computed before alignment.
8.1.4 Signing Split APKs with the Same Key
When testing split APKs on redroid/Waydroid, ALL splits in a bundle must share the same signing key:
# Extract splits from .apks/.apkm
unzip input.apks -d splits/
# Align all APKs
for apk in splits/*.apk; do
zipalign -v -p 4 "$apk" "${apk%.apk}_aligned.apk"
done
# Sign ALL splits with THE SAME key
for apk in splits/*_aligned.apk; do
apksigner sign \
--ks ~/apk-testing.keystore \
--ks-key-alias testing \
--ks-pass pass:your_password \
--key-pass pass:your_password \
"$apk"
done
# Install all at once via ADB
adb install-multiple splits/base_aligned.apk \
splits/split_config.arm64_v8a_aligned.apk \
splits/split_config.en_aligned.apk
8.1.5 uber-apk-signer: All-in-One Alternative
If you want to skip the manual zipalign + apksigner dance:
Keystore was tampered with, or password was incorrect
Verify with keytool -list
Not aligned at all
App installs but runs slow; INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION on some ROMs
Always run zipalign -v -p 4
Missing v2 scheme on API 24+
Silent rejection or INSTALL_PARSE_FAILED_NO_CERTIFICATES
apksigner defaults to v1+v2; verify with apksigner verify -v
Best Practices
Always backup the original APK: Keep an unmodified copy before any patching—recovery is impossible without it.
Test on multiple Android versions: Verify compatibility across API levels (e.g., 29, 33, 35) before distribution.
Use proper signing keys (don't lose them): Store keystore files securely with strong passwords; losing your key means you can never update the app.
Keep the original package name unless deliberately changing it: Changing package name creates a new app identity, preventing updates.
Verify split APK alignment: Use zipalign -v -p 4 on all splits before signing; misalignment causes runtime crashes.
Test GApps-dependent APKs in an emulator first: Use Android Studio AVD or redroid to catch GApps integration issues before physical device testing.
Document all modifications made: Keep a changelog of smali/resource edits for debugging and future patches.
8.2 Redroid: Android in Docker for Headless APK Testing
8.2.1 What Is Redroid?
Redroid (Remote-android) runs a full Android system inside a Docker container. It does NOT use QEMU or virtualization — it runs Android userspace natively on the host Linux kernel using LXC primitives.
Key characteristics:
Runs as a Docker container — fully containerized, reproducible, scriptable
Root by default (uid=0 inside the container)
ADB access via TCP on port 5555
No display by default (headless) — use scrcpy for screen mirroring if needed
Supports Android 11 through 15
Perfect for CI/CD, batch testing, and automated APK validation
Install ARM translation: redroid-script.py <id> --libndk
No audio output
Expected in headless mode; use scrcpy for visual only
Magisk instability after install
Restart container 2-3 times
GPU artifacts on NVIDIA
Use software rendering (remove -v /dev/dri:/dev/dri)
8.3 Waydroid: Android Container with Desktop UI
8.3.1 What Is Waydroid?
Waydroid runs Android as an LXC container with native desktop window integration. Unlike redroid, it displays Android apps as regular windows on your Linux desktop. It requires a Wayland compositor (GNOME Wayland, KDE Plasma Wayland, Sway, Hyprland, etc.).
Key characteristics:
Android apps appear as native desktop windows
Clipboard sync between Linux and Android (Wayland only)
Audio via PulseAudio/PipeWire
Requires Wayland compositor (or nested weston for X11)
ADB access via local socket
Single Android session (not multi-container like redroid)
Waydroid relies on Mesa/GBM for GPU rendering. NVIDIA's proprietary driver doesn't use Mesa:
# Workaround 1: Force software rendering
WAYDROID_DISABLE_GPU=1 waydroid session start
# Workaround 2: Switch to integrated GPU (dual-GPU laptops)
# Use prime-select or DRI_PRIME=1
# Workaround 3: NVIDIA open kernel module 575.51.02+
# Recent reports (mid-2025) show Waydroid "works" with open driver
# But GPU acceleration may still be partial
8.3.7 Waydroid Known Issues
Issue
Workaround
NVIDIA GPU: no/flickering rendering
WAYDROID_DISABLE_GPU=1 or switch to iGPU
X11: no display
Run nested Wayland: weston & then WAYLAND_DISPLAY=wayland-1 waydroid show-full-ui
Camera not working
Very limited support (v4l2 only, no PipeWire)
Magisk flaky install
Check waydroid_script version; may need manual Magisk flash
Bluetooth/USB not working
Not natively supported
Dual GPU flickering
Force iGPU only or use software rendering
SELinux blocks Waydroid
Set permissive: sudo setenforce 0 (temp) or configure policy