base on Powerful android apk editor - aapt/aapt2 independent <details><summary> 👈 <code><i> Click arrows to expand/collapse details on this page </i></code></summary></details>
# APKEditor
### Powerful android apk resources editor
This tool uses [ARSCLib](https://github.com/REAndroid/ARSCLib) to edit any apk resources and has six main features
<details><summary><code>java -jar APKEditor.jar <b>-h</b></code></summary>
```ShellSession
$ java -jar APKEditor.jar -h
APKEditor - x.x.x
Using: ARSCLib-x.x.x
https://github.com/REAndroid/APKEditor
Android binary resource files editor
Usage:
java -jar APKEditor.jar <command> <args>
commands:
1) d | decode - Decodes android resources binary to readable json
2) b | build - Builds android binary from json
3) m | merge - Merges split apk files from directory or XAPK, APKM, APKS ...
4) x | refactor - Refactors obfuscated resource names
5) p | protect - Protects/Obfuscates apk resource
6) info - Prints information of apk
run with <command> -h to get detailed help about each command
```
</details>
#### 1- Decompile
* Decompiles resources of apk to human readable json string.
* Decompiles resources of apk to XML source code (for un-obfuscated apk only). Use ``` -t xml ```
<details> <summary><code>java -jar APKEditor.jar <b>d</b> -i path/to/your-file.apk</code></summary>
```ShellSession
$ java -jar APKEditor.jar d -i test.apk -o test_json
00.000 I: [DECOMPILE] Decompiling ...
Input: test.apk
Output: test_json
----------------------------
00.036 I: [DECOMPILE] Loading ...
00.129 I: [DECOMPILE] Decompiling to json ...
30.093 I: [DECOMPILE] Done
```
</details>
#### 2- Build
Builds back to apk from decompiled json/XML files
<details> <summary><code>java -jar APKEditor.jar <b>b</b> -i path/to/decompiled-directory</code></summary>
```ShellSession
$ java -jar APKEditor.jar b -i test_json -o test_edited.apk
00.000 I: [BUILD] Building ...
Input: test_json/base
Output: test_edited.apk
----------------------------
00.048 I: [BUILD] Scanning directory ...
00.247 I: [BUILD] Writing apk...
22.032 [BUILD] Writing: method=STORED total=284921526 bytes : resources.arsc
25.009 I: [BUILD] Zip align ...
27.101 I: [BUILD] Saved to: test_edited.apk
30.217 I: [BUILD] Done
```
</details>
#### 3- Merge
Merges multiple splitted apk files (directory, xapk, apkm, apks ...) to standalone apk
<details> <summary><code>java -jar APKEditor.jar <b>m</b> -i path/to/input</code></summary>
```ShellSession
$ java -jar APKEditor.jar m -i apk_files
00.049 I: [MERGE] Merging ...
Input: apk_files
Output: apk_files_merged.apk
----------------------------
00.050 I: [MERGE] Searching apk files ...
00.060 I: [MERGE] Found apk files: 3
00.192 I: [MERGE] Found modules: 3
00.302 I: [MERGE] Merging: base
00.307 I: [MERGE] Added [base] classes.dex -> classes.dex
00.308 I: [MERGE] Merging resource table: base
01.302 I: [MERGE] Merging: config.xxhdpi-1
01.304 I: [MERGE] Merging resource table: config.xxhdpi-1
01.386 [MERGE] tum_ic_visibility_white_24.png
01.386 I: [MERGE] Merging: config.arm64_v8a-1
01.390 [MERGE] : lib/arm64-v8a/libnativeai.so
01.475 I: [MERGE] Sanitizing manifest ...
01.478 I: [MERGE] Removed: extractNativeLibs
01.480 I: [MERGE] Removed: isSplitRequired
01.480 I: [MERGE] Writing apk...
03.686 [MERGE] Writing: total=47693672 bytes : resources.arsc
03.729 I: [MERGE] Zip align ...
04.611 I: [MERGE] Saved to: apk_files_merged.apk
04.700 I: [MERGE] Done
```
![apkmerger](/.github/apkmerger.png)
</details>
#### 4- Refactor
Refactors obfuscated resource entry names
<details> <summary><code>java -jar APKEditor.jar <b>x</b> -i path/to/input.apk</code></summary>
```ShellSession
$ java -jar APKEditor.jar x -i input.apk
00.000 I: [REFACTOR] Refactoring ...
Input: input.apk
Output: input_refactored.apk
----------------------------
00.017 I: [REFACTOR] Loading apk: input.apk
00.952 I: [REFACTOR] Renamed entries: 5888
00.954 I: [REFACTOR] Writing apk ...
03.268 [REFACTOR] Writing: total=47589184 bytes : resources.arsc
03.350 I: [REFACTOR] Zip align ...
03.504 I: [REFACTOR] Saved to: input_refactored.apk
03.504 I: [REFACTOR] Done
```
</details>
#### 5- Protect
Protects apk resources against almost all known decompile/modify tools.
<details> <summary><code>java -jar APKEditor.jar <b>p</b> -i path/to/input.apk</code></summary>
```ShellSession
00.026 I: [PROTECT] Protecting ...
Input: test.apk
Output: test_protected.apk
----------------------------
00.027 I: [PROTECT] Loading apk file ...
00.052 I: [PROTECT] Protecting files ..
00.454 I: [PROTECT] Protecting resource table ..
00.474 I: [PROTECT] Writing apk ...
02.264 [PROTECT] Writing: total=47654392 bytes : resources.arsc
02.346 I: [PROTECT] Zip align ...
02.451 I: [PROTECT] Saved to: test_protected.apk
02.451 I: [PROTECT] Done
```
</details>
#### 6- Info (⭐NEW⭐)
Prints/dumps from basic up to detailed information of apk.
<details> <summary><code>java -jar APKEditor.jar <b>info</b> -v -resources -i input.apk </code></summary>
```ShellSession
Package name=com.mypackage id=0x7f
type string id=1 entryCount=1
resource 0x7f010000 string/app_name
() My Application
(-de) Meine Bewerbung
(-ru-rRU) Мое заявление
type mipmap id=2 entryCount=1
resource 0x7f020000 mipmap/ic_launcher_round
() res/mipmap/ic_launcher_round.png
type drawable id=3 entryCount=1
resource 0x7f030000 drawable/ic_launcher
() #006400
```
</details>
---
***Build executable jar***
<details> <summary> <code> ./gradlew fatJar </code> </summary>
```ShellSession
# NB: Due to my lazyness , the dependency ARSCLib.jar is pre-built and placed under APKEditor/libs/ARSCLib.jar or you can build yourself and replace it.
git clone https://github.com/REAndroid/APKEditor
cd APKEditor
./gradlew fatJar
# Executable jar will be placed ./build/libs/APKEditor-x.x.x.jar
```
</details>
***Downloads***
* [Latest release with pre-built executable jar](https://github.com/REAndroid/APKEditor/releases/latest)
***Contribute***
* Everyone is so welcome in this project, if you have some code improvements please make a pull request
* Please share your ideas / thoughts in [discussions](https://github.com/REAndroid/APKEditor/discussions)
* Please create issue you faced while using this tool along with your apk
<details> <summary><i><b>Contact</b></i></summary>
* Telegram: [@kikfox](https://t.me/kikfox)
* Email: [
[email protected]](mailto:
[email protected])
</details>
", Assign "at most 3 tags" to the expected json: {"id":"11512","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"