Tinker热修复集成流程及采坑

这篇文章的集成AS版本是2.1.3,gradle版本也是2.x版本,其实2.x版本和3.x版本的gradle差别不是很大。

文章就直接写我从开始集成到结束的整个过程,在这中间遇到的问题我会用红色标注出来。

集成Tinker当然首先是看官方文档,进入GitHub的Tinker地址tinker去查看官方文档,点击右侧的接入指南,看整个接入的过程,大概浏览了一遍,感觉头大啊,太tm麻烦了,但是没办法不学不行啊,一步步来吧。

添加依赖

1:项目的build.gradle中添加依赖:

buildscript {
    dependencies {
        classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.1')
    }
}

2:在Module的gradle中添加依赖

dependencies {
	//可选,用于生成application类 
	provided('com.tencent.tinker:tinker-android-anno:1.9.1')
    //tinker的核心库
    compile('com.tencent.tinker:tinker-android-lib:1.9.1') 
}
...
...
//apply tinker插件
apply plugin: 'com.tencent.tinker.patch'

好,从文档上来看,基本上配置就完了,就是这么简单,然后同步一下,错误开始
问题一:
在这里插入图片描述
同步完毕出现了上面的报错tinkerid is not set,然后查询tinkerid是个什么东西,文档的解释如下
在这里插入图片描述
那么这个东西在哪里配置呢,这个东西是配置在Module中的gradle文件中的,具体怎么配置,比较复杂,所以一般的解决办法是导入Tinker中的例子项目tinker-sample-android,导入以后,把它的Module中的gradle文件全部复制到自己项目中,然后在根据自己原来定义的配置去修改。

导入sample工程

建议建个新工程,只导入sample这一个项目,因为Tinker中除了这个例子工程还有其他的工程,使用import Module导入以后,开始出现问题

问题二:找不到is_gradle_3()函数
在这里插入图片描述
上面sample工程中的gradle文件的一部分,其中有一个is_gradle_3函数,仔细看上面的截图就能明白,这个函数其实是判断项目用的哪个版本的gradle,根据不同的版本来进行不同的依赖,但是这个函数例子中没有定义,系统也没有提供,所以只能自己来删除另一个版本的依赖语句。

问题三:找不到TINKER_VERSION
这个问题比较好解决,仔细看上面的gradle截图,为了修改版本号方便,这里使用动态引入版本的方式,在工程的gradle.properties文件中定义就好,如下图:
在这里插入图片描述
然后继续同步,有可能会再次出现上面的tinkerid is not set的错误,如果出现了这个错误,咱们就去gradle文件中找到这个id的位置,如下图:
在这里插入图片描述
在这里,返回了tinker_id,首先去获取TINKER_ID字段有没有值,如果没有,会执行gitSha()方法返回这个id,由于我们的gradle.properties文件中没有定义TINKER_ID,所以会执行gitSha()方法,返回tinker_id,这个方法我就不截图了,这个方法返回的是git的版本号,也就是说,如果这个sample工程,你是使用git的方式clone下来的,这个方法会返回git的版本号,如果不是,就获取不到,就会报错,总而言之,这个tinker_id是为了获取一个唯一标识,所以这里可以直接在gradle.properties文件中定义好TINKER_ID,如下图
在这里插入图片描述
好,到此,基本上,配置就集成完毕了,注意,最后要把复制过来的gradle文件修改一下,部分配置要改成原来项目中的,比如applicationId要改成包名,由于Tinker需要自动签名,所以在gradle中也好配置好签名文件的路径。

修改Application

Tinker为了能够做到热修复Application类,使用了将原来Application类隔离的方式来做的,具体见自定义Application,所以这里要使用注解的方式来完成Application的改造。

1:继承ApplicationLike

public class MyApplicationLinke extends ApplicationLike {}

2:添加注解
@DefaultLifeCycle(application = ".MyApplication",//而这个类是真正的自定义的application,别忘了在AndroidManifest.xml中使用
        flags = ShareConstants.TINKER_ENABLE_ALL,
        loadVerifyFlag =false)

注意上面的注释,真正在清单文件中注释的是application这个字段定义的类名,具体每个字段的含义,可以直接取文档中查,这里需要注意,在清单文件配置Application的name的时候,会报红,但是没有关系,因为这个类是通过注解动态生成的,所以编译的时候就可以通过。

3:复写方法
//相当于attachBaseContext
    @Override
    public void onBaseContextAttached(Context base) {
        super.onBaseContextAttached(base);
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

可以把原来attachbaseContext方法中的逻辑放到onBaseContextAttached

4:修改Application对象

之前使用到Application对象的位置,可以通过getApplication()来替换

注册Tinker

在application中注册Tinker
TinkerInstaller.install(this);
到此,集成完毕,开始生成基准包,基准包的意思就是我们第一次发布的apk包。

生成基准包

基准包使用如下图的方式来生成,可以是debug的也可以Release的,因为gradle中配置了前面文件的路径,apk生成直接就是签名了的。
在这里插入图片描述
生成的基准包在如下图的,build的目录下的bakApk的目录下,直接使用这个包发布即可

在这里插入图片描述

生成patch补丁

当线上出现了bug的时候,我们就需要生成补丁包了,直接修改bug代码,然后需要配置gradle,再生成补丁包,配置gradle如下图
在这里插入图片描述
把上图1的位置的apk的名称,拷贝到2的位置,也就是说,告诉Tinker,我是在哪个基准包的基础上生成的补丁包,这里需要注意:不要删掉基准包apk,因为我们每次生成补丁包都需要在基准包的基础之上,即使修复多次也是从基准包的基础上生成的。

修改完以后,如下图的方式,生成patch补丁包
在这里插入图片描述
生成的补丁包,在build – outputs–tinkerPatch目录下,如下图:
在这里插入图片描述

加载补丁patch

然后通过TinkerInstaller.onReceiveUpgradePatch(this,path);直接加载补丁包就好了,Tinker在加载完补丁包以后,需要重启进程才能生效。

最后一个问题:第二次加载patch不生效的问题。
我在集成测试的时候,出现了第一次加载补丁是生效的,当第二次加载的时候补丁不生效,原因是版本的问题,我使用的是1.9.13版本,sample工程中使用的1.9.1,这个版本是稳定的。

好了,到此Tinker的集成就完毕了,接下来就是了解Tinker的原理的

猜你喜欢

转载自blog.csdn.net/static_zh/article/details/90241771