How to Analyze Android Application Code: 5 Techniques for Reverse Engineering APKs
The Android Reverse Engineering skill provides a complete, script-driven workflow for decompiling Android packages and extracting HTTP APIs by combining decompilation engines like jadx and Fernflower with manifest-driven entry-point discovery and pattern-based grep analysis.
Reverse engineering Android applications requires systematic analysis to understand internal API structures and execution flows. The SimoneAvogadro/android-reverse-engineering-skill repository automates this process through a five-phase workflow that transforms binary APKs into readable Java sources and documented API catalogs. This guide explores the specific techniques and tools used to analyze Android application code, from initial dependency verification to final endpoint extraction.
The Five-Phase Analysis Workflow
The repository structures its analysis into five discrete phases, each implemented through specific shell scripts and reference documents that handle different aspects of the reverse engineering process.
Phase 1: Dependency Verification
Before decompilation begins, the workflow validates that the required toolchain is present. The scripts/check-deps.sh script detects the operating system and package manager, verifying the presence of Java JDK 17+, jadx, and optional components like Fernflower/Vineflower or dex2jar. When dependencies are missing, scripts/install-dep.sh provides portable installation commands with user-friendly hints, ensuring the environment is ready to analyze Android application code reliably.
Phase 2: APK Decompilation
The scripts/decompile.sh wrapper orchestrates the transformation of APK, XAPK, JAR, and AAR files into readable Java or Kotlin source. By default, the script uses jadx, a fast Android-aware decompiler that handles resources and smali code simultaneously. For higher-quality output on complex generics and lambda expressions, the script can alternatively invoke Fernflower or Vineflower. The --deobf flag enables automatic deobfuscation, generating readable class and method names even when the original code was processed by ProGuard or R8.
Phase 3: Structure Survey
Once decompiled, the survey phase inspects AndroidManifest.xml to identify the application's entry points, permissions, and component structure. Analysts grep for activity and service declarations (android:name attributes) and scan package hierarchies to detect architectural patterns like MVVM, MVP, or Clean Architecture. This structural mapping, documented in SKILL.md, provides the foundation for understanding how components interact before tracing specific execution paths.
Phase 4: Call-Flow Tracing
According to references/call-flow-analysis.md, this phase follows execution from UI entry points down to network requests through several specific techniques:
- Entry-point mapping: Starting from manifest-declared activities, services, and broadcast receivers identified by grepping for
android:name - Lifecycle tracking: Following
onCreate,onResume, andonViewCreatedmethods to initialization logic - Event handler location: Finding click handlers through
setOnClickListenerandonClickimplementations - Dependency injection resolution: Tracing Dagger or Hilt bindings by searching for
@Inject,@Provides, and module declarations to determine which implementation serves a given interface - String literal anchoring: Using hard-coded URLs, API keys, or header names as immutable anchors when surrounding code is obfuscated, since ProGuard and R8 never obfuscate string constants
Phase 5: API Extraction and Documentation
The final phase uses scripts/find-api-calls.sh to execute pattern-based grep searches across decompiled sources, targeting specific networking libraries. The script recognizes signatures for Retrofit annotations (@GET, @POST), OkHttp builder patterns, Volley request constructors, and raw HttpURLConnection usage. Discovered endpoints are formatted into a consistent Markdown template documenting method, path, base URL, parameters, headers, and response types, creating a complete API catalog from the binary.
Core Reverse Engineering Techniques
When you analyze Android application code using this toolkit, you employ seven fundamental techniques that handle obfuscation, library diversity, and complex control flows:
Decompilation with jadx: Handles multi-format inputs (APK, XAPK, AAR) directly while preserving resource references and offering GUI and CLI modes.
Optional Fernflower/Vineflower: Provides higher-fidelity Java output for complex inheritance chains and generic types that jadx may simplify incorrectly.
Manifest-driven entry-point discovery: Guarantees complete coverage of application components even when class names are mangled or reflection obscures instantiation.
Dependency-injection tracing: Resolves interface implementations to concrete classes by parsing Dagger/Hilt modules, essential for understanding which ApiService implementation is actually invoked.
String-literal anchoring: Exploits the fact that string constants survive obfuscation, allowing analysts to search for domain names, endpoint paths, or authentication headers to locate relevant network code.
Pattern-based grep for library signatures: Uses specific regex patterns defined in references/api-extraction-patterns.md to distinguish between Retrofit service interfaces, OkHttp interceptors, Volley request queues, and WebView JavaScript bridges.
Automated documentation templates: Enforces consistent API documentation formatting that captures HTTP method, path, authentication requirements, and source location in the call flow.
Practical Usage Examples
Run the full decompilation with automatic deobfuscation using jadx:
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh --deobf myapp.apk
Compare outputs from both decompilation engines to maximize code readability:
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh --engine both --deobf myapp.apk
Extract only Retrofit-defined API endpoints from decompiled sources:
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh output/sources/ --retrofit
Search for hard-coded URLs and potential authentication tokens:
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh output/sources/ --urls --auth
Manually locate Retrofit service methods using grep:
grep -rn '@GET\|@POST\|@PUT\|@DELETE\|@PATCH\|@HEAD' output/sources/
Identify OkHttp request construction patterns:
grep -rn 'Request\.Builder\|HttpUrl\|\.newCall\|\.enqueue\|addInterceptor' output/sources/
Summary
- The SimoneAvogadro/android-reverse-engineering-skill repository implements a five-phase workflow to analyze Android application code through dependency verification, decompilation, structure survey, call-flow tracing, and API extraction.
- jadx serves as the primary decompiler with automatic deobfuscation support, while Fernflower/Vineflower offer higher-quality Java output for complex codebases.
- Call-flow tracing combines manifest analysis, lifecycle method tracking, and dependency-injection resolution to map execution paths from UI events to network requests.
- String-literal anchoring exploits the immutability of string constants in obfuscated code to locate API endpoints and authentication mechanisms.
- The
find-api-calls.shscript automates endpoint extraction through pattern-based grep targeting Retrofit, OkHttp, Volley, and raw HTTP connection implementations.
Frequently Asked Questions
What tools are required to analyze Android application code according to the repository?
The workflow requires Java JDK 17+, jadx for primary decompilation, and optionally Fernflower or Vineflower for alternative Java output. The scripts/check-deps.sh file validates these dependencies and scripts/install-dep.sh provides installation commands for various package managers. These tools enable the transformation of binary APKs into readable sources suitable for API extraction.
How does the workflow handle obfuscated Android code?
The repository handles obfuscation through multiple techniques. The decompile.sh script accepts a --deobf flag that activates jadx's deobfuscation features to generate readable names for mangled classes and methods. Additionally, string-literal anchoring searches for hard-coded URLs and API keys that survive ProGuard and R8 obfuscation, while dependency-injection tracing resolves obfuscated interface bindings by analyzing Dagger and Hilt module annotations.
What is the difference between jadx and Fernflower for Android decompilation?
jadx is an Android-specific decompiler that handles APK, XAPK, JAR, and AAR formats directly while preserving Android resources and smali mappings, making it faster for Android-specific analysis. Fernflower and Vineflower are general-purpose Java decompilers that often produce higher-quality output for complex generics, lambda expressions, and intricate inheritance patterns, though they require conversion to JAR format first. The repository's decompile.sh wrapper can run both engines and compare results.
How do you locate HTTP API endpoints in decompiled Android sources?
The repository uses pattern-based grep through the find-api-calls.sh script to locate endpoints. For Retrofit, it searches for annotations like @GET and @POST; for OkHttp, it targets Request.Builder and addInterceptor calls; for Volley, it identifies RequestQueue implementations. The script also searches for hard-coded URLs using regex patterns defined in references/api-extraction-patterns.md, allowing analysts to extract complete API catalogs even when networking code is scattered across multiple classes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →