前言
相信不少Android的小伙伴们都会遇到过APP上线之后才发现还有Bug,或者哪个地方还需要小改动,难道这个时候为了一点小改动重新编译,重新发布新版本吗?使用Tinker来解决Android APP的热补丁更新,实现修改.java代码、替换.so、替换资源后免发布版本,更新APP的代码。
Tinker是什么?为什么选择Tinker?
Tinker 是一个开源项目(Tinker GitHub链接),它是微信官方的 Android 热补丁解决方案,它支持动态下发代码、So 库以及资源,让应用能够在不需要重新安装的情况下实现更新。
TinkerPatch 平台
一个后台管理系统,使用者通过这个平台为APP下发和管理补丁包。
首先我们需要进入到Tinker Patch平台中,注册账号并登陆。然后添加APP,获取到APP Key,并且添加一个基包版本号。
这里解释一下基包,就是全量包,也可以说是完整的基础包。
补丁包,也就是增量包,也可以说是升级包,基于基包修改后,tinker比对后生成的差异包。
通俗的原理:发布一个全量包,如果有bug或者改动,通过tinker比对生成升级包,再通过TInkerPatch平台发布下发给用户这个升级包,用户客户端自动完成后台升级,下次打开就是修改后的客户端了。
具体TinkerPatch平台的使用流程参考:http://www.tinkerpatch.com/Docs/start
记下来APP Key和添加的版本号 我这里版本号设置成1.0.0
Gradle集成SDK
1.在项目的根目录下的build.gradle中添加jcenter远程仓库的依赖,和添加TinkerPatch 插件
2.在app目录下 添加TinkerPatch的配置文件tinkerpatch.gradle
applyplugin:'tinkerpatch-support'
/**
* TODO: 请按自己的需求修改为适应自己工程的参数
*/
def bakPath = file("${buildDir}/bakApk/")
def baseInfo ="app-1.0.0-1112-12-49-34"
def variantName ="release"
/**
* 对于插件各参数的详细解析请参考
* http://tinkerpatch.com/Docs/SDK
*/
tinkerpatchSupport {
/** 可以在debug的时候关闭 tinkerPatch **/
tinkerEnable =true
/** 是否使用一键接入功能 **/
reflectApplication =true
/** 是否开启加固模式,只有在使用加固时才能开启此开关 **/
protectedApp =false
/** 补丁是否支持新增 Activity �(exported必须为false�)**/
supportComponent =true
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"
}
/**
* 用于用户在代码中判断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 =false
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
}
}
3.在app/build.gradle中添加TinkerPatch的SDK依赖和引入上个步骤新建的配置文件
4.build.gradle依赖sdk和引入配置文件后,sync now 同步成功之后,右上角的Gradle点开,项目(root)》tasks》会增加一个tinker,这个时候tinker插件加载进来了。
布局及功能
1.按钮用来强制更新拉取补丁包,TextView用来显示后续更新状态
2.布局的逻辑代码,按钮点击通过TinkerPatch.with().fetchPatchUpdate(true);来强制拉取补丁
3.app/tinkerpatch.gradle 中的reflectApplication =true的时候,我们需要新建一个自定义MyApplication继承Application中重写onCreate,在super.onCreate();之后一行进行Tinker的初始化工作。reflectApplication =false的情况请参考官方文档。
8.再到AndroidManifest.xml中 application节点添加自定义的MyApplication
签名配置
1.在app/build.gradle中,配置签名
生成基包(全量包/完整包/基础包)
生成基包,主要需要配置的TinkerPatch参数是一个appVersion和appKey ,appKey只需要一次配置正确后续不用管,appVersion参数需要你在TinkerPatch平台中发布的app版本号要一致,同时app/build.gradle中的versionName也要一致。其他的参数就是先不用管。现在就可以打包全量包了。通过点击右上角的Gradle》项目名(root)》Tasks》build》assembleRelease来打包
之后在app/build/bakApk/下生成一个apk完整的包
我们把这个全量包,丢到手机中安装。
生成补丁包
接下去我们修改一些代码,再生成补丁包,再下发给用户。
接着我们就要配置一下app/tinkerpatch.gradle的参数,主要需要修改的是baseInfo和variantName参数,其他的无需更改
接着就是使用tinker插件,来生成补丁包(增量包/升级包),点击右上角Gradle》项目(root)》Tasks》tinker》tinkerPatchRelease来生成补丁包
输出日志显示SUCCESS字样就是成功了,成功之后在app/build/outputs/tinkerPatch/release/下生成patch_signed_7zip.apk
然后我们把补丁包到TinkerPatch平台中,发布补丁
接着我们继续打开我们的app,点击强制更新按钮,之后可以查看我们TinkerPatch后台查看状态
点击了强制更新之后,可以看到用户已经下载了,结束app进程,重新启动APP
重启之后,我们就可以发现文本框已经改变了,所以也应用成功了,热更新就这样成功了。我们再看看TinkerPatch平台的监控状态
TinkerPatch平台后台监控,同样也能看到应用成功数、合成成功数、下载成功数的状态了。
注意
如果再次修改生成补丁,配置文件中的baseinfo不需要改动,保持最初的基包。修改代码后直接通过Gradle的tinker插件生成补丁包,再到TinkerPatch平台下发补丁包就好了。
默认的话 Tinker是三个小时拉取一次更新包,在教程中,我是通过按钮,执行强制拉取代码来马上热更。在实际应用中,你们也可以通过推送,然后执行强更操作。又或者保留原本三小时拉取一次都可以。