Skip to content

Comments

refactor: nested dex + replace --only-main-classes with -a/--all-src#4069

Merged
IgorEisberg merged 1 commit intomainfrom
fix-dex
Jan 16, 2026
Merged

refactor: nested dex + replace --only-main-classes with -a/--all-src#4069
IgorEisberg merged 1 commit intomainfrom
fix-dex

Conversation

@IgorEisberg
Copy link
Collaborator

@IgorEisberg IgorEisberg commented Jan 15, 2026

Fixes: #4068

  • Change default mode for mDecodeSources from FULL to ONLY_MAIN_CLASSES, which is more common in normal usage.
  • Replace --only-main-classes with -a/--all-src as it's less common in normal usage, and complements -s/--no-src.
  • Add CLASSES_FILES_PATTERN to easily separate standard dex files from unknown dex files (usually loaded dynamically by the app).
  • With -a/--all-src, unknown dex files are (not matching CLASSES_FILES_PATTERN) decoded and not copied to the working folder.
  • Without -a/--all-src, unknown dex files are copied to the unknown folder to be repacked as-is.
  • Fix decoding nested dex files by using @ as a path separator placeholder in smali_ folder name.
  • Rename DuplicateDexTest to DynamicDexTest as "duplicate" dex are now impossible (unless these dex file have @ in their name, for some reason). Now it tests for success rather than validating an old bug that caused failure.

Misc optimizations:

  • Rename ResourcesDecoder to ResDecoder for simplicity and to match variable names.
  • Instantiate SmaliDecoder once and make it reusable, like ResDecoder.
  • Separation of concerns: Let SmaliDecoder record handled mDexFiles and the minimal mInferredApiLevel to be later used by ApkDecoder.
  • Change condition for saving inferred API level from "if no resources" to "if no manifest or if decoded without resources", as minSdkVersion is only decoded from AndroidManifest.xml, not resources.arsc.
  • Instantiate SmaliBuilder once and make it reusable.
  • Instantiate AaptInvoker once for consistency with ResDecoder.
  • Optimize Directory by using separator (String) and separatorChar (char), like File class, to avoid concatenation of different data types by an implicit StringBuilder.
  • Use some shorter variable names for readability, like RAW_DIRS, *_FILES_PATTERN, resFileMap and resZip.
  • Normalized test APK names with underscores for consistency.
  • Removed unnecessary sConfig.setForced(true) in tests, use separate folders instead for easier analysis in case of failure.
  • Some minor cleanup.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the handling of nested/dynamic dex files and replaces the --only-main-classes CLI option with -a/--all-src. The default decoding mode changes from decoding all sources to only decoding standard classes*.dex files, which is more typical for normal usage. Dynamic dex files (not matching the classes*.dex pattern) are now handled differently: with -a they're decoded, without it they're copied to the "unknown" folder. The PR also fixes nested dex file decoding by using @ as a path separator placeholder in smali folder names.

Changes:

  • Default decode mode changed from FULL to ONLY_MAIN_CLASSES; CLI option inverted from --only-main-classes to -a/--all-src
  • Nested dex files supported by replacing path separators with @ in folder names during decode, reversed during build
  • SmaliDecoder and SmaliBuilder refactored to be reusable across multiple dex files

Reviewed changes

Copilot reviewed 23 out of 27 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
brut.j.dir/.../Directory.java Added separatorChar constant alongside separator String for performance
brut.j.dir/.../AbstractDirectory.java Uses separatorChar for indexOf operations
brut.j.dir/.../ZipRODirectory.java Uses separatorChar for indexOf operations
brut.apktool/.../Config.java Changed default mDecodeSources from FULL to ONLY_MAIN_CLASSES
brut.apktool/.../ApkInfo.java Added CLASSES_FILES_PATTERN, renamed constants for clarity
brut.apktool/.../SmaliDecoder.java Made reusable with thread-safe mDexFiles tracking
brut.apktool/.../SmaliBuilder.java Made reusable by accepting smaliDir parameter instead of storing it
brut.apktool/.../ResDecoder.java Renamed from ResourcesDecoder for brevity
brut.apktool/.../ResFileDecoder.java Renamed resFileMapping to resFileMap
brut.apktool/.../AaptInvoker.java Removed conditional check for resources.zip existence
brut.apktool/.../ApkDecoder.java Refactored dex handling with @ separator for nested paths
brut.apktool/.../ApkBuilder.java Reverse @ separator back to path separator during build
brut.apktool/.../Main.java Replaced --only-main-classes with -a/--all-src CLI option
brut.apktool/.../TestUtils.java Optimized replace operations
brut.apktool/.../test/*.java Renamed test resources, removed setForced(true), use separate output dirs
test resources/*.apk Renamed test APK files with underscores for consistency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Owner

@iBotPeaches iBotPeaches left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you hit PR for the doc changes?

@IgorEisberg IgorEisberg merged commit 51b81f8 into main Jan 16, 2026
24 checks passed
@IgorEisberg IgorEisberg deleted the fix-dex branch January 16, 2026 14:43
@iBotPeaches iBotPeaches added this to the 3.0.0 milestone Jan 16, 2026
@IgorEisberg
Copy link
Collaborator Author

Can you hit PR for the doc changes?

Done!

Copilot AI pushed a commit to EduardoA3677/Apktool that referenced this pull request Feb 4, 2026
EduardoA3677 pushed a commit to EduardoA3677/Apktool that referenced this pull request Feb 4, 2026
* Initial plan

* fix: tighten span tag parsing (iBotPeaches#4061)

* fix: avoid assumptions about res dir (iBotPeaches#4067)

* refactor: nested dex + replace --only-main-classes with -a/--all-src (iBotPeaches#4069)

* refactor: source and tests (iBotPeaches#4071)

* chore: promote -a/--all-src to a common option (iBotPeaches#4072)

* build(deps): bump com.android.tools:r8 from 8.13.17 to 8.13.19 (iBotPeaches#4064)

Bumps com.android.tools:r8 from 8.13.17 to 8.13.19.

---
updated-dependencies:
- dependency-name: com.android.tools:r8
  dependency-version: 8.13.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* minor: TextUtils hotfix (iBotPeaches#4079)

* refactor: new BinaryXmlResourceParser, ResXmlSerializer and more (iBotPeaches#4077)

* build: migrate to modern maven publish (iBotPeaches#4073)

* build: migrate to modern maven publish

* build: move to v0.36

* build: use v33 for Java 11 min

* build: skip maven on unsupported Java versions

* chore: configure codeql manually

* build: defer maven publishing till jdk11

* chore: move publising to own file

* build(deps): bump gradle/actions from 5.0.0 to 5.0.1 (iBotPeaches#4080)

Bumps [gradle/actions](https://github.com/gradle/actions) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](gradle/actions@v5...v5.0.1)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: ensure proper locale in ResPrimitive (iBotPeaches#4084)

Signed-off-by: Salvo Giangreco <giangrecosalvo9@gmail.com>

* feat: support for API 36.1 (Baklava) (iBotPeaches#4082)

* feat: staged aliases support (iBotPeaches#4085)

* fix: framework parse performed twice (iBotPeaches#4086)

* fix: framework parse performed twice

* fix up dynamic references with calling pkgId

* Fix merge conflict markers in SmaliDecoder.java

* Fix compilation errors in SmaliDecoder and AaptInvoker

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Salvo Giangreco <giangrecosalvo9@gmail.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Igor Eisberg <8811086+IgorEisberg@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Connor Tumbleson <iBotPeaches@users.noreply.github.com>
Co-authored-by: Salvo Giangreco <giangrecosalvo9@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Baksmaling secondary dex files is broken

2 participants