简介:这是一款面向Android开发者、逆向工程师及爱好者的APK修改与重打包工具集,涵盖反编译、资源编辑、代码修改、重新编译与签名等完整流程,可用于自定义应用标识、去除广告、界面美化及安全分析。压缩包共186个文件,体积约8.76MB,包含94个smali字节码文件、45张PNG图片、13个XML配置、5个JAR库、4个可执行程序,并配有反编译脚本、打包签名脚本和测试APK,构成一套可直接上手的环境。目前已吸引617人学习下载。工具集中既有经典命令行工具,也有可视化资源编辑器,配合一键批处理脚本,能帮助用户快速完成APK解包、查看与修改smali代码、替换资源、重新打包签名等操作。无论用于学习Android打包机制、调试自有应用,还是开展合规的逆向研究,都能从中获得从解析到出包的完整路径参考。
1. android apk 修改工具:先搞清楚要改什么,再选工具链
当有人和你说“android apk 修改工具”,他脑子里可能蹦出三个完全不同的诉求:把别人包的图标和名字换成自己的,帮自己开发的 App 在不上架的情况下改个包名重签名,或者给某个老应用做汉化和去广告。这三个诉求的落点不一样,对应的工具链也完全不一样。我第一次碰这个领域时,最直观的感受是:工具并不难下载,难的是搞清 APK 里哪些文件能改、改了之后要不要重签名、签名后为什么手机依然不让装。我会从 APK 的包结构讲起,把解包、改资源、改 smali、重打包、签名、安装的完整路径拆开,给出一套能直接抄的命令和参数,并把我踩过的坑按“现象—原因—解决”写清楚。适合准备做 APK 二次开发、市场包体定制或自动化打包的工程师参考。
2. APK 结构拆解:修改前先搞清楚 dex、资源表和签名在哪
2.1 一个 APK 到底装了什么:从 ZIP 说起
APK 的本质是一个 ZIP 压缩包,但它不是普通压缩包。Android 系统安装应用时不会把 ZIP 解压到数据目录,而是按固定路径读特定文件。AndroidManifest.xml 提供包名、权限、Activity 声明,安装时系统要解析它来创建应用入口;classes.dex 是编译后的 Dalvik 字节码,App 的逻辑都在这;resources.arsc 是一张全局资源索引表,把资源 ID 映射到实际文件路径和字符串;res/ 目录存放图片、布局、动画等原始资源,里面按 values、layout、drawable、mipmap 等子目录组织;lib/ 目录按 ABI 类型存放 so 动态库,比如 arm64-v8a、armeabi-v7a;assets/ 是原样打包的资产文件,适合放体积大又不参与资源索引的数据;META-INF/ 保存签名证书和摘要文件,安装时用于完整性校验。
很多新手犯的第一个错误,是用普通解压软件把 APK 解开直接改,再塞回去。这个做法对 assets/ 里的纯数据文件偶尔能成立,但只要你动了 AndroidManifest.xml 或 resources.arsc,安装时就会报“解析包错误”。原因是这两个文件在打包阶段已经被 aapt2 编译成了二进制 XML,不是普通文本,用文本编辑器改必然破坏结构。这也是为什么市面上的修改工具里,最核心的一类不是压缩软件,而是能对二进制资源做解码和回编译的工具,典型就是 apktool。
另外要注意区分“查看工具”和“修改工具”。很多人下载 jadx 把 APK 拖进去能看代码,但这只能做到看,改不了。要真正改完还能装能跑,必须走“解包—修改—重打包—签名”四步。每一步选错工具都会让前面的工作白费,所以下面我按目标来拆工具链,而不是按工具来背命令。
2.2 用 apktool 解包:最小命令与产物说明
apktool 是目前最通用的资源回编译工具,它的核心作用是两件事:把二进制 AndroidManifest.xml 和 resources.arsc 解码成可读 XML,把 dex 反汇编成 smali 汇编代码。我一般从下面这组命令开始:
# 安装 apktool,macOS 上 brew 最省事,Linux 可以直接下载 jar 包放到 /usr/local/bin brew install apktool # 解包:-f 表示输出目录已存在时强制清空,-o 指定输出目录 apktool d -f target.apk -o target_src执行完之后,target_src 目录下会看到 AndroidManifest.xml、res/、smali/、assets/、lib/、original/ 等目录。original/ 里保留了解包时的原始元数据,包括 META-INF 下的证书文件,后面重打包时 apktool 会参考它。打开 AndroidManifest.xml,你会发现它已经变成可读的 XML 了,<uses-permission>、<application>里的 android:label、android:icon 都能直接改。
这里有几个参数要说明。第一,apktool d 的 -f 不是必须的,但如果你重复解包同一个 APK,不带 -f 会报“Directory already exists”,建议每次都带上。第二,-o 如果不写,默认输出到与 APK 同名的目录,我习惯显式写清楚,避免覆盖。第三,-s 参数的意思是“只解码资源,不把 dex 转成 smali”,如果只是改图标和名称,加上它会快很多,因为 dex 反汇编很耗时。反过来,如果要改逻辑,就不要加 -s,让 apktool 把 classes.dex 全部反汇编成 smali/ 目录。
还需要注意 apktool 的版本选择。Android 14 及之后的系统,APK 的 resources.arsc 可能包含更新的编码,老版本 apktool 会解析失败,建议用 2.9.x 或更新版本。另外遇到多 dex 的 APK 时,解包产物里会有 smali_classes2/、smali_classes3/ 这类目录,它们和 classes2.dex、classes3.dex 一一对应。修改时一定要确认自己改的代码在哪个 dex,如果改错位置,运行时会触发 ClassNotFoundException。我一般会先用 jadx 打开 APK 定位关键类,再回到 apktool 的对应 smali 目录里找,这样效率最高。
2.3 不重打包也能确认包信息:aapt2 与 Android Studio 的 apkanalyzer
很多场景下你不需要完整解包,只想确认包名、版本号、targetSdk、图标路径。这时候用 apktool 属于“杀鸡用牛刀”,更快的做法是直接用 Android SDK 自带的 aapt2 和 apkanalyzer。aapt2 在 build-tools 目录下,如果你电脑装了 Android Studio,通常路径是 ~/Library/Android/sdk/build-tools/34.0.0/aapt2,Linux 或 Windows 对应在 ANDROID_HOME 的 build-tools 下。我一般会把 build-tools 加到 PATH 里,方便后续 zipalign、apksigner 一起调用。
# 查看 APK 的包名、版本、权限、入口 Activity aapt2 dump badging target.apk # 用 apkanalyzer 打印 Manifest 内容,适合脚本解析 apkanalyzer manifest print target.apkaapt2 dump badging 的输出里有一行 package: name=... versionCode=... versionName=...,还有 launchable-activity: name=...,这些信息是修改前必须确认的。如果包名和系统里已装应用冲突,一会儿安装时大概率失败;如果 targetSdk 比系统版本低很多,运行时有些行为会不同。apkanalyzer 是 Android Studio 自带的命令行工具,它输出的 Manifest 接近原始 XML,比 aapt2 更适合在脚本里做 grep。当你只是临时查一个信息,千万不要解包整个 APK,文件多且费时间。
到这里你应该明白了:修改 APK 的第一步不是找工具,而是搞清楚自己要动的文件在哪层。只动 assets 可以拿 ZIP 处理;动图标和文案走 apktool 的资源路径;动代码走 smali 路径;改完必须重签名。下一章我按这三种目标分别给可复现的做法。
3. 按修改目标选工具:改资源、改逻辑还是改签名
3.1 只改图标和名称:资源回编译的三步
最常遇到的修改需求是换图标和换应用名。这种修改不涉及 dex,流程最短,但也有很多细节。第一步解包,建议加 -s 只解资源,速度快;第二步改文件和替换图片;第三步回编译。命令如下:
# 解包,-s 跳过 dex 反汇编,改资源足够 apktool d -f -s target.apk -o target_src # 修改 res/values/strings.xml 里的 app_name # 用你自己的图标覆盖 res/mipmap-*/ic_launcher.png 或 ic_launcher_round.png # 回编译 apktool b target_src -o rebuilt.apk要注意,res/values/strings.xml 里的 app_name 是应用显示名,但很多 APK 还会在 AndroidManifest.xml 的<application>节点直接写 android:label="xxx",这个优先级更高。所以只改 strings.xml 不一定生效,正确做法是打开解包后的 AndroidManifest.xml,把 application 节点的 label 改成 @string/app_name 或直接改成指定文案。图标同理,AndroidManifest.xml 里 android:icon 指向的 mipmap 资源如果被你删了,回编译时会报资源找不到,所以替换时不要删原始文件名,而是覆盖对应密度的文件。
关于图标尺寸,res/mipmap-mdpi、mipmap-hdpi、mipmap-xhdpi、mipmap-xxhdpi、mipmap-xxxhdpi 五个文件夹都要覆盖,只改一个会导致高密度设备上图标模糊。如果你需要快速生成一套图标,Android Studio 自带的 Image Asset 工具最省事,它在 New > Image Asset 里,能自动输出五个密度。命令行的方式则是用脚本缩放,但最稳妥的就是用 Image Asset,避免不同密度下比例不一致。
回编译这一步参数不多,apktool b 默认会编译资源并重新组装 APK,-o 指定输出文件。如果资源有错误,会直接报错并告诉你具体文件。改完资源后,新 APK 还没有签名,直接安装会失败,所以必须进入第 3.3 节的签名流程。这里我特别强调:资源回编译后的 APK 体积通常比原包大,因为 apktool 不会像 Android Gradle Plugin 那样做强压缩和资源混淆,这是正常的,不要怀疑改坏了。
3.2 改 smali 逻辑:jadx 看代码,apktool 改回编译
当你要修改的不仅是文案,而是行为逻辑,比如改服务器地址、修改默认开关、去掉某个弹窗,就需要动 dex。纯看代码我推荐 jadx,它能把 dex 反编译成接近源码的 Java 输出,阅读效率远高于直接看 smali。但真正修改时,我一般直接改 smali,因为 jadx 输出的 Java 在回编译时很难保证与原包一致。具体流程是:先用 jadx 定位目标类和方法,再回到 apktool 解包产物里的 smali 目录找到对应 .smali 文件修改。
# 用 jadx 反编译到 java_src 目录,方便阅读定位 jadx -d java_src target.apk # 在 smali 目录里搜索关键字符串 grep -r "old.example.com" target_src/smali/假设要改一个硬编码的接口地址,你会定位到某个 .smali 文件里的 const-string。smali 是寄存器风格的汇编,每行指令都要指定操作数。例如原始代码是:
const-string v0, "https://old.example.com" invoke-virtual {v0}, Ljava/lang/String;->length()I把第一行改成新地址即可,但要注意新字符串长度变化后,如果后面有对 v0 长度判断或数组拷贝的逻辑,可能破坏行为。所以最稳妥的改法是尽量保持字符串长度一致,或者干脆在调用点前面插入新逻辑,而不是替换。另外 smali 里的寄存器是可以重用的,v0、v1 这些只是局部变量,不要以为它和 Java 局部变量一一对应。改完 smali 后同样执行 apktool b 重打包,但这次不要加 -s,因为要重新汇编 dex。
提一个常见场景:很多 APK 在 Application 或 MainActivity 里做了签名校验,你重签名后一启动就闪退。这种校验往往在 smali 里通过对比签名哈希实现,搜索字符串“signature”或调用 PackageManager 的 getPackageInfo 位置,把校验逻辑改成常量返回即可。但我要说清楚:处理签名校验逻辑只适合你有权修改的应用,比如自己的测试包。对他人作品做这种操作,版权和责任都在你自己身上,别指望工具替你担责。
3.3 重打包与签名:apksigner 和 zipalign 的配合
无论改了资源还是 smali,重打包后的 APK 必须重新签名才能安装。签名工具我用 apksigner,它是 Android build-tools 里的标准工具,兼容 v1、v2、v3 签名方案。另一件事是对齐,zipalign 会把 APK 内的资源按 4 字节对齐,让系统能用 mmap 高效读取。顺序上必须先 zipalign 再签名,如果反过来,v2 签名会覆盖对齐信息,导致包结构异常。
# 如果没有 keystore,先用 keytool 生成一个(只生成一次) keytool -genkeypair -alias mykey -keyalg RSA -keysize 2048 -validity 10000 \ -keystore my.keystore -storepass 123456 -keypass 123456 # 对齐:-p 表示对 .so 也用 4KB 页对齐,-f 覆盖输出 zipalign -p -f 4 rebuilt.apk aligned.apk # 签名:--ks 指定 keystore,--ks-key-alias 指定别名 apksigner sign --ks my.keystore --ks-key-alias mykey \ --ks-pass pass:123456 --key-pass pass:123456 \ --out signed.apk aligned.apkzipalign 的 4 是字节对齐大小,一般固定写 4。-p 参数是 Android 4.2 之后推荐的,它会额外检查并处理 .so 文件的 4KB 对齐,对于新安装包影响不大但建议带上。apksigner 的 --ks-pass 和 --key-pass 分别对应 storepass 和 keypass,如果 keytool 生成时两个密码设置成一样,这里也要分别写。更安全的做法是不在命令行写明文密码,让 apksigner 交互式输入,但脚本自动化时我会把密码放到环境变量里,避免出现在历史记录中。
apksigner 默认会同时启用 v1 和 v2 签名,v3 根据 targetSdk 自动判断。如果你在 Android 11 或更高版本安装失败,多半是因为没有 v2 签名,或者签名时用了老工具 jarsigner。apksigner 是这个时代的默认选择。签名完成后可以用 apksigner verify 验证,这个放到下一章细说。
4. 从修改到安装:签名参数和安装失败的排查路径
4.1 签名算法与 v1/v2/v3 的选择
APK 签名方案经历了三代。v1 是 JAR 签名,校验的是 META-INF 里的 MANIFEST.MF、CERT.SF 和 CERT.RSA,它会覆盖所有未压缩的条目,但容易受到“篡改后再重打包”的攻击,Android 7.0 以下必须用它。v2 是在 ZIP 文件末尾的 Signing Block 里放签名,整包校验,速度快,Android 7.0 及以上才支持。v3 在 v2 基础上支持密钥轮换,Android 9 及以上。现在新开发的 App 基本都要求 v2 起步。
修改工具做重签名时,最保守的做法是 v1+v2 同时启用。v1 保证老设备能装,v2 保证新系统不会因为签名方案缺失而拒绝。apksigner 默认行为是“能签的都签”,但有些 ROM 对签名方案有特殊要求,比如 targetSdk 28 及以上的应用在 Android 9 上如果只有 v1 签名,安装时可以但运行时部分功能受限。因此我们可以在命令里显式控制:
# 只启用 v1 和 v2,禁掉 v3,避免密钥轮换信息干扰 apksigner sign \ --v1-signing-enabled true \ --v2-signing-enabled true \ --v3-signing-enabled false \ --ks my.keystore --ks-key-alias mykey \ --ks-pass pass:123456 \ --out signed.apk aligned.apk这个参数组合适合大多数二次修改场景。如果你明确只适配 Android 9 以下,禁掉 v3 也没关系;如果目标设备是 Android 11 以上,建议保持 v2 开启。v3 主要面向应用升级时的密钥更换,普通修改用不上。另一个容易踩的坑是:如果 APK 原本是 v1 签名的,你用 apksigner 加上 v2 后,系统可能报“signatures do not match”。那是因为安装时系统会同时检查新旧签名,这里不是 apksigner 的问题,而是原包本身只支持 v1,重签名时必须保留原包签名证书才行。实际操作中,若你是替换签名而不是保持原签名,最好卸载旧应用再装新包。
4.2 用 apksigner 验证签名是否生效
签名完成并不代表一定能装。验证签名是否正常,我每次都会跑一遍 apksigner verify,这比盲目传到手机上安装快得多。命令如下:
# 详细验证签名,并打印证书信息 apksigner verify --verbose --print-certs signed.apk输出里会列出 Verified using v1 scheme: true / Verified using v2 scheme: true / Verified using v3 scheme: false 这样的信息,还有证书的 CN、有效期和 SHA-256 指纹。看到 v1 和 v2 都是 true,说明签名结构没毛病。如果 --verbose 输出里出现 WARNING,比如分区签名缺失或未对齐,一般不会直接导致安装失败,但最好处理掉。另外 --print-certs 打印的证书指纹可以用来和别人比对,确认这个包到底是用谁的证书签的。
还有一种情况:apksigner verify 能过,但手机依然提示“应用未安装”,那就要看是不是 keystore 里的 alias 不对。apksigner 签名时不会警告 alias 不存在,它会把文件写出来,但包内的签名块可能是空的。所以签名后第一步永远是用 verify 看一眼,再上设备。
4.3 无法安装 APK 的排查:解析包错误、签名不一致、targetSdk 限制
到了安装这一步,最常见的手机提示有两类。第一类是“解析包错误”,通常指 APK 文件本身损坏或签名没生效。原因可能是你在解包后手动改了 ZIP 结构,比如删了 META-INF 里的文件但没重新签名,或者资源回编译时输出目录不完整。解决办法是走完整流程:重新用 apktool b 生成包,zipalign,再 apksigner sign,不要手动改 ZIP。第二类是“应用未安装”,这个提示背后的原因很多:签名不一致、包名冲突、系统版本限制。
签名不一致是最典型的情况。手机上已经装了某个签名证书的包,你想覆盖安装另一个证书签的包,系统会拒绝。这时只能卸载旧包再装,或者确保新旧包用同一个 keystore 签名。包名冲突则是另一个坑,如果目标 APK 的包名和系统内置应用或已有应用一样,即使卸载也可能装不上,尤其是系统应用,需要使用 adb 的 install -r 配合签名匹配。我在测试修改包时一般会改包名,改包名的方法是在 AndroidManifest.xml 里改 package 属性,同时把 application 里的所有相对路径引用检查一遍,否则会闪退。
targetSdk 限制也不可忽视。Android 14 及之后的系统不允许安装 targetSdk 低于 23 的应用,国产 ROM 还会针对 targetSdk 或 AB 架构做额外限制。用 aapt2 dump badging 看一下 targetSdk 值,如果过低,可以用 apktool 修改 AndroidManifest.xml 里的 uses-sdk 节点,把它提高到 23 以上。但这会带来行为变化,比如运行时权限需要动态申请,原本只在 Android 6 以下跑的 App 可能因此出现权限闪退。所以修改 targetSdk 时要权衡,不要为了装上而盲目提版本。
5. 修改 APK 的避坑清单:5 条血泪经验
5.1 改完闪退:多半是 resources.arsc 没编译好或 smali 语法错
现象:apktool b 成功,签名成功,安装成功,但一点开就闪退,Logcat 里不停报资源找不到或 ClassNotFoundException。原因通常是两个:一是你改了 AndroidManifest.xml 里的资源引用但没有同步改 res/values/public.xml,导致资源 ID 错位;二是 smali 修改时寄存器分配错误,比如用了一个不存在的 v 寄存器,apktool 有的版本在汇编时不够严格,能产出 dex 但运行时直接崩。解决方法是先看 Logcat 最前面的异常类型。如果是 Resources$NotFoundException,打开 apktool 生成的 public.xml,检查你改过的资源 ID 是否与原来一致;如果是 VerifyError 或 CFGI 错误,回到 smali 检查寄存器数量,方法头部的 .registers 数字是否覆盖了你用到的最大寄存器编号。记住 smali 里 .registers 是声明,不是建议。
5.2 手机提示“应用未安装”:v1/v2 签名缺失或 zipalign 顺序错
现象:apksigner verify 输出 v2=false,或者 zipalign 后报错。原因:有的脚本教程用 jarsigner 签名,它只写 v1,新系统不认;或者你在签名之后又跑了一次 zipalign,把签名块破坏了。解决:固定使用 apksigner,且严格按 zipalign → apksigner 的顺序执行。如果已经破坏了,就重新从 apktool b 开始,不要试图用 zip 工具修补签名块。另外,apksigner 默认会同时签 v1 和 v2,如果你在命令里手动指定了 --v1-signing-enabled false,那老设备就装不上,不要自己给自己挖坑。
5.3 资源改名后找不到资源:public.xml 与资源 ID 变化
现象:把 res/ 目录里的某个 layout 文件名改了,回编译不报错,但运行时 inflate 失败。原因:Android 资源 ID 在 resources.arsc 里是编译期定死的,apktool 回编译时会重新给资源分配 ID。你在 XML 里用 @layout/main 引用没问题,但如果代码里用了 getResources().getIdentifier("main", "layout", ...),或者某个第三方库在 native 层硬编码了 ID,改名就会断。解决:改文件名不如改内容,保持资源路径和 ID 不变。实在要改,必须同步修改 public.xml 里的<public>条目,而且最好在回编译前就把 public.xml 里的 id 写成和原包一致。这个坑在“android 自定义混淆字典无效”的场景里也常见,混淆字典改了资源名但没改 public.xml,最终系统找不到资源。
5.4 64 位与 32 位 so 不匹配:lib 目录误删导致崩溃
现象:原包在模拟器上正常,修改后装到真机闪退,Logcat 报 dlopen failed: library "xxx.so" not found。原因:apktool 解包后 lib/ 目录里同时有 armeabi-v7a 和 arm64-v8a 两套 so,很多人为了减小体积只保留一套,结果在另一套 ABI 的设备上加载不到。解决:要么保留两套,要么确保修改后的 APK 只支持一种 ABI。如果只保留 arm64-v8a,那 32 位设备会直接提示无法安装。更微妙的是,有些 so 本身是 32 位的,却放在 arm64-v8a 目录下,安装不报错但一调用就崩。我一般用 file lib/arm64-v8a/xxx.so 查看 ELF 类型,确认是 64-bit 再保留。另外原包里的 so 通常经过压缩,apktool 回编译后如果没有用 zipalign -p,系统可能无法在 mmap 时解析,这也是不装或崩的一个隐藏原因。
5.5 加了 Apk 加固的包不能直接二次修改:先改再加固才是正路
现象:拿到一个加固过的 APK,apktool 解包后 smali/ 目录里只有一个壳的 dex,找不到业务代码;或者用 jadx 打开全是壳类。原因:加固工具会把原始 dex 加密后放到 assets 或特定文件里,运行时由壳的 Application 解密加载。你解包看到的 classes.dex 只是壳,业务逻辑根本不在。解决:不要试图对加固包做二次修改。加固包的定制应该在加固之前做,也就是先对未加固的 APK 完成资源、代码的修改和签名,再交给加固平台加固。如果你手头只有加固包且没有原包,那就只能放弃这个修改目标。这也解释了为什么很多修改工具教程会要求你找“未加固版本”,并不是工具不行,而是技术路线本来就该这样走。做 Apk 加固后的包,你要做的不是修改,而是重新走打包流程。
6. 进阶:用命令行脚本把“解包-修改-重打包-签名”串成一条流水线
当你手里有一批 APK 要做同样规则的修改,手工敲命令很容易出错。我一般会把流程写成一个 bash 脚本,按参数传入输入包、keystore 和要替换的图标目录。脚本里每一步都加了 set -e,任何一步失败就停下来,避免拿半成品去安装。下面是一个简化版:
#!/bin/bash set -e INPUT_APK="$1" KEYSTORE="$2" KEY_ALIAS="$3" STORE_PASS="$4" ICON_DIR="$5" OUT_APK="${INPUT_APK%.apk}_signed.apk" WORK_DIR="work_$(date +%s)" # 1. 解包并替换资源 apktool d -f -s "$INPUT_APK" -o "$WORK_DIR" if [ -d "$ICON_DIR" ]; then cp "$ICON_DIR"/ic_launcher*.png "$WORK_DIR/res/mipmap-mdpi/" # 实际使用时要按密度目录逐个覆盖 fi # 2. 回编译、对齐、签名 apktool b "$WORK_DIR" -o "${WORK_DIR}/unsigned.apk" zipalign -p -f 4 "${WORK_DIR}/unsigned.apk" "${WORK_DIR}/aligned.apk" apksigner sign --ks "$KEYSTORE" --ks-key-alias "$KEY_ALIAS" \ --ks-pass pass:"$STORE_PASS" --out "$OUT_APK" "${WORK_DIR}/aligned.apk" # 3. 验证 apksigner verify --verbose --print-certs "$OUT_APK"脚本参数里,ICON_DIR 指向存放新图标的目录,你可以在目录里放 ic_launcher.png、ic_launcher_round.png,按密度复制时文件名保持一致。STORE_PASS 可以设置为环境变量,脚本里用 $STORE_PASS 引用,而不是硬编码。注意脚本里 apktool d 加了 -s,如果后续要改 smali,要把它去掉,并额外处理多 dex。
验证方法不只是 apksigner verify。我会再跑一次 aapt2 dump badging 确认包名和版本没被意外改动,然后安装到一台 Android 14 的真机上,全程观察 Logcat。如果安装报“INSTALL_FAILED_NO_MATCHING_ABIS”,说明 lib 目录只保留了不带匹配的 so;如果安装后闪退,先看是不是 resources.arsc 出问题。这套脚本我用了很久,它最大的价值是让每一次修改都可重复。以前我手动敲命令时,经常漏掉 zipalign 或把签名顺序搞反,现在脚本固定了顺序,反而少了很多翻车。希望这份流水线思路和前面那些参数能帮到你,下次拿到一个 APK 修改需求,先别急着找工具,按这个流程把每一步走完,你会少踩很多坑。
本文还有配套的精品资源,点击获取