iBotPeaches/Apktool
64.0
Adequate · 24 September 2026
15k
lines of production code
Java
primary language
5
measurements over time
What this system is
This system is a command-line tool for decompiling and rebuilding Android application packages (APKs). It handles the full lifecycle of APK analysis, including decoding resources and smali code, parsing binary structures, and rebuilding modified applications. The tool supports parallel processing for performance and provides utilities for managing Android resource metadata and XML serialization.
How it got here
2010–2012 — Pure-Java refactoring and parallelization
15 changes.
This period focused on removing native JNI dependencies for Android resource decoding, replacing them with a pure-Java implementation to improve portability and stability. The codebase was simultaneously restructured to support parallel processing of APKs, significantly enhancing performance through multi-threaded decoding and building.
2013–2024 — Build system modernization and tooling improvements
13 changes.
The project migrated its build infrastructure to Gradle Kotlin DSL with JDK 17, upgraded core dependencies like Guava and R8, and replaced the legacy aapt1 resource compiler with aapt2. Concurrently, developer experience was enhanced through platform-specific wrapper scripts, improved XML security utilities, and expanded test coverage for edge cases.
2025–2026 — Resource model refactoring and YAML parser migration
9 changes.
This period focused on restructuring the core resource table and value serialization logic into a type-safe, modular class hierarchy to improve parsing accuracy and maintainability. Concurrently, the project replaced the external YAML library with a custom, stricter parser and serializer, accompanied by extensive test coverage for both the new YAML handling and the updated resource decoding components.
Features
Add Linux wrapper script for apktool
A new executable wrapper script (scripts/linux/apktool) has been added to allow users to invoke apktool directly via the command line instead of using 'java -jar apktool.jar'. The script automatically detects and uses the highest versioned apktool\\.jar file in the directory, sets a default maximum heap size of 1GB, forces UTF-8 encoding, and supports passing custom Java options via the -J flag.
scripts/linux · high confidence
Add common exception and logging utilities
The brut.j.common module now includes a new BrutException class for standardized error handling and a Log utility class that provides convenient methods for debug, info, warning, and error logging via the standard Java Logger. Additionally, an Apache 2.0 license header template has been added to standardize file headers across the project.
brut.j.common · high confidence
Added macOS wrapper script for automatic APKTool version selection
A new executable wrapper script (scripts/osx/apktool) has been added to allow users to invoke the tool directly as 'apktool' instead of using 'java -jar'. This script automatically detects and uses the highest available version of the apktool jar file in the directory, eliminating the need to manually manage jar filenames. It also configures the Java runtime with a 1GB maximum heap size, forces UTF-8 encoding, and sets specific JVM flags to handle larger APKs and zip file structures more robustly.
scripts/osx · high confidence
Apktool now supports parallel decoding and building
The decode and rebuild operations in the library now run in parallel using a configurable number of worker threads. This is controlled by the 'jobs' setting in the Config object (defaulting to the number of available processors, capped at 8), which allows users to significantly speed up the processing of large APKs by utilizing multiple CPU cores during both the smali/binary decoding and the resource/aapt building phases.
brut.apktool/apktool-lib/src/main/java/brut/androlib · high confidence
New XML pull utility for consistent event copying
A new \XmlPullUtils\ class has been added to the \brut.j.xml\ module to provide a robust utility for copying XML pull parser events to a serializer. This utility handles edge cases such as duplicate START\_DOCUMENT events and normalizes empty namespace strings to null, ensuring consistent XML output across different parser implementations.
brut.j.xml/src/main/java/brut/xmlpull · high confidence
New XML resource serialization and encoding utilities
Apktool introduces a new set of classes in the \brut.androlib.res.xml\ package to handle XML resource encoding and serialization. \ResStringEncoder\ manages the encoding of raw and styled strings, including proper handling of spans and attributes, while \ResXmlSerializer\ provides a custom implementation of \XmlSerializer\ for writing XML output with namespace support. \ResXmlUtils\ offers helper methods for modifying AndroidManifest.xml and network security configurations, such as setting debug flags or adjusting trust anchors. These components are coordinated via the \ValuesXmlSerializable\ interface, which defines how resource entries should be serialized to XML.
brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml · high confidence
New resource data model classes for Android binary parsing
Added new classes in the resource data package to support parsing and representing specific Android resource structures: FeatureFlag for handling feature flags, LayoutBounds and NinePatchData for reading layout and nine-patch binary data, ResChunkHeader for defining resource chunk types (including staged aliases and flags), ResStringPool for optimized string pool parsing with UTF-8 support, and StyledString for representing styled text with spans.
brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data · high confidence
Repository initialization and project scaffolding
The repository has been initialized with standard project configuration files, including a \.editorconfig\ for consistent code formatting, a \.gitattributes\ file to manage line endings and binary file handling, and an updated \.gitignore\ that excludes Gradle build artifacts, IDE settings, and temporary files. Additionally, the project now includes a \SECURITY.md\ file outlining the process for reporting vulnerabilities, a \ROADMAP.md\ detailing future development goals, a \CONTRIBUTORS.md\ listing project contributors, and an \INTERNAL.md\ guide for maintainers on the release and publishing process.
(repo-wide) · high confidence
Secure XML parsing utilities added
A new XmlUtils class has been introduced to provide safe XML document handling. It configures the underlying parser to disable external DTD loading and DOCTYPE declarations, and restricts access to external schemas and DTDs, mitigating XXE and BPE vulnerabilities. The utility offers methods to parse XML from strings or files, save documents to files, and evaluate XPath expressions against the parsed DOM.
brut.j.xml/src/main/java/brut/xml · high confidence
Removals
Removal of JNI-based resource decoding support
The JNI-based resource decoding implementation has been removed. This change deletes the \src/brut/androlib/res/jni\ package (including \JniConfig\, \JniEntry\, \JniPackage\, \JniType\, and \JniBagItem\) and the core resource data model classes in \src/brut/androlib/res/data\ (such as \ResConfig\, \ResConfigFlags\, \ResID\, \ResPackage\, \ResResSpec\, \ResResource\, \ResTable\, \ResType\, and \ResValuesFile\). Users will no longer be able to decode Android resources using the native JNI backend; the tool now relies exclusively on its pure Java implementation.
src/brut/androlib/res/data · high confidence
Removal of legacy resource value classes and JNI decoding support
The \src/brut/androlib/res/data/value\ directory has been completely removed, deleting all legacy resource value classes (such as \ResArrayValue\, \ResAttr\, \ResBagValue\, \ResStringValue\, and \ResValueFactory\) and the \ResXmlSerializable\ interface. This change also removes the dependency on JNI-based resource decoding, as the \ResValueFactory\ previously relied on \JniEntry\ and \JniBagItem\ classes to parse resource data. Users should expect that resource value handling and XML serialization logic has been refactored or moved to other parts of the codebase.
src/brut/androlib/res/data/value · high confidence
Removed legacy Androlib, AndrolibSmali, and ApkFile classes
The legacy \Androlib\, \AndrolibSmali\, and \ApkFile\ classes in \src/brut/androlib\ have been removed. This eliminates the previous monolithic decoding and building logic that relied on the older \AndrolibSmali\ wrapper for smali/baksmali operations and the \ApkFile\ abstraction, streamlining the library's internal structure.
src/brut/androlib · high confidence
Architecture
Removed C++/JNI-based resource decoding in favor of pure-Java implementation
The decoder module has removed the JNI-based XML decoding path and its supporting classes (JniPackageDecoder, ResXmlStreamDecoder, ResStreamDecoderContainer, ResXmlSerializer, and the old ResFileDecoder). This change eliminates the dependency on native code for parsing Android resource XML, making the decoding process platform-independent and relying entirely on pure-Java libraries (such as AXmlResourceParser) instead.
src/brut/androlib/res/decoder · high confidence
Behavioural changes
22 commits (2 fixes) modifying brut.apktool/apktool-lib/src/main/resources/prebuilt/linux
A change to existing behaviour in brut.apktool/apktool-lib/src/main/resources/prebuilt/linux — 22 commits (2 fixs), 2 files.
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux, src · medium confidence · unverified
Added ProGuard rules to support R8 and Guava upgrades
A new proguard-rules.pro file has been added to the CLI module to ensure compatibility with the recent upgrade to Guava 33.3.0 and R8 optimization. The rules preserve the main entry point and enum reflection methods, and suppress warnings for J2ObjC annotations used by Guava, preventing build failures or runtime issues when code is minified.
brut.apktool · high confidence
Apktool.yml metadata now uses a new YAML serialization format
The internal structure of the Apktool.yml file has changed to use a new YAML parser and serializer. This update reworks how metadata (such as SDK info, version details, and resource configurations) is stored and read, ensuring better compatibility and robustness when decoding or encoding APK information.
brut.apktool/apktool-lib/src/main/java/brut/androlib/meta · high confidence
Exception classes moved to a dedicated package
The exception classes used by the library (such as FrameworkNotFoundException, OutDirExistsException, RawXmlEncounteredException, UndefinedResObjectException, InFileNotFoundException, and NinePatchNotFoundException) have been moved from their previous locations into the new brut.androlib.exceptions package. This reorganization groups all error types together, making it easier for developers to locate and handle specific failure scenarios when using the library.
brut.apktool/apktool-lib/src/main/java/brut/androlib/exceptions · high confidence
Introduce new CLI entry point and version properties
The CLI module now uses a new Main.java entry point that defines the command-line interface options (such as --verbose, --quiet, --jobs, --frame-path, --all-src, --no-src, --no-res, --only-manifest, --res-resolve-mode, --keep-broken-res, --ignore-raw-values, --match-original, --no-assets, --output, --force, --no-apk, --no-crunch, --copy-original, --debuggable, --net-sec-conf, --aapt) and a new apktool.properties file that exposes the application version and git commit ID.
brut.apktool/apktool-cli · high confidence
Migration to aapt2 for resource compilation and linking
Apktool now uses aapt2 instead of aapt1 for compiling and linking Android resources. The new AaptInvoker and AaptManager classes handle the aapt2 binary (bundled for 64-bit platforms) and pass modern flags such as --legacy, --feature-flags, and --no-auto-version. This change improves compatibility with current Android build tools and resolves issues related to stricter parsing and resource deduplication during the build process.
brut.apktool/apktool-lib/src/main/java/brut/androlib/res · high confidence
New SmaliBuilder and SmaliDecoder classes for dex handling
The smali package now includes dedicated SmaliBuilder and SmaliDecoder classes. SmaliBuilder handles the compilation of .smali files into a .dex file, enforcing a maximum API level of 29 for opcodes. SmaliDecoder manages the disassembly of APKs, supporting multi-dex containers by iterating through dex entries and decoding them into separate directories, while also inferring the API level from the dex opcodes.
brut.apktool/apktool-lib/src/main/java/brut/androlib/smali · high confidence
New custom YAML parser and serializer introduced
The application now uses a newly implemented, lightweight YAML parser and serializer (YamlPullParser, YamlSerializer) instead of the previous external library. This change provides stricter syntax validation, including specific error reporting for indentation and sequence/mapping mismatches, and handles string escaping for special characters and Unicode. Users may notice differences in how YAML files are parsed and written, particularly regarding strict indentation rules and the handling of quoted strings.
brut.j.yaml · high confidence
Refactored directory abstraction with new file and zip implementations
The \brut.j.dir\ module has been refactored to introduce a cleaner, unified directory abstraction. The core \Directory\ interface now implements \AutoCloseable\ and exposes methods to retrieve file sizes and compression levels. Two concrete implementations have been added: \FileDirectory\ for standard file-system access and \ZipRODirectory\ for read-only access to ZIP archives, which now explicitly filters out entries containing \..\ to prevent path traversal. Additionally, a new \ExtFile\ wrapper class has been introduced to automatically manage the lifecycle of these directory resources, ensuring they are closed when the file object is deleted or garbage collected.
brut.j.dir · high confidence
Refactored resource decoding architecture with new parsers and handlers
The resource decoding subsystem has been restructured to improve maintainability and parsing accuracy. The package now introduces dedicated parsers like BinaryResourceParser and BinaryXmlResourceParser to handle ARSC and AXML chunks, replacing the previous monolithic approach. A new ResChunkPullParser manages low-level chunk iteration, while ResFileDecoder orchestrates the selection of appropriate decoders (such as ResNinePatchStreamDecoder for 9-patch images and ResXmlPullStreamDecoder for XML) based on file extensions. Additionally, a new event-driven model using ResXmlPullEventHandler and ManifestPullEventHandler allows for more granular processing of XML attributes, such as extracting SDK and version information from the manifest.
brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder · high confidence
Refactored resource table model with new type-safe entry and ID classes
The resource table parsing logic has been restructured to use a new set of model classes in the \brut.androlib.res.table\ package. \ResId\ now provides a type-safe wrapper for resource identifiers with caching, while \ResEntrySpec\ and \ResEntry\ separate resource metadata from their values. \ResConfig\ centralizes configuration constants, and \ResOverlayable\ handles overlayable resource policies. \ResPackage\ and \ResPackageGroup\ manage the hierarchy of resource packages, and \ResTypeSpec\ validates type names against standard Android formats. This refactoring improves the internal structure and validation of parsed resources.
brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table · high confidence
Refactored resource value serialization with dedicated type classes
The resource value serialization logic has been restructured into a hierarchy of dedicated classes (ResArray, ResAttribute, ResEnum, ResFlags, ResPlural, ResPrimitive, ResReference, ResString, and ResCustom) under the \brut.androlib.res.table.value\ package. This change improves the accuracy of \values.xml\ output by handling specific resource types more precisely, such as correctly inferring typed array formats (e.g., \string-array\), properly serializing attribute enums and flags with their symbols, and ensuring correct locale handling for primitive values. Users will see more faithful decompilation of complex resources like plurals, arrays, and custom attributes, with better support for feature flags and unresolved symbol injection.
brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value · high confidence
Refactored utility library with new background worker and hardened I/O
The brut.j.util package has been restructured into a set of focused utility classes. A new BackgroundWorker class provides a thread-safe executor for managing concurrent tasks, while BrutIO and ZipUtils now use a new sanitizePath method to prevent path traversal vulnerabilities when handling file operations. OS detection and execution capabilities are consolidated in the OS and OSDetection classes, which include improved 64-bit detection for Windows. Additionally, new helper classes like BinaryDataInputStream for efficient binary reading, Pair for data pairing, and TextUtils for string and color parsing have been introduced to replace scattered logic.
brut.j.util · high confidence
Removal of JNI-based resource decoding and smali updater
The native JNI dependency for decoding Android resources (libAndroid.so) and the ResSmaliUpdater component for tagging and updating resource IDs in smali files have been removed from the src/brut/androlib/res package. This eliminates the requirement for native libraries during resource table loading and smali modification, shifting these capabilities to pure Java implementations in other parts of the codebase.
src/brut/androlib/res · high confidence
Removed JNI-based native resource decoding
The Android resource decoding implementation no longer relies on the native \libAndroid.so\ library. The Java classes \StringBlock\, \XmlBlock\, and \TypedValue\ that previously loaded this native library and delegated string and XML parsing to JNI methods have been removed, indicating a shift to a pure-Java or alternative decoding strategy for resource tables.
src/android · high confidence
Windows wrapper script now supports versioned JARs and handles spaces in paths
The Windows batch script (apktool.bat) has been updated to automatically locate and use the highest versioned JAR file in the directory, supporting semantic versioning (X.Y.Z) for better compatibility with release artifacts. It also fixes issues with spaces in file paths by properly quoting arguments, ensures Unicode support via code page 65001, and respects the JAVA\_HOME environment variable if set. Additionally, the script now correctly handles the /c command line switch to prevent unintended pauses in non-interactive environments.
scripts/windows · high confidence
Test coverage
Added test resources for APKTool regression testing; Added tests for AAPT version parsing; Added tests for APK meta-info YAML parsing and serialization; Added tests for UTF-8 surrogate pair decoding and missing div 9-patch handling; Added tests for XML value escaping and format specifier normalization; Expanded test coverage for APK decoding and building edge cases.
Dependencies
Migrate build system to Gradle Kotlin DSL and update dependencies
The build system has been migrated from Groovy to Kotlin DSL, introducing a centralized version catalog (libs.versions.toml) to manage dependencies such as R8 (9.1.31), Guava (33.7.1-jre), and Commons IO (2.22.0). The project now requires JDK 17 for the build process while maintaining Java 8 compatibility for the resulting artifacts. This change also updates the output JAR naming convention to use underscores (e.g., apktool\\.jar) and configures reproducible builds.
(dependencies) · high confidence
Upgrade Gradle Wrapper to version 9.7.1
The Gradle wrapper has been updated to version 9.7.1, changing the distribution URL to fetch the binary release from the official Gradle services. This update includes configuration for network timeouts, retry logic, and distribution URL validation to ensure a more robust build environment.
gradle · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 61 → 64 (+3.1)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 73 → 81 (+8.0)
- Architecture 100 → 97 (-3.0)
- Maturity 52 → 50 (-1.6)
- Readiness 87 → 73 (-13.5)
- Security 57 → 74 (+17.0)
Resolved (51)
- Coverage not included — suite not readable by the collector
- Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
- Duplicated block (10 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java)
- Duplicated block (10 lines × 2) (brut.j.util/src/main/java/brut/util/TextUtils.java)
- Duplicated block (11 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlUtils.java)
- Duplicated block (11 lines × 3) (brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java)
- Duplicated block (12 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/ResDecoder.java)
- Duplicated block (12 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResChunkPullParser.java)
- Duplicated block (12 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value/ResEnum.java)
- Duplicated block (13 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java)
- Duplicated block (13 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value/ResEnum.java)
- Duplicated block (13 lines × 2) (brut.j.util/src/main/java/brut/util/TextUtils.java)
- Duplicated block (14 lines × 2) (brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java)
- Duplicated block (14 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java)
- Duplicated block (7 lines × 2) (brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java)
- Duplicated block (7 lines × 2) (brut.j.util/src/main/java/brut/util/TextUtils.java)
- Duplicated block (8 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ManifestPullEventHandler.java)
- Duplicated block (8 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/ResPackage.java)
- Duplicated block (8 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/ResPackage.java)
- Duplicated block (9 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java)
- …and 31 more
New (89)
- ClassTooLong: BinaryResourceParser (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryResourceParser.java)
- ClassTooLong: BinaryXmlResourceParser (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryXmlResourceParser.java)
- ClassTooLong: Main (brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java)
- ClassTooLong: ResConfig (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/ResConfig.java)
- Dependency hygiene PARTLY measured — Maven/Gradle declarations read, no dependency graph resolved
- Documentation: no installation or build instructions (README.md)
- Duplicated block (10 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AaptInvoker.java)
- Duplicated block (10 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value/ResArray.java)
- Duplicated block (12 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AaptInvoker.java)
- Duplicated block (12 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value/ResEnum.java)
- Duplicated block (12 lines × 2) (brut.j.util/src/main/java/brut/util/TextUtils.java)
- Duplicated block (12 lines × 3) (brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java)
- Duplicated block (13 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryResourceParser.java)
- Duplicated block (14 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java)
- Duplicated block (14 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value/ResPrimitive.java)
- Duplicated block (16 lines × 2) (brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java)
- Duplicated block (16 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value/ResEnum.java)
- Duplicated block (16 lines × 3) (brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java)
- Duplicated block (16 lines × 3) (brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/value/ResEnum.java)
- Duplicated block (18 lines × 2) (brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java)
- …and 69 more
Changes since last survey
- 14 commits — 10 feature/other, 4 fixes
By area
- brut.apktool/apktool-lib — 7 commits
- gradle/wrapper — 3 commits
- .github/workflows — 2 commits
- gradle/libs.versions.toml — 2 commits
Notable commits
- fix: Fix crash encoding empty raw resource strings (#4209)
- fix: fix: extend support for r/w feature flags (#4220)
- fix: fix: hotfix for yaml + extra (#4231)
- fix: fix: yaml edge case (#4232)
- change: Android 17 (API 37) - Cinnamon Bun Support (#4214)
- change: build(deps): bump actions/setup-java from 5 to 6 (#4221)
- change: build(deps): bump com.google.guava:guava from 33.6.0-jre to 33.7.1-jre (#4216)
- change: build(deps): bump gradle-wrapper from 9.6.1 to 9.7.0 (#4207)
- change: build(deps): bump gradle-wrapper from 9.7.0 to 9.7.1 (#4215)
- change: build(deps): bump gradle/actions from 6.2.0 to 6.3.0 (#4206)
- change: build(deps): bump org.xmlunit:xmlunit-legacy from 2.12.0 to 2.13.0 (#4205)
- change: chore: change gradle dist to gradle-bin (#4226)
- change: chore: new yaml parser/serializer (#4229)
- change: feat: Upgrade aapt2 to latest AOSP (Android 17) sources (#4223)
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
iBotPeaches/Apktool was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 24 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 57690eee61e394e1987c09981bd36ff171e73d8d — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-ae95d6cad036.