一、微信Tinker简介
1、Tinker是微信官方的 Android 热补丁解决方案,它支持动态下发代码、So 库以及资源,让应用能够在不需要重新安装的情况下实现更新。
2、Tinker热补丁方案不仅支持类、So 以及资源的添加和替换,它还是2.X-7.X的全平台支持,不足之处是无法即时生效,下面的与其他知名热修复的对比:
![](https://img.haomeiwen.com/i4109474/870b728db89023ab.png)
3、Tinker 已运行在微信的数亿 Android 设备上。
2、Tinker存在的问题
1、Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件;
2、由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码;
3、在Android N上,补丁对应用启动时间有轻微的影响;
4、不支持部分三星android-21机型,加载补丁时会主动抛“TinkerRuntimeException:checkDexInstall failed”;
5、对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。
3、接入Tinker
1、添加依赖:
①在项目的build.gradle文件,添加tinker-patch-gradle-plugin的依赖:
buildscript {
dependencies {
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.11')
}
}
②然后在app的gradle文件app/build.gradle,我们需要添加tinker的库依赖:
dependencies {
//依赖这个原因后面讲
compile "com.android.support:multidex:1.0.1"
//可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.7.11')
//tinker的核心库
compile('com.tencent.tinker:tinker-android-lib:1.7.11')
}
③配置信息:
下载TinkerDemo https://github.com/Tencent/tinker/tree/master/tinker-sample-android
如果要打签名包,要在app/build.gradle配置签名信息:
signingConfigs {
release {
keyAlias 'key0'
keyPassword '123456'
storeFile file('C:/Users/lyh/Desktop/debug.jks')
storePassword '123456'
}
}
还有:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
需要混淆的也可以参考Demo,在app/build.gradle的defaultConfig中:
multiDexEnabled true
multiDexKeepProguard file("tinkerMultidexKeep.pro")
然后把Demo里的规则拷贝过来:
![](https://img.haomeiwen.com/i4109474/8ead7862ba5abf4d.png)
Demo里面需要注意会有这个两个文件,直接拿来用:
![](https://img.haomeiwen.com/i4109474/1337cec71d5762b0.png)
先解释下tinkerpath.gradle,看上半部分的截图,下半部分不用管:
![](https://img.haomeiwen.com/i4109474/24678773df115e43.png)
appVersion一定是和你发布到各大应用市场一致,也就是你发布到各大应用市场的就是基础包。
然后是SampleApplicationLike,这是Tinker提供的生成Application推荐方法:
//tinker.sample.android.app.SampleApplication 是生成的Application的路径
@DefaultLifeCycle(application = "tinker.sample.android.app.SampleApplication",
flags = ShareConstants.TINKER_ENABLE_ALL,
loadVerifyFlag = false)
public class SampleApplicationLike extends DefaultApplicationLike {
private static final String TAG = "Tinker.SampleAppLike";
public SampleApplicationLike(Application application,
int tinkerFlags,
boolean tinkerLoadVerifyFlag,
long applicationStartElapsedTime,
long applicationStartMillisTime,
Intent tinkerResultIntent
) {
super(
application,
tinkerFlags,
tinkerLoadVerifyFlag,
applicationStartElapsedTime,
applicationStartMillisTime,
tinkerResultIntent
);
}
/**
* install multiDex before install tinker
* so we don't need to put the tinker lib classes in the main dex
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
//you must install multiDex whatever tinker is installed!
MultiDex.install(base); //这就是上面依赖MultiDex的原因
}
/**
* 我们需要确保至少对主进程跟patch进程初始化 TinkerPatch
*/
@Override
public void onCreate() {
super.onCreate();
initTinker();
}
private void initTinker() {
if (BuildConfig.TINKER_ENABLE) {
//开始检查是否有补丁,这里配置的是每隔访问3小时服务器是否有更新。
TinkerPatch.init(this)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true)
.setFetchPatchIntervalByHours(3);
// 获取当前的补丁版本
Log.d(TAG, "current patch version is " + TinkerPatch.with().getPatchVersion());
//每隔3个小时去访问后台时候有更新,通过handler实现轮训的效果
TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
}
}
当然,我们大部分已经有自己的Application,把那些初始化操作放在我们自己的Application,注意的是tinkerpatch.gradle的reflectApplication要设置为true,否则会抛出TinkerRuntimeException: Tinker Exception:applicationLike must not be null。
到这里已经的配置完成了,下看具体怎么使用。
4、Tinker使用
1、首先,Tinker官网创建APP,这一步不用说,跳过;
2、其次,打基础包,找到app/build.gradle,点击右上角会出现这个:
![](https://img.haomeiwen.com/i4109474/6f6b0cb3432c5d76.png)
直接右键run,这里以assembleDebug包为例,成功之后会在这里看到基础包:
![](https://img.haomeiwen.com/i4109474/ce47f622290ef1f4.png)
就可以把这个放到各大应用市场。
3、打更新包,也就是修改bug或者你想做的,当然,要注意Tinker存在的问题,上面提到了,改完一定要注意,上面提到一个地方,在tinkerpatch.gradle中修改:
![](https://img.haomeiwen.com/i4109474/613191ba2e98b8f5.png)
一一对应,然后就可以打更新包了,还是找到app/build.gradle,点击右上角:
![](https://img.haomeiwen.com/i4109474/d0160ed03fe66223.png)
选择tinkerPatchDebug右键run,成功之后会在这里看到:
![](https://img.haomeiwen.com/i4109474/da7fc749c885fb8d.png)
这个就是更新包了,拿出来,打开Tinker官网http://www.tinkerpatch.com/,我的APP-->管理-->发布新补丁:
![](https://img.haomeiwen.com/i4109474/81302a8added33fd.png)
搞定,那怎么让他更新,上面配置的默认是3小时去找一次,但Tinker提供了立即更新的API:TinkerPatch.with().fetchPatchUpdate(true),立即更新,可以在APP启动时调用,这样每次启动都会APP去看有没更新包,然后重启APP,过一会就会看到热修复成功,不是立即生效。
5、APP加固流程(360加固)
1、build中打包基准包assembleRelease A-> A到360网页加固,然后签名B -> B安装到手机上->修改bug .修改baseInfo为A的名字-> tinker里面打包tinerPatchReleasepatch_signed_7zip->发布到tinker后台 (全程都开protectedApp = true),具体参考
https://github.com/TinkerPatch/tinkerpatch-flavors-sample/blob/master/app/tinkerpatch.gradle
tinkerpatch.gradle中:
productFlavors {
flavor {
flavorName = "protect"
appVersion = "${tinkerpatchSupport.appVersion}_${flavorName}"
pathPrefix = "${bakPath}/${baseInfo}/${flavorName}-${variantName}/"
name = "${project.name}-${flavorName}-${variantName}"
baseApkFile = "${pathPrefix}/${name}.apk"
baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
baseResourceRFile = "${pathPrefix}/${name}-R.txt"
/**开启加固开关,上传此flavor的apk到加固网站进行加固**/
protectedApp = true
}
flavor {
flavorName = "flavor1"
appVersion = "${tinkerpatchSupport.appVersion}_${flavorName}"
pathPrefix = "${bakPath}/${baseInfo}/${flavorName}-${variantName}/"
name = "${project.name}-${flavorName}-${variantName}"
baseApkFile = "${pathPrefix}/${name}.apk"
baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
baseResourceRFile = "${pathPrefix}/${name}-R.txt"
}
}
6、渠道包
1、Tinker官方推荐[packer-ng-plugin]https://github.com/mcxiaoke/packer-ng-plugin或者walle来进行多渠道打包,其中walle是支持最新的SchemaV2签名的。
网友评论