踩坑热修复框架Tinker

Tinker是什么

Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件。

为什么使用Tinker

当前市面的热补丁方案有很多,其中比较出名的有阿里的AndFix、美团的Robust以及QZone的超级补丁方案。但它们都存在无法解决的问题,这也是正是使用Tinker的原因。

 

总的来说:
1、AndFix作为native解决方案,首先面临的是稳定性与兼容性问题,更重要的是它无法实现类替换,它是需要大量额外的开发成本的;
2、Robust兼容性与成功率较高,但是它与AndFix一样,无法新增变量与类只能用做的bugFix方案;
3、Qzone方案可以做到发布产品功能,但是它主要问题是插桩带来Dalvik的性能问题,以及为了解决Art下内存地址问题而导致补丁包急速增大的。

Tinker的已知问题

由于原理与系统限制,Tinker有以下已知问题:
1、Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件;
2、由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码;
3、在Android N上,补丁对应用启动时间有轻微的影响;
4、不支持部分三星android-21机型,加载补丁时会主动抛出"TinkerRuntimeException:checkDexInstall failed";
5、对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。

以上关于Tinker的介绍来自Tinker官方Wiki

Tinker集成

一、配置gradle

1,在项目的gradle.properties文件中添加Tinker的版本号

TINKER_VERSION=1.9.14.3
#TINKER_ID主要作用是区分当前打出的补丁包是基于哪个版本的apk,也就是说当前打出的补丁包能修复哪个版本的bug。这里可以填versionName
versionName=1.0.1
TINKER_ENABLE=true
android.enableD8.desugaring = true
android.useDexArchive = true

2,在项目的build.gradle中,添加tinker-patch-gradle-plugin的依赖

  dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.14.3')

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

3,在app的gradle文件app/build.gradle,添加tinker的库依赖

implementation 'com.android.support:multidex:1.0.3'
//optional, help to generate the final application
 compileOnly('com.tencent.tinker:tinker-android-anno:1.9.14.3')
//tinker's main Android lib
implementation('com.tencent.tinker:tinker-android-lib:1.9.14.3')

4,在app的gradle文件app/build.gradle,添加tinker的相关配置

下面就把整个app/build.gradle配置提出来,其中Tinker相关配置抽取到另一个文件tinkerpatch.gradle,其中比较重要的属性都标有中文注释,其余属性解释可以自行参考 Tinker 接入指南

apply from: 'tinkerpatch.gradle'
apply plugin: 'com.tencent.tinker.patch'

//-----------------------tinker配置区-----------------------------
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-release-1018-17-55-04"//这里需要修改为build/bakApk下面比对的旧包名字。这里填对应发版的文件名,只会修复发这个版本之后的bug,以前发的其它版本不起作用

//def gitSha() {//该方法需要安装git,并将项目与git建立连接,本例中不使用git,故注释
//    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'")
//        }
//        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'")
//    }
//}

/**
 * you can use assembleRelease to build you base apk
 * use tinkerPatchRelease -POLD_APK=  -PAPPLY_MAPPING=  -PAPPLY_RESOURCE= to build patch
 * add apk from the build/bakApk
 */
ext {
    //开发者模式下,关闭插件
    def sp = project.gradle.startParameter
    def taskName = sp.taskNames[0]
    def isopenthinker = true
    if (taskName.equals(":app:assembleDebug")) {
        isopenthinker = false
    }
    //for some reason, you may want to ignore tinkerBuild, such as instant run debug build?
    tinkerEnabled = isopenthinker

    //for normal build
    //old apk file to build patch apk
    tinkerOldApkPath = "${bakPath}/${baseInfo}.apk"
    //proguard mapping file to build patch apk
    tinkerApplyMappingPath = "${bakPath}/${baseInfo}-mapping.txt"
    //resource R.txt to build patch apk, must input if there is resource changed
    tinkerApplyResourcePath = "${bakPath}/${baseInfo}-R.txt"

    //only use for build all flavor, if not, just ignore this field
    tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}


def getOldApkPath() {
    return hasProperty("OLD_APK") ? OLD_APK : ext.tinkerOldApkPath
}

def getApplyMappingPath() {
    return hasProperty("APPLY_MAPPING") ? APPLY_MAPPING : ext.tinkerApplyMappingPath
}

def getApplyResourceMappingPath() {
    return hasProperty("APPLY_RESOURCE") ? APPLY_RESOURCE : ext.tinkerApplyResourcePath
}

def getTinkerIdValue() {
//    return hasProperty("TINKER_ID") ? TINKER_ID : gitSha()
    return versionName //需要保证TINKER_ID有设置(在gradle.properties中)
}

def buildWithTinker() {
    return hasProperty("TINKER_ENABLE") ? TINKER_ENABLE : ext.tinkerEnabled
}

def getTinkerBuildFlavorDirectory() {
    return ext.tinkerBuildFlavorDirectory
}

if (buildWithTinker()) {
    apply plugin: 'com.tencent.tinker.patch'

    tinkerPatch {
        /**
         * necessary,default 'null'
         * the old apk path, use to diff with the new apk to build
         * add apk from the build/bakApk
         * 必须,默认为null
         * 基准apk包的路径
         */
        oldApk = getOldApkPath()
        /**
         *
         * optional,default 'false'
         * there are some cases we may get some warnings
         * if ignoreWarning is true, we would just assert the patch process
         * case 1: minSdkVersion is below 14, but you are using dexMode with raw.
         *         it must be crash when load.
         * case 2: newly added Android Component in
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值