前言
我们先来比较一下当下热修复界中的四大天王(分别来自微信,QQ空间,阿里,美团):近年来随着Android用户的爆发式增长,Android应用也逐渐完善,应用再也不是只需要会四大组件就可以满足产品的需求,出现了很多三方的SDK,优秀的类库,还有个性化的插件。热修复在近年来特别hot,下面我们就来介绍一下业界评价最好的热修复之一Tinker!
什么是Tinker?
tinker是微信官方的Android热补丁解决方案,官方是这么概括Tinker的:Tinker is a hot-fix solution library for Android, it supports dex, library and resources update without reinstalling apk。用于给程序打补丁,不需要重新安装,支持动态下发代码、So库以及资源等
可以说很全面了,不管是Java类、xml布局文件、图片甚至是So库都可以用热修复来修改~
我们要介绍的是自定义Tinker的集成与使用,需要后台的支持,如果不想这么麻烦,可以尝试TinkerPatch的一键傻瓜式接入,具体的可参考文档TinkerPatch 平台介绍。
这款优秀的热修复的GitHub地址是:https://github.com/Tencent/tinker
官方文档:http://www.tinkerpatch.com/Docs/intro
怎样集成Tinker?(自定义Tinker )
1.设置tinker版本 :
在gradle.properties文件中 添加tinker版本号,方便以后升级时修改:
TINKER_VERSION=1.9.1
2.在项目的build.gradle文件中添加依赖:
dependencies {
buildscript {
repositories {
jcenter()
}
dependencies {
// TinkerPatch 插件
classpath'com.tencent.tinker:tinker-patch-gradle-plugin:${TINKER_VERSION}’
}
}
3.配置app的build.gradle文件
可以依照 tinker-sample-android 项目的build.gradle文件配置
https://github.com/Tencent/tinker/tree/master/tinker-sample-android
注:build.gradle配置文件中记得配置keysotre 密码,如果和debug模式,要将自己电脑的debug.keystore文件复制到app下keystore文件夹中
- debug.keystore在自己电脑 C:\Users<用户名>.Android\debug.keystore
在运行demo时可能出现tinkerId未设置问题,这是由于demo中tinkerId为git的版本,当你本地无法获取git的版本时,会报错,
可以将thinkerId设置为应用的versionName,tinkerId保证其唯一性即可,每次升级app tinkerId也需要更新,继续与versionName保持一致。如下当前App的版本号是5.22:
def gitSha() {
try {
// String gitRev = 'git rev-parse --short HEAD'.execute(null, project.rootDir).text.trim()
// if (gitRev == null) {
// throw new GradleException("can't get git rev, you should add git to system path or just input test value, such as 'testTinkerId'")
// }
//设置tinkerId,与versionName一致即可
return '5.22'
// return gitRev
} catch (Exception e) {
throw new GradleException("can't get git rev, you should add git to system path or just input test value, such as 'testTinkerId'")
}
}
4.添加sd的读写权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- 改造Application
请参考SampleApplicationLike来看!
将原来自定义的Application子类中的逻辑移动到
SampleApplicationLike中
修改Application,然后将Application类继承TinkerApplication.java。`除了构造方法之外,你最好不要引入其他的类,这将导致它们无法通过补丁修改。
public class SampleApplication extends TinkerApplication {
public SampleApplication() {
super(
//tinkerFlags, tinker支持的类型,dex,library,还是全部都支持!
ShareConstants.TINKER_ENABLE_ALL,
//ApplicationLike的实现类,只能传递字符串
"tinker.sample.android.app.SampleApplicationLike",
//Tinker的加载器,一般来说用默认的即可
"com.tencent.tinker.loader.TinkerLoader",
//tinkerLoadVerifyFlag, 运行加载时是否校验dex与,ib与res的Md5
false);
}
}
具体的数值含义:
为了隐藏你的Application类,我们更加推荐你使用tinker-android-anno
在运行时生成你的Application类。这样保证你无法修改你的Application类,不会因为错误操作导致引入更多无法修改的类。
@DefaultLifeCycle(
application = ".SampleApplication", //application类名
flags = ShareConstants.TINKER_ENABLE_ALL, //tinkerFlags
loaderClass = "com.tencent.tinker.loader.TinkerLoader", //loaderClassName, 我们这里使用默认即可!
loadVerifyFlag = false) //tinkerLoadVerifyFlag
public class SampleApplicationLike extends DefaultApplicationLike
记得在清单文件中配置application名称:
一些自定义扩展类
这些类为我们提供了许多方法
比如加载补丁时的各种回调函数,详情见文档
注意其中有个service,在补丁加载成功或失败时会执行 记得在清单文件中配置。
怎样使用Tinker?
如果按照demo中app的build.gradle文件配置,那么每次运行或者打包时均会在build/bakApk中生成apk、R.txt、 mapping文件每次正式发布版本后需要保存这个包的apk(基准包) R.txt(用于修改了资源文件时打补丁) mapping.txt(如果基准包进行了混淆,打补丁时需要用到)
制作补丁
1.修改代码、资源文件 解决bug修复
3.运行 命令行: gradlew tinkerPatchRelease 或者 tinkerPatchDebug
完毕后就得到了补丁包
4.去自己的后台管理系统传补丁包并开启
重启应用,使之生效。
加载补丁的api
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk");
加载补丁的结果
在tinker包下SampleResultService类中处理
多Flavor打包
有的时候我们希望通过flavor方式打包,在sample中提供了简单的用法事例:
1.通过flavor编译,这个时候我们可以看到bakApk路径是一个按照flavor名称区分的目录;
2.将编译目录路径填写到sample中tinkerBuildFlavorDirectory,其他的几个字段不需要填写,这里会自动根据路径拼接;
ext {
tinkerBuildFlavorDirectory = "${bakPath}/app-1014-13-35-12"
}
3.运行tinkerPatchAllFlavorDebug或者tinkerPatchAllFlavorRelease即可得到所有flavor的补丁包。
- 关于同一版本多次打补丁问题
Tinker支持对同一基准版本做多次补丁修复,在生成补丁时,oldApk依然是已经发布出去的那个版本。即补丁版本二的oldApk不能是补丁版本一,它应该依然是用户手机上已经安装的基准版本。
为避免重复下载补丁包,补丁包也应有‘版本号’
调用接口获取此时客户端版本对应的补丁包信息:
补丁包版本号 (每次在后台上传补丁包时版本号自动递增最佳)
网友评论