前言
相信从事Android开发的各位都遇到过APP上线了这时候突然发现出现了一些小的bug或者被用户或产品经理临时要求加个小功能或者修改某个功能,相信在没有热修复之前都是匆忙的改了代码后很快的上线新版本,这不仅麻烦,而且让用户体验性非常不好,用户想体验新版的APP还需要重新安装,这会使APP的用户量大大的流失。所以有了这个需求,热修复就问世了。
现在市面上热修复框架种类还是非常多的,根据公司团队来划分主要有以下几种:
| 类别 | 成员 |
|---|---|
| 阿里系 | AndFix、Dexposed、阿里百川、Sophix |
| 腾讯系 | 微信的Tinker、QQ空间的超级补丁、手机QQ的QFix |
| 知名公司 | 美团的Robust、饿了么的Amigo、美丽说蘑菇街的Aceso |
| 其他 | RocooFix、Nuwa、AnoleFix |
部分热修复框架的对比如下表所示:
由于本人目前只用过tinker热更新方案,个人觉得接入还是挺方便快捷的,下面为大家介绍接入流程。
第一步 添加 插件依赖
首先要在工程的根目录下的build.gradle文件下添加以下代码:
第二步 集成 TinkerPatch SDK
其次,在app目录下的build.gradle文件的dependencies标签下添加依赖
然后在apply plugin: 'com.android.application'下面添加apply from: 'tinkerpatch.gradle',例如:
第三步 配置 tinkerpatchSupport 参数
然后在app目录下创建上面引用的tinkerpatch.gradle文件,并且配置参数。这是我个人工程的参数:
apply plugin: 'tinkerpatch-support'
/**
* TODO: 请按自己的需求修改为适应自己工程的参数
*/
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-1.0.1-0509-16-54-36"// 注意!!! 改成对应的路径
def variantName = "release"
def versionName = "1.0.1"
/**
* 对于插件各参数的详细解析请参考
* http://tinkerpatch.com/Docs/SDK
*/
tinkerpatchSupport {
/** 可以在debug的时候关闭 tinkerPatch **/
tinkerEnable = true
/** 是否使用一键接入功能 **/
reflectApplication = true
/** 是否开启加固模式,只有在使用加固时才能开启此开关 **/
protectedApp = false
/** 补丁是否支持新增 Activity (exported必须为false)**/
supportComponent = false
autoBackupApkPath = "${bakPath}"
/** 在tinkerpatch.com得到的appKey **/
appKey = "yourAppKey"
/** 注意: 若发布新的全量包, appVersion一定要更新 **/
appVersion = "1.0.0"
def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
def name = "${project.name}-${variantName}"
baseApkFile = "${pathPrefix}/${name}.apk"
baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
baseResourceRFile = "${pathPrefix}/${name}-R.txt"
/**
* 若有编译多flavors需求, 可以参照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
* 注意: 除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息(相关工具:walle 或者 packer-ng)
**/
}
/**
* 用于用户在代码中判断tinkerPatch是否被使能
*/
android {
defaultConfig {
buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
}
}
/**
* 一般来说,我们无需对下面的参数做任何的修改
* 对于各参数的详细介绍请参考:
* https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
*/
tinkerPatch {
ignoreWarning = true
useSign = true
dex {
dexMode = "jar"
pattern = ["classes*.dex"]
loader = []
}
lib {
pattern = ["lib/*/*.so"]
}
res {
pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
ignoreChange = []
largeModSize = 100
}
packageConfig {
}
sevenZip {
zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
// path = "/usr/local/bin/7za"
}
buildConfig {
keepDexApply = false
}
}
至于参数的具体含义可以去tinker官网查看tinker官网。
第四步 初始化 TinkerPatch SDK
最后在我们的代码中,只需简单的初始化 TinkerPatch 的 SDK 即可,我们无需考虑 Tinker 是如何下载/合成/应用补丁包, 也无需引入各种各样 Tinker 的相关类。
1. reflectApplication = true 的情况
若我们使用 reflectApplication 模式,我们无需为接入 Tinker 而改造我们的 Application 类。直接在我们自己的Application类里面进行初始化操作,下面是我自己的Application代码:(这个项目我是用kotlin写的,跟Java差异不大)
class MyApplication : Application() {
private var tinkerApplicationLike: ApplicationLike? = null
override fun onCreate() {
super.onCreate()
// 我们可以从这里获得Tinker加载过程的信息
tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike()
// 初始化TinkerPatch SDK, 更多配置可参照API章节中的,初始化SDK
TinkerPatch.init(tinkerApplicationLike)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true)
.setFetchPatchIntervalByHours(3)
// 每隔3个小时(通过setFetchPatchIntervalByHours设置)去访问后台时候有更新,通过handler实现轮训的效果
TinkerPatch.with().fetchPatchUpdateAndPollWithInterval()
}
}
2. reflectApplication = false 的情况
因为本人比较懒,这种情况我自己没有使用,就使用了第一种情况,根据tinker官网给出的方案是新建一个类集成DefaultApplicationLike类,我们可以参考 tinkerpatch-sample 中的 SampleApplicationLike 类.
public class SampleApplicationLike extends DefaultApplicationLike {
...
@Override
public void onCreate() {
super.onCreate();
// 初始化TinkerPatch SDK, 更多配置可参照API章节中的,初始化 SDK
TinkerPatch.init(this)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true)
.setFetchPatchIntervalByHours(3);
// 每隔3个小时(通过setFetchPatchIntervalByHours设置)去访问后台时候有更新,通过handler实现轮训的效果
TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
}
...
}
如果要使用第二种方法的可以通过tinker官网去下载他们的demo获取,这里就不在多做探讨。
第五步 使用步骤
TinkerPatch 的使用步骤非常简单,一般来说有以下几个步骤:
1、运行 assembleRelease task 构建基准包,如下图所示:
在构建完基准包之后,会在app目录下的build的下会创建一个bakApk文件夹,里面的apk文件就是基准包。
2、要想发布补丁包,需要修改tinkerpatch.gradle文件的一下参数,如下所示:
然后运行 tinkerPatchRelease task 构建补丁包,补丁包将位于 build/outputs/tinkerPatch下。
注意:打基准包时,一定要有签名,如果没有签名时候打补丁包会报:Execution failed for task ':app:tinkerPatchRelease'. > can't the get signConfig for this build异常
打完补丁包后会在outputs目录下的apk下创建tinkerPatch目录,里面的release目录下的patch_signed_7zip.apk就是我们所构建的补丁包了,如下所示:
得到补丁包后我们进入tinker官网去发布我们的补丁包,如下:

点击添加补丁文件,去到我们刚才发布的目录下添加,然后点击提交就可以发布我们的补丁了。
下面贴出我运行基准包和加载补丁包后的结果演示:

结束语:tinker集成完了,感谢大家观看本文章,如果有不好的地方请指出来,谢谢。