Skip to main content

apkbox

APK 工具箱:把 APK 转成能直接引入工程的 AAR,反编译出 .java,或快速看一眼 APK 里有什么。

apkbox app.apk                 # app.apk → app.aar(aar 是默认子命令)
apkbox java app.apk -o src/    # 整个 APK 反编译成 .java
apkbox info app.apk            # 包名 / 权限 / 组件 / ABI / 签名摘要

依赖

  • Python 3.9+
  • JDK 8+(java 要在 PATH 里)
  • 可选:Android SDK —— 提供 android.jar 做 AAR 的资源 link 自检,也是 aapt2 的首选来源(见下文)

就这些。wheel 只有约 40 KB、Python 侧无第三方依赖;apktool / dex-tools / aapt2 / jadx 这些工具不在包里,系统装过就直接用,没有的话首次用到时自动下载到缓存 (约 110 MB,一次性)。

安装

pip install apkbox            # 从 PyPI 装

# 或从源码 / wheel 装
pip install --break-system-packages .
pip install --break-system-packages dist/apkbox-2.1.3-py3-none-any.whl

# 不想安装,直接在源码目录跑
python3 -m apkbox --version

Debian/Ubuntu 的系统 Python 是 externally-managed,所以要加 --break-system-packages; 在 venv 里装则不需要这个参数。

工具从哪来

每个工具按这个顺序解析,找到就用,不重复造轮子:

命令行参数 > 环境变量 > 系统 PATH / Android SDK > apkbox 缓存 > 自动下载
  • 缓存目录默认 ~/.cache/apkbox(遵循 XDG_CACHE_HOME),下载前先比对 sha256,装一次后续直接复用。

  • 下载先走官方直链(GitHub releases、Google Maven),不通再换内置镜像; 设置 APKBOX_MIRROR 可以指定自己的镜像(此时镜像优先、直链兜底)。

  • 首次运行会看到类似输出,之后都是 ✓:

    tools  : apktool ✓, dex2jar 已下载, aapt2 ✓
    
  • 想提前把工具备齐(离线机、CI 预热):

    apkbox fetch                  # 全部:apktool / dex2jar / aapt2 / jadx
    apkbox fetch jadx apktool     # 指定几个
    

    fetch 每个工具下载后都会回验:能跑的打 ✓,跑不起来的打 ⚠ 并说明原因 (退出码 1)——不会下载完就报成功。

平台注意(Termux / ARM)

apktool / dex-tools / jadx 都是纯 Java,跟着 JDK 走;只有 aapt2 是平台相关的, Google 官方只提供 x86_64 Linux 版(没有 arm64,没得下)。在 ARM 设备(Termux、 树莓派、Apple Silicon)上:

  • apkbox 会先自己想办法(都不需要 root,fetch 和转 AAR 都会触发):
    • Termux:问一句后执行 pkg install aapt2
    • Debian / Ubuntu 等带 apt 的发行版:用 apt --print-uris 解析依赖,把官方 仓里的 aapt2 及其依赖下载、解包进缓存(走你自己配置的 apt 源,glibc 天然匹配)
  • 也可以手动装,装上就自动识别、优先使用:Termux pkg install aapt2、 Debian/Ubuntu apt install aapt2,或用 --aapt2 / APKBOX_AAPT2 指一个能跑的
  • 或装 qemu-x86_64 模拟跑官方版(apkbox 检测到会自动用)
  • 都不行时不会白下 2.3 MB,直接说清原因(官方版是 x86_64 二进制 / 本机 架构不符)并给上面的解法:fetch 打 ⚠ 且退出码 1;转 AAR 降级继续—— 跳过 aapt2 自检,R.txt / public.xml 缺失、资源 id 不固定(有警告),其余 产物(classes.jar / res / manifest)照常可用

环境变量:

变量 作用
APKBOX_MIRROR 镜像前缀,逗号分隔,下载地址 = 前缀 + 官方 URL(与 gh-proxy.com 同规则);设为空则只走直链
APKBOX_OFFLINE=1 禁止联网,缺工具直接报错并给出手动下载地址
APKBOX_CACHE 缓存目录(默认 ~/.cache/apkbox)
APKBOX_NO_VERIFY=1 跳过 sha256 校验(慎用)
APKBOX_APKTOOL / APKBOX_DEX2JAR / APKBOX_AAPT2 / APKBOX_JADX 分别指定工具路径
ANDROID_HOME / ANDROID_SDK_ROOT 找 aapt2 和 android.jar
APKBOX_LANG 界面语言 zh / en

当前自动下载的版本(升级时改 apkbox/fetch.py 里的 SPECS):

工具 版本 来源
apktool 2.7.0 GitHub releases(单个 fat jar)
dex-tools 2.4 GitHub releases
jadx 1.5.6 GitHub releases
aapt2 9.4.1-15978811 Google Maven(dl.google.com)

转 AAR

apkbox app.apk                                  # → app.aar(和输入同目录)
apkbox aar app.apk -o dist/app.aar --keep        # 指定输出,保留中间文件
apkbox app.apk --code-only                       # 只要 classes.jar,不带 res/assets/jni
apkbox app.apk -w work/ --skip-decode            # 复用 work/ 里已有的解包结果

流程:apktool 解包 → dex2jar 出 classes.jar(两者互不依赖,并行执行,整体快约 1–2 分钟)→ 组装 res/assets/jni(public.xml 钉死资源 id)→ 裁剪 AndroidManifest → aapt2 compile + link 自检 → 打包 .aar。

常用选项:

选项 说明
-o, --output 输出 .aar 路径(默认与 apk 同名)
-w, --work-dir 中间文件目录(默认临时目录,指定后保留)
--code-only 只要 classes.jar,不带 res/assets/jni
--keep-app-attrs 保留 <application> 的属性(默认清空以免与宿主合并冲突)
--skip-decode 复用 -w 目录里已有的 apktool 解包结果
--keep 保留临时目录
--apktool / --dex2jar / --aapt2 手动指定工具(默认按上面的顺序自动解析)
--android-jar android.jar 路径(用于 link 自检,缺省自动找 SDK)
-v, --verbose 打印每步实际执行的子命令

产物注意事项

  • 打印的 可能与宿主 Duplicate class: androidx … 是提示:这些包宿主大概率已有,合并前先看一眼。
  • <application> 的 android:name/icon/label/theme 默认被清空(避免和宿主合并冲突),图标、label、主题、Application 类要宿主自己设置;确实想带上用 --keep-app-attrs。
  • 没找到 android.jar 时跳过 link 自检,R.txt 按原 APK 的资源 id 生成,minCompileSdk 取原 APK 的 compileSdkVersion;找到时会尝试各平台,取能通过的最低版本。
  • native 库按 APK 原样携带:APK 里有哪些 ABI,AAR 的 jni/ 就有哪些;只有 arm 库的话 x86 模拟器跑不起来(会打印警告)。

反编译成 .java

apkbox java app.apk -o src/          # APK → src/**/*.java + resources/
apkbox java classes.dex              # 单个 dex → classes-java/
apkbox java ./smali_out/ -o src/     # 目录里挑 classes*.dex
apkbox java app.apk -r               # --no-res:只要代码,不解资源
apkbox java app.apk -j 4 --deobf     # 4 线程 + 反混淆
选项 说明
-o, --output 输出目录(默认 <输入名>-java)
-r, --no-res 不反编译资源,只出 .java
-j, --jobs 线程数(默认用 jadx 的)
--deobf 反混淆:太短/太长的类名重新命名
-e, --export-gradle 输出成 Android/Java gradle 工程
--show-bad-code 反编译不出来的代码也照样输出(带注释标记)
--jadx jadx 可执行文件/jar(默认自动解析/下载)
  • 有反编译错误时会在输出旁写一份 <输出名>.log(混淆过的 APK 出现几百处错误很常见)。
  • 进度行只在终端里刷,重定向到文件时不会刷屏。

看 APK 摘要

apkbox info app.apk
apkbox info v2.1.3
  file      : app.apk (21.2 MB)
  sha256    : 7440d842…
  dex       : 3 文件, 15.1 MB
  res       : 766 条目, assets 98, arsc 3.3 MB
  abis      : arm64-v8a
  sign      : v1 + v2/v3
  package   : com.deepseek.chat (versionCode 279, versionName 2.6.1)
  label     : DeepSeek
  sdk       : min 23, target 36, compile 36
  launcher  : com.deepseek.chat.MainActivity
  perms     : 22
    - android.permission.INTERNET
    …
  components: 32 (activity 11, service 11, receiver 5, provider 5)
  • zip 级信息(dex / res / ABI / 签名)纯 Python 读,秒出;manifest 级信息用 aapt2 dump badging + xmltree,没有 aapt2 时自动降级为 zip-only 摘要并提示。
  • 组件统计数的是 AndroidManifest.xml 里的 activity / service / receiver / provider(含 activity-alias)。
  • 不解包、不反编译,适合 CI 里做前置检查。

体积分析

apkbox size app.apk                  # 按类别统计 + 最大的 10 个文件
apkbox size app.aar --top 20         # .aar 同样可用
apkbox size v2.1.3
  file: app.apk (21.2 MB), 1023 个文件, 压缩后 21.0 MB (原始 43.5 MB, 2.1x)

  类别       文件数        压缩后       占比         原始       膨胀
  代码        11     7.2 MB    34.3%    15.1 MB     2.1x
  原生库      16     8.7 MB    41.4%    20.5 MB     2.4x
  资源       767     3.9 MB    18.3%     4.1 MB     1.1x
  …

  最大的 5 个文件(压缩后):
     1. classes.dex  5.7 MB → 11.7 MB
     …
  • 类别口径:dex/jar/kotlin → 代码;res/+resources.arsc → 资源;lib//jni/ → 原生库;AndroidManifest.xml → 清单;META-INF/+R.txt 等 → 元数据。
  • 纯 zip 读,秒出;"膨胀"列是原始大小 ÷ 压缩后大小。

对比两个包

apkbox diff old.apk new.apk          # 版本升级前后 / CI 里做回归检查
  • zip 级:文件增减、内容变化(按未压缩大小,同内容重新打包不算差异)、 各类别体积增减、大文件清单。
  • manifest 级:包名/版本、sdk、label、launcher、权限增减、组件数量变化。 AAR 直接解析纯文本 manifest;APK 走 aapt2 dump,没有 aapt2 时跳过该段并提示。
  • 退出码 0 完全一致 / 1 有差异 / 2 输入错误,可直接用于 CI 卡点。

列 dex 类名

apkbox classes app.apk               # 全部类名
apkbox classes app.apk com.foo       # 子串过滤
apkbox classes app.apk -c            # 只要数量
apkbox classes classes.dex kotlin.   # 单个 dex 也行
  • 纯 Python 解 dex(class_defs → type_ids → string_ids),不解包、不反编译,秒出。
  • .dex / .apk / 含 classes*.dex 的 zip 都支持;多 dex 按 classes.dex, classes2… 顺序合并。
  • 统计行走 stderr(24 / 15484 类),stdout 可以直接管道给 grep/wc。

dex 成员与统计

apkbox members app.apk MainActivity    # 这些类的字段/方法(类名子串匹配)
apkbox members app.apk 'okhttp3.'      # 一批类的成员一起看
apkbox dexinfo app.apk                 # 每个 dex 的大小/类/方法/字段数
  • members 输出 类名#方法(参数)返回值 / 类名#字段:类型,参数按 dex 描述符 还原成 Java 写法(android.os.Bundle、int[]),和 javap 的签名一致。
  • dexinfo 的"方法"列是 method_ids 数——65536 上限算的就是它;单个 dex 接近 60000 会打警告(混淆重的大包很容易撞上)。
  • 都是纯 Python 解 dex,统计行走 stderr,stdout 可直接管道。

清单转 XML

apkbox manifest app.apk                # 二进制清单 → 可读 XML(走 aapt2)
apkbox manifest app.aar                # 文本清单 → 重新排版
apkbox manifest app.apk -o m.xml       # 写到文件
  • 输出标准 XML(带 xmlns 声明、属性全部展开),可以直接 diff、搜索、给脚本吃; 不解包、不反编译。
  • APK 需要 aapt2(自动解析/下载);AAR 或纯文本 XML 不需要,走 ElementTree 美化。

组件审计

apkbox components app.apk                  # 列四大组件: 类型/exported/类名/权限
apkbox components app.apk --exported       # 只看导出的(攻击面)
apkbox components app.apk --type service   # 只看某一类
apkbox components app.aar                  # AAR/文本清单不需要 aapt2
  • exported 列是生效值:显式 android:exported 优先;没声明时带 intent-filter 的标 default*(旧规则默认可导出),否则 -。
  • 统计行(共 n 个组件 (…)) 走 stderr,stdout 是纯数据可直接管道;组件带 permission / readPermission / writePermission 时行尾追加 [权限]。

XML 条目转文本

apkbox xml app.apk res/xml/network_security_config.xml
apkbox xml app.apk res/layout/main.xml -o out.xml
  • 任意二进制 XML 条目(layout / xml / drawable…)→ 可读 XML,和 manifest 同一条解码链路;文本条目直接美化输出。
  • manifest 就是 xml … AndroidManifest.xml 的特例。

提取图标

apkbox icon app.apk                       # → app-icons/<dpi 目录>/
apkbox icon app.apk -o icons/             # 指定输出目录
  • 优先 aapt2 dump badging 里的 application-icon-<dpi> 行,每个 dpi 精准取; 没有 aapt2 时退回文件名启发式(*ic_launcher*)并提示。
  • 按原目录结构落到输出目录;adaptive-icon 的 xml 是二进制,想看内容用 apkbox xml。

完整性体检

apkbox check app.apk                      # zip / CRC / dex / 清单 / 签名
  • 纯 Python 不联网:zip 结构 → 全量 CRC → dex magic → 清单在不在 → v1 / v2-v3 签名,逐行打 ✓/✗/⚠。
  • ✗(损坏/缺失)退出码 1;⚠(没 dex、没签名,AAR 很常见)只提示,退出码 0。

找字符串

apkbox strings app.apk --only dex https    # 只扫 dex,正则过滤
apkbox strings app.apk --only native -i libfoo
apkbox strings classes.dex --min 6          # 单文件,unix strings 风格
  • 语义同 unix strings:stdout 出串(zip 输入带 条目名: 前缀),stderr 出 统计,直接管道给 grep。
  • 扫 APK 时按条目解压后逐个扫,--only 限定类别(dex/res/assets/native/…); 只匹配 ASCII 可打印串,--min 默认最短 4,--icase 忽略大小写。

只抽一类文件

apkbox extract app.apk native -o libs/    # 只要 .so(或 dex/res/assets/…)
apkbox extract app.apk manifest           # manifest 文本(见下)
apkbox extract app.aar all -o out/        # 整包解出
apkbox extract app.apk all --list         # 只列出条目(大小+路径),不写文件
apkbox extract app.apk all --glob 'lib/*' # 通配符过滤,和类别条件叠加
  • 类别:dex / res / assets / native / manifest / meta / all, 默认输出到 <输入名>-<类别>/。
  • 防 zip-slip:拒绝 .. 和绝对路径条目(会提示跳过了几个)。
  • --list 不建目录不写文件;--glob 是 fnmatch 通配符(* / ? / [seq])。
  • manifest 对 APK 用 aapt2 dump xmltree 转成 AndroidManifest.txt(文本格式, 不是 XML 源文件);没有 aapt2 时退成原始二进制并提示。AAR 的 manifest 本就是 文本,原样抽出。想直接拿可读 XML 用 apkbox manifest。

界面语言

按系统 locale 自动选中文/英文,也可以强制指定:

apkbox --lang en java app.apk      # --lang 放子命令前后都行
APKBOX_LANG=en apkbox app.apk      # 环境变量

Python API

from apkbox import (convert, decompile_to_java, run_info, run_size,
                    run_diff, run_classes, run_members, run_dexinfo,
                    run_manifest, run_xml, run_components, run_icon,
                    run_check, run_strings, run_extract, ToolError)

convert("app.apk")                                   # → app.aar,返回退出码
convert("app.apk", "dist/app.aar", code_only=True)   # 只要 classes.jar
info = decompile_to_java("app.apk", "src/")          # 返回统计 dict
print(info["java_files"], info["errors"], info["log_file"])
run_info("app.apk")                                  # 打印 APK 摘要,返回退出码
run_size("app.apk")                                  # 体积分析
run_diff("old.apk", "new.apk")                       # 0 一致 / 1 有差异 / 2 输入错误
run_classes("app.apk", "com.foo")                    # 类名(stdout 打印)
run_members("app.apk", "MainActivity")               # 字段/方法
run_dexinfo("app.apk")                               # 每 dex 类/方法/字段数
run_manifest("app.apk")                              # 清单转可读 XML
run_xml("app.apk", "res/xml/network_security_config.xml")  # 任意条目转可读 XML
run_components("app.apk", exported_only=True)        # exported 组件审计
run_icon("app.apk")                                  # 抽启动图标
run_check("app.apk")                                 # 完整性体检
run_strings("app.apk", "https", only="dex")          # 在 dex 里找字符串
run_extract("app.apk", "native", "libs/")            # 抽原生库
run_extract("app.apk", "all", list_only=True)        # 只列出条目

参数与命令行同名(convert 的 work_dir/code_only/keep/skip_decode/..., decompile_to_java 的 no_res/deobf/jobs/show_bad_code/...)。 工具级失败抛 ToolError;API 和命令行一样,缺工具会自动下载(APKBOX_OFFLINE=1 可禁止)。

退出码

码 含义
0 成功(diff 里表示两包完全一致;check 的 ⚠ 只提示不算失败)
1 工具执行失败(外部命令报错,已打印 error: …);diff 里表示有差异;check 发现损坏/缺失;icon 没找到图标
2 参数/输入文件问题

Metadata

Release files for apkbox 2.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for apkbox 2.1.3
File Size Uploaded
apkbox-2.1.3.tar.gz 75.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for apkbox 2.1.3
File Interpreter ABI Platform
apkbox-2.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 156.8 kB

Release files / apkbox-2.1.3.tar.gz

Download URL apkbox-2.1.3.tar.gz
Size 75.9 kB
Tags Source
SHA-256 checksum
How to use checksums
2a74406482fc3ed7cc6574835174f801b045fbb05733e6a24f11e2b5a6075fe8
BLAKE2b-256 checksum
How to use checksums
b6d9034b5ad3e0bb3b0c13e9106233b58dda25b8b66b8c7d8ebc90e96b98728d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release files / apkbox-2.1.3-py3-none-any.whl

Download URL apkbox-2.1.3-py3-none-any.whl
Size 80.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a7d2692661f88bbcb3b07ff97cc9fa8483ff286f95ce73a984f78c7672e16dcf
BLAKE2b-256 checksum
How to use checksums
f77e3b63df6e7441a2232c455cb17ac14360c24222fa4159c7477a5156e1d270
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

2.1.3 This release

2 release files

2.1.2

2 release files

2.1.1

2 release files

2.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page