Tinker 热修复集成与使用指南
版本:Tinker 1.9.15.2 、AGP 8.2.2 、Gradle 8.7 。
目标:讲清环境、引入、集成、日常怎么用,并列出本项目踩过的坑。
项目仓库地址:点击进入
aar修复,请参照项目文件 docs目录下的 old和new .aar文件,关于项目如何打包 .aar,我会出一个新的文档
一、Tinker 能做什么
| 类型 | 说明 | 本项目 |
|---|---|---|
| Dex | 改 Java/Kotlin 业务逻辑 | ✅ 已验证 |
| 资源 | 改 strings、colors、layout 等 | ✅ 已验证 |
| so | 替换 APK 内 lib/<abi>/*.so |
✅ 已配置(需自带 native) |
| 本地 AAR | 替换 libs/*.aar 后打补丁 |
✅ 已验证(zcclib-release.aar) |
| Manifest 新组件 | 热增 Activity/Service 等 | ❌ 未开启 |
说明: 手机上不会单独替换 .aar 文件,而是把新版 AAR 编译进新 APK,再与基准 APK 做差量生成补丁;用户加载补丁后,AAR 内的 Dex/资源/so 变更会随补丁生效。
不能做的: 不能改 SampleApplication 壳类;不能靠补丁在 Manifest 里注册新的 Activity/Service 等组件。
二、环境搭建
2.1 必备环境
- JDK 11+ (本项目
sourceCompatibility = 11) - Android SDK ,
compileSdk 34 - Gradle Wrapper 8.7 (不要用 Gradle 9,Tinker 插件会报
GFileUtils等错误)
2.2 版本对照(与本项目一致)
| 组件 | 版本 |
|---|---|
| Gradle | 8.7 |
| Android Gradle Plugin | 8.2.2 |
| Tinker SDK + 插件 | 1.9.15.2 |
2.3 仓库
settings.gradle 中已配置 google()、mavenCentral(),并保留 Tinker / 阿里云镜像(拉 SevenZip 等依赖时有用)。
三、引入 Tinker
3.1 根工程 build.gradle
gradle
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:8.2.2'
classpath 'com.tencent.tinker:tinker-patch-gradle-plugin:1.9.15.2'
}
}
3.2 模块 app/build.gradle
gradle
apply plugin: 'com.android.application'
apply plugin: 'com.tencent.tinker.patch' // 必须在 application 插件之后
dependencies {
implementation 'com.tencent.tinker:tinker-android-lib:1.9.15.2'
implementation 'androidx.multidex:multidex:2.0.1'
}
3.3 Release 构建注意
multiDexEnabled trueminifyEnabled true时必须有 mapping.txtshrinkResources必须为 false(Tinker 要求)- 配置 Release 签名(基准包与补丁包签名一致)
四、集成步骤(对照本项目)
4.1 核心类分工
SampleApplication ← 壳,不能热修,只做 Tinker 入口
SampleApplicationLike ← 真正 Application 逻辑,可热修
TinkerManager ← install / loadPatch / cleanPatch
PatchResultService ← 合成成功后冷重启
TinkerPatchService ← :patch 进程合成补丁
4.2 Application 壳
AndroidManifest.xml 中 android:name 指向 SampleApplication ,不要直接写 ApplicationLike。
SampleApplication 继承 TinkerApplication,并指定代理类:
java
public SampleApplication() {
super(
ShareConstants.TINKER_ENABLE_ALL, // dex + so + res
"com.example.tinkerdemo.app.SampleApplicationLike",
"com.tencent.tinker.loader.TinkerLoader",
false // 正式环境建议 true:校验补丁 MD5
);
}
4.3 在 attachBaseContext 安装 Tinker
SampleApplicationLike.onBaseContextAttached() 中:
MultiDex.install(base)TinkerManager.installTinker(this)
必须在 attachBaseContext 阶段完成 ,不能拖到 onCreate。
4.4 AndroidManifest 必配项
- meta-data
TINKER_ID:与build.gradle里manifestPlaceholders一致 - Service (本项目已注册):
TinkerPatchService(:patch进程)PatchResultService(主进程,合成后杀进程冷启动)TinkerPatchForeService(Android 8+ 前台保活)
4.5 权限(本地调试补丁路径)
READ/WRITE_EXTERNAL_STORAGE- Android 11+:
MANAGE_EXTERNAL_STORAGE(读/sdcard/patch_signed_7zip.apk) android:requestLegacyExternalStorage="true"(调试方便)
4.6 混淆 proguard-rules.pro
至少保留:
com.tencent.tinker.**SampleApplication(loader 白名单)ApplicationLike、Patch/Load ReporterR$*成员(资源 ID 稳定)
打补丁时使用基准包的 mapping.txt (applyMapping)。
4.7 tinkerPatch 配置要点
gradle
def TINKER_ID = "base-1.0.0"
def OLD_APK = "${rootDir}/patch/base/app-release.apk"
def OLD_MAPPING = "${rootDir}/patch/base/mapping.txt"
def OLD_RESOURCE = "${rootDir}/patch/base/R.txt"
android {
defaultConfig {
manifestPlaceholders = [TINKER_ID: TINKER_ID]
}
}
tinkerPatch {
oldApk = OLD_APK
ignoreWarning = true // 含 Java/AAR 改动时建议 true,见「常见问题」
useSign = true
buildConfig {
applyMapping = OLD_MAPPING
applyResourceMapping = OLD_RESOURCE
tinkerId = TINKER_ID
}
dex {
dexMode = "jar"
pattern = ["classes*.dex"]
loader = [
"com.tencent.tinker.loader.*",
"com.example.tinkerdemo.app.SampleApplication"
]
}
lib { pattern = ["lib/*/**.so"] }
res { pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"] }
}
4.8 本地 AAR 与热修复(已验证)
gradle
implementation files('libs/zcclib-release.aar')
两种场景不要搞混:
| 场景 | 操作 |
|---|---|
| 首次接入 AAR(发版) | 把 AAR 放进 app/libs/,打基准包 → 更新 patch/base/ → 安装到手机 |
| 仅热修 AAR(已上线) | 不要动基准包 ;用改好的 .aar 覆盖 app/libs/ 里同名文件 → tinkerPatchRelease → 推补丁 |
AAR 热修步骤(本项目已验证):
- 手机上已是含旧版 AAR 的基准包(
patch/base/app-release.apk与之一致)。 - 在外部改好 SDK,重新打包得到新的
zcclib-release.aar(或你的 aar 文件名)。 - 将新 AAR 替换 到
app/libs/zcclib-release.aar(路径、依赖方式不变)。 - 执行
.\gradlew.bat clean(可选,建议 clean 后打补丁)→.\gradlew.bat tinkerPatchRelease。 - 推送
app/build/tmp/tinkerPatch/patch_signed_7zip.apk,App 内加载补丁并冷启动。
补丁日志中通常能看到 Dex 差量 (AAR 内 Java 变更)以及 资源差量 (若 AAR 含 layout、strings 等)。若 AAR 带 jni/*.so,还会走 lib 差量。
注意: 热修 AAR 时仍需使用基准包的 mapping.txt、R.txt;若新版 AAR 导致资源 ID 体系变化过大,需评估是否应发新基准包而非打补丁。
五、目录与基准包
TinkerClaude/
├── patch/
│ ├── base/ # 基准包("已上线版本")
│ │ ├── app-release.apk
│ │ ├── mapping.txt
│ │ └── R.txt
│ └── patch_signed_7zip.apk # 可选:备份最近一次补丁
├── app/build/tmp/tinkerPatch/ # 补丁真正输出目录(推这个)
│ ├── patch_signed_7zip.apk
│ └── patch_signed.apk
└── keystore/tinker_demo.jks # Release 签名
每次发布新基准包 都要更新 patch/base/ 三件套,并 adb install -r 装到手机。
六、使用流程(推荐顺序)
6.1 发布基准包(模拟上线)
bash
# Windows
.\gradlew.bat clean :app:assembleRelease
将产物拷贝到 patch/base/:
| 源文件 | 目标 |
|---|---|
app/build/outputs/apk/release/app-release.apk |
patch/base/app-release.apk |
app/build/outputs/mapping/release/mapping.txt |
patch/base/mapping.txt |
app/build/intermediates/runtime_symbol_list/release/R.txt |
patch/base/R.txt |
安装到手机:
bash
adb install -r patch/base/app-release.apk
6.2 修改代码 / 资源 / AAR 后打补丁
在不改变 patch/base/ 基准包的前提下,任选其一或组合修改:
- 改 App 内 Java、layout、strings 等
- 用新版
.aar覆盖app/libs/下同名文件(AAR 热修,已验证)
然后:
bash
.\gradlew.bat tinkerPatchRelease
仅替换 AAR 时:基准包仍是旧 AAR 打进 APK 的那一版;新 AAR 只参与「新 APK」构建,用于和基准做 diff,无需为此重新安装基准包(除非你还改了 Manifest、TINKER_ID 等)。
补丁输出位置(重要):
- ✅ 使用:
app/build/tmp/tinkerPatch/patch_signed_7zip.apk - ❌ 不要只推:
app/build/outputs/apk/tinkerPatch/release/(可能是旧文件)
6.3 推送到真机并加载
bash
adb push app/build/tmp/tinkerPatch/patch_signed_7zip.apk /sdcard/patch_signed_7zip.apk
adb shell stat -c %s /sdcard/patch_signed_7zip.apk # 校验大小
App 内:从外部存储加载补丁 → 授权「所有文件访问权限」→ 合成成功后会 自动冷重启 (PatchResultService)。
6.4 验证是否生效
- 看 资源演示页 文案/颜色是否变化
- logcat 过滤
Tinker.TinkerLoader,应出现tryLoadPatchFiles: load end, ok! - 首次装基准包未打补丁时,
code=-2(无 tinker 目录)是正常现象
6.5 清除补丁
主界面 清除补丁 → 强制停止 App → 再打开,即回到基准包行为。
七、代码里如何触发补丁
7.1 从 SD 卡加载(Demo 默认)
路径:/storage/emulated/0/patch_signed_7zip.apk(见 PatchFileUtils)
java
TinkerManager.loadPatch(context, patchPath);
7.2 从 assets 加载(本地演示)
将补丁放入 app/src/main/assets/patch_signed_7zip.apk,点击「从 assets 加载」。
7.3 生产环境建议
用 OkHttp / 下载 SDK 把补丁下到私有目录或 getExternalFilesDir,再调用:
java
TinkerInstaller.onReceiveUpgradePatch(context, absolutePath);
合成成功后务必 冷启动 (杀进程或依赖 PatchResultService)。
八、能力边界速查
| 场景 | 是否支持 |
|---|---|
| 改 Activity / 工具类 Java 代码 | ✅ Dex |
| 改/新增 layout、strings(保持 R.txt 稳定) | ✅ 资源 |
覆盖 app/libs/xxx.aar 后打补丁 |
✅ 已验证(Dex/资源/so 差量) |
手机上单独拷贝一个 .aar 文件即生效 |
❌(须打补丁包并加载) |
| AAR 仅含 Java,无 so | ✅ Dex 补丁即可 |
| AAR 含 layout/资源 | ✅ 资源补丁(需 applyResourceMapping) |
AAR 含 jni/*.so |
✅ so 补丁(ABI 与基准一致) |
| 新增 Manifest Activity 并启动 | ❌ |
改 SampleApplication |
❌ |
| 改 AndroidManifest 里 Service 注册 | ❌ 需重装基准包 |
九、常见问题
9.1 打补丁失败:ShareTinkerInternals loader 类变更
现象: some loader class has been changed in new primary dex
处理: tinkerPatch { ignoreWarning = true }(本项目已开启)。这是 R8 重编译后的无害差异,不影响业务类热修。
9.2 补丁推了但界面不变
- 确认推的是
build/tmp/tinkerPatch/下最新文件 - 用
adb shell stat -c %s核对大小,不要只看ls -l时间 - 必须 冷启动,不要只划掉后台
- 手机上必须是 基准包,不是已包含新资源的完整 APK
- 合成成功后 SD 卡补丁可能被删除,需重新 push
9.3 patch_meta.info / code=-2 日志
- 首次安装、未加载过补丁:正常
- 重装基准包后:先 清除补丁 再加载新补丁
9.4 mkdir res_temp/res 报错但显示合成成功
部分机型(如 vivo)常见,若 onPatchResult: success=true 且冷启动后界面已更新,可忽略。
9.5 Gradle 9 构建失败
请使用 Gradle 8.7,不要用 9.x milestone。
9.6 改了 AndroidManifest(新增 Service 等)
Manifest 变更 不能 靠补丁生效,需 重新打基准包并安装。
9.7 何时必须更新基准包
- 新功能首次上线(新的基准 APK)
- 修改了 Manifest 组件
- 修改了
TINKER_ID - 换了签名或 ABI 策略
仅改业务代码 / 资源 / 覆盖 libs 下 AAR 后打补丁 :只打补丁,不更新基准。
9.8 AAR 热修后无效果
- 确认手机安装的是旧版 AAR 的基准包,而不是已手动集成新 AAR 编出来的完整 APK。
- 确认
app/libs/里已是新版 aar,且执行过tinkerPatchRelease(建议先clean)。 - 补丁需从
build/tmp/tinkerPatch/推送,加载后 冷启动。 - 查看构建日志是否有
Gen classes.dex patch(有 Java 变更时应有 Dex 差量)。
十、命令速查
| 目的 | 命令 |
|---|---|
| 打基准包 | .\gradlew.bat :app:assembleRelease |
| 打补丁 | .\gradlew.bat tinkerPatchRelease |
| 安装基准 | adb install -r patch/base/app-release.apk |
| 推送补丁 | adb push app/build/tmp/tinkerPatch/patch_signed_7zip.apk /sdcard/patch_signed_7zip.apk |
| 解决 R8 锁文件 | .\gradlew.bat --stop 后 clean 再编 |
十一、本项目关键文件索引
| 文件 | 作用 |
|---|---|
app/build.gradle |
Tinker 插件、tinkerPatch、TINKER_ID |
app/src/main/AndroidManifest.xml |
权限、Service、TINKER_ID |
app/.../SampleApplication.java |
Tinker 壳 |
app/.../SampleApplicationLike.java |
MultiDex + installTinker |
app/.../TinkerManager.java |
安装与加载补丁 |
app/.../PatchResultService.java |
合成成功冷重启 |
app/.../MainActivity.java |
加载/清除补丁、权限 |
app/.../PatchFileUtils.java |
补丁路径 |
app/proguard-rules.pro |
混淆保留规则 |
patch/base/ |
基准 APK + mapping + R.txt |
十二、参考链接
- Tencent Tinker 官方仓库
- 本 Demo 包名:
com.example.tinkerdemo - 更多项目使用和详细 参见 Android Tinker Demo 使用手册