Tinker热修复使用总结

Tinker的使用记录与总结

1. 使用场景(为什么使用热修复?)

在开发过程中,我们经常遇到一些小的且必须及时解决的线上bug,常用的方法就是更新一个版本,推送到用户强制更新。

例:公司项目3.0.0版本上线后,遇到用户不能使用流量下载的bug,我们只能推出了3.0.1版本修复了此bug。

如果使用了热修复技术,我们就可以在不升级版本的情况下解决此问题。

2.为什么使用Tinker?

 

Tinker

QZone

AndFix

Robust

类替换

yes

yes

no

no

So替换

yes

no

no

no

资源替换

yes

yes

no

no

全平台支持

yes

yes

no

yes

即时生效

no

no

yes

yes

性能损耗

较小

较大

较小

较小

补丁包大小

较小

较大

一般

一般

开发透明

yes

yes

no

no

复杂度

较低

较低

复杂

复杂

Rom体积

Dalvik较大

较小

较小

较小

成功率

较高

较高

一般

最高

研发实力雄厚;Tinker 在微信的数亿用户上得到验证,它的稳定性与性能值得信赖。

第三方支持平台多:TinkerPatchBugly,Tinker-Manager,tinker-dex-dump等方便对Tinker进行使用及调试。

下面以TinkerPatch为例:

附上链接:http://www.tinkerpatch.com/

在TinkerPatch后台申请appKey(申请步骤略过):

3.TinkerPatch的使用

1)添加Gradle插件依赖(project下的build.gradle)

dependencies { classpath ("com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:${TINKERPATCH_VERSION}") { changing = true } }

2)添加 TinkerPatch SDK 库的 denpendencies 依赖(app下的build.gradle)

annotationProcessor("com.tinkerpatch.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true }
compileOnly("com.tinkerpatch.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true } 
implementation("com.tinkerpatch.sdk:tinkerpatch-android-sdk:${TINKERPATCH_VERSION}") { changing = true }

为了简单方便,我们将 TinkerPatch 相关的配置都放于 tinkerpatch.gradle 中, 我们需要将其引入

apply from: 'tinkerpatch.gradle'

3)在gradle.properties添加版本信息,方便更新版本

TINKERPATCH_VERSION=1.2.2 
TINKER_VERSION=1.9.2

4) 配置 tinkerpatchSupport 参数,打开引入的 tinkerpatch.gradle,如图:

apply plugin: 'tinkerpatch-support'

def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-3.1.0-1203-16-00-22"
def variantName = "primary-release"

/**
 * 对于插件各参数的详细解析请参考
 * http://tinkerpatch.com/Docs/SDK
 */
tinkerpatchSupport {
    /** 可以在debug的时候关闭 tinkerPatch **/
    tinkerEnable = true
    reflectApplication = true

    autoBackupApkPath = "${bakPath}"

    /** 是否开启加固模式,只有在使用加固时才能开启此开关 **/
    protectedApp = true

    appKey = "这里替换成TinkerPatch后台的Appkey"
    appVersion = "3.1.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"

//    baseApkFile = "${bakPath}/app-1.0.0-0118-15-36-58/debug/app-debug.apk"
//    baseProguardMappingFile = "${bakPath}/app-1.0.0-0118-15-36-58/debug/app-debug-mapping.txt"
//    baseResourceRFile = "${bakPath}/app-1.0.0-0118-15-36-58/debug/app-debug-R.txt"

    /** 若有编译多flavors需求,可在flavors中覆盖以下参数
     *  你也可以直接通过tinkerPatchAllFlavorDebug/tinkerPatchAllFlavorRelease, 一次编译所有的flavor补丁包
     *  注意的是:除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息
     **/
//    productFlavors {
//        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"
//        }
//
//        flavor {
//            flavorName = "flavor2"
//            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"
//        }
//    }
}

/**
 * 用于用户在代码中判断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
    }
}

5)初始化TinkerPatch SDK。

 public class MyApplication extends MultiDexApplication{
   
   ...
     
    private ApplicationLike tinkerApplicationLike;
    @Override

    public void onCreate() {
        super.onCreate();
        if (BuildConfig.TINKER_ENABLE) {
            // 我们可以从这里获得Tinker加载过程的信息
            tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
            // 初始化TinkerPatch SDK, 更多配置可参照API章节中的,初始化SDK
            TinkerPatch.init(tinkerApplicationLike)
                    .reflectPatchLibrary()
                    .setPatchRollbackOnScreenOff(true)
                    .setPatchRestartOnSrceenOff(true)
                    .setFetchPatchIntervalByHours(1);
            Log.e("TinkerPatch", "Current patch version is " + TinkerPatch.with().getPatchVersion());
            // 每隔1个小时(通过setFetchPatchIntervalByHours设置)去访问后台时候有更新,通过handler实现轮训的效果
            TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
            ...
        }
        
        ...
        
    }

注意:初始化的代码建议紧跟 super.onCreate(),并且所有进程都需要初始化,已达到所有进程都可以被 patch 的目的

6)生成基类包

运行完毕,之后找到基类包的生成路径。

修改tinkerpatch.gradle中的3个文件路径。

def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-3.1.0-1203-16-00-22"
def variantName = "primary-release"

7)生成补丁包。在原代码基础上添加任意Toast用来测试补丁是否加载成功(原包里是没有这段Toast的)。

showToast("升级ok!!!!!!!",false);

运行结束之后,找到补丁包的位置,如下:

8)发布补丁,进入TinkerPatch后台进行配置:

在这里我们选择开发预览,开发预览用于开发测试,不会影响到线上版本。

9)先安装第6步生成的基类包,此时是没有Toast代码的,开发者需要在手机上安装测试工具,

附上链接:http://ogmj51oem.bkt.clouddn.com/TinkerDebugTool.apk

打开开关,

再重新打开我们的应用,从后台可以发现补丁已经被下载,需要再次重新打开应用,才会完成合并的操作,在后台我们可以看到补丁的下载数/合成数/应用数,刚刚发布的补丁也只有16.6k:

测试没问题后,选择全量下发,就可以不知不觉的修复线上的bug,并在后台可以实时监控补丁合成情况:

总结

截止到此,借助TinkerPatch三方平台,初步掌握了热修复的使用,复杂的原理知识还有待学习,凭着他们的官方文档接入SDK时,遇到了很多坑,所以又重新梳理了我在接入和使用Tinker时的步骤和方法,感兴趣的同学可以借鉴看一看。

猜你喜欢

转载自blog.csdn.net/Json_Jerry/article/details/84792116