Android接入tinker热更新

前言

相信从事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集成完了,感谢大家观看本文章,如果有不好的地方请指出来,谢谢。


版权声明:本文为weixin_38203696原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。