热更新Tinker的集成使用

请珍惜劳动者的汗水,一分耕耘一分收获,转载请注明出处,谢谢!

初衷:如今热更新越来越火,各大厂也陆续开源自己的热更新框架。目前主流的热更新大概有以下一些,未统计到的望给予补充。

正好年底了有点时间,也总结一下。

1、Tinker 微信  2、QZone  QQ空间  3、阿里 AndFix  4、美团 Robust  5、Nuwa 俗称女娲 。。。。。。

下面就本人用到的Tinker做个分析,以及具体的实现步骤。

傻瓜式SDK Tinker进入参考文档:http://tinkerpatch.com/Docs/intro

当然还要一种是源码直接接入,自己管理后台服务,稍微复杂麻烦点,可参考github上Tinker的官方介绍:https://github.com/Tencent/tinker

具体的原理和差异算法大家可以去参考下官方文档


差异算法结构图:


 

对比以上各优势果断选择了Tinker,主要看中的是资源文件的替换,当然有一点不满意的就是无法及时生效,不过也不影响,还可以使用锁屏自动生效的方式,这一点还是挺好的!

2、集成步骤:

新建项目成功后配置build.gradle,有三处的gradle需要配置。由于文档并未完全标明,其中一个gradle的配置还是费了点精力^_^。最后还是再同事的一句话点醒了。

2.1 至于我们的Application可以使用我们平常项目中正常的方式,只需稍加盖上即可。

 

public class SampleApplication extends Application{
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        TinkerPatch.init(TinkerPatchApplicationLike.getTinkerPatchApplicationLike());
        TinkerPatch tinkerPatch = TinkerPatch.with();
        tinkerPatch.fetchPatchUpdate(true);  //向后台请求补丁升级配置;true,即每次调用都会真正的访问后台是否有更新。

    }
}


gradle结构:



都需要我们配置,其中tinkerpatch.gradle 需要手动建立,然后在 2 中进行引用

具体看下第1个 的内容:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        // TinkerPatch 插件
        classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.0.1" 
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


下面先看下 第3个 gradle的内容:

apply plugin: 'tinkerpatch-support'
def bakPath = file("${buildDir}/basekApk/")
def tempPath = "app-1.0.0-0113-10-26-03"

/**
 * 对于插件各参数的详细解析请参考
 * http://tinkerpatch.com/Docs/SDK
 */
tinkerpatchSupport {
    tinkerEnable = true
    appKey = "你要去申请的appkey"
    appVersion = "${APP_VERSIONNAME}"
    reflectApplication = true

    autoBackupApkPath = "${bakPath}"

    baseApkFile = "${bakPath}/${tempPath}/app-release.apk"   //app-debug.apk
    baseProguardMappingFile = "${bakPath}/${tempPath}/app-release-mapping.txt"   //app-debug-mapping.txt
    baseResourceRFile = "${bakPath}/${tempPath}/app-release-R.txt"    //app-debug-R.txt

}


/**
 * 一般来说,我们无需对下面的参数做任何的修改
 * 对于各参数的详细介绍请参考:
 * 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
    }
}

很简单

继续第2点,也没啥好将的,就是需要将第3个gradle进行apply 

apply from: 'tinkerpatch.gradle'
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.0'
    testCompile 'junit:junit:4.12'

    compile "com.android.support:multidex:1.0.1"
    //若使用annotation需要单独引用,对于tinker的其他库都无需再引用
    provided("com.tencent.tinker:tinker-android-anno:1.7.6") { changing = true }
    compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.0.1"){ changing = true }
}

至此Tinker的集成已经搞定!!!下面就是打包,编译差异包的过程了。下面还是列下官方的实现步骤吧,依葫芦画瓢,so sasy !

参考:http://tinkerpatch.com/Docs/SDK


集成完毕后将项目切换到Project模式下,可以看到这样的结构



展开Gradle projects 编译打包,其中tinker下是编译产生差异包



第一步 添加 gradle 插件依赖

gradle 远程仓库依赖 jcenter, 例如 TinkerPatch Sample 中的 build.gradle .
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // TinkerPatch 插件
        classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.0.2"
    }
}
注意,在这里SDK使用了fat打包的模式,我们不能再引入任何 Tinker 的相关依赖,否则会造成版本冲突。当前SDK是基于 tinker 1.7.6 内核开发的。

第二步 集成 TinkerPatch SDK

添加TinkerPatch SDK 库的 denpendencies 依赖, 可参考 Sample 中的 app/build.gradle:

dependencies {
    //若使用annotation需要单独引用,对于tinker的其他库都无需再引用
    provided("com.tencent.tinker:tinker-android-anno:1.7.6")
    compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.0.2")
}

注意,若使用 annotation 自动生成 Application, 需要单独引入 Tinker的 tinker-android-anno 库。除此之外,我们无需再单独引入 tinker 的其他库。

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

apply from: 'tinkerpatch.gradle'

第三步 配置 tinkerpatchSupport 参数

打开引入的 tinkerpatch.gradle 文件,它的具体参数如下:

tinkerpatchSupport {
    tinkerEnable = true
    appKey = "f828475486f91936"
    appVersion = "1.0.0"

    autoBackupApkPath = "${bakPath}"

    baseApkFile = "${bakPath}/${appName}/app-debug.apk"
    baseProguardMappingFile = "${bakPath}/${appName}/app-debug-mapping.txt"
    baseResourceRFile = "${bakPath}/${appName}/app-debug-R.txt"
}

它的具体含义如下:

参数默认值描述
tinkerEnabletrue是否开启 tinkerpatchSupport 插件功能。
appKey""在 TinkerPatch 平台 申请的 appkey, 例如 sample 中的 'f828475486f91936'
appVersion""在 TinkerPatch 平台 输入的版本号, 例如 sample 中的 '1.0.0'。 注意,我们使用 appVersion 作为 TinkerId, 我们需要保证每个发布出去的基础安装包的 appVersion 都不一样。
reflectApplicationfalse是否反射 Application 实现一键接入;一般来说,接入 Tinker 我们需要改造我们的 Application, 若这里为 true, 即我们无需对应用做任何改造即可接入
autoBackupApkPath""将每次编译产生的 apk/mapping.txt/R.txt 归档存储的位置
baseApkFile""基准包的文件路径, 对应 tinker 插件中的 oldApk 参数;编译补丁包时,必需指定基准版本的 apk,默认值为空,则表示不是进行补丁包的编译。
baseProguardMappingFile""基准包的 Proguard mapping.txt 文件路径, 对应 tinker 插件 applyMapping 参数;在编译新的 apk 时候,我们希望通过保持基准 apk 的 proguard 混淆方式,从而减少补丁包的大小。这是强烈推荐的,编译补丁包时,我们推荐输入基准 apk 生成的 mapping.txt 文件。
baseResourceRFile""基准包的资源 R.txt 文件路径, 对应 tinker 插件 applyResourceMapping 参数;在编译新的apk时候,我们希望通基准 apk 的 R.txt 文件来保持 Resource Id 的分配,这样不仅可以减少补丁包的大小,同时也避免由于 Resource Id 改变导致 remote view 异常。

一般来说,我们无需修改引用 android 的编译配置,也不用修改 tinker 插件原来的配置。针对特殊需求,具体的参数含义可参考 Tinker 文档:Tinker 接入指南.

第四步 初始化 TinkerPatch SDK

最后在我们的代码中,只需简单的初始化 TinkerPatch 的 SDK 即可,我们无需考虑 Tinker 是如何下载/合成/应用补丁包, 也无需引入各种各样 Tinker 的相关类。

1. reflectApplication = true 的情况

若我们使用 reflectApplication 模式,我们无需为接入 Tinker 而改造我们的 Application 类。初始化 SDK 可参考 tinkerpatch-easy-sample 中的 SampleApplication 类.

public class SampleApplication extends Application {
...
     public void attachBaseContext(Context base) {
         TinkerPatch.init(TinkerPatchApplicationLike.getTinkerPatchApplicationLike());
     }
...

我们将 Tinker 加载补丁过程的结果存放在 TinkerPatchApplicationLike 中。

2. reflectApplication = false 的情况

若我们已经完成了应用的 Application 改造,即将 Application 的逻辑移动到 ApplicationLike类中。我们可以参考 tinkerpatch-sample 中的 SampleApplicationLike 类.

public class SampleApplicationLike extends DefaultApplicationLike {
...
     public void onBaseContextAttached(Context base) {
        TinkerPatch.init(this);
     }
...
}

第五步 使用步骤

TinkerPatch 的使用步骤非常简单,一般来说可以参考以下几个步骤:

  1. 运行 assembleRelease task 构建基准包,即将要发布的版本;
  2. 通过 autoBackupApkPath 保存编译的产物 apk/mapping.txt/R.txt 文件;
  3. 若想发布补丁包, 只需将步骤2保存下来的文件分别填到 baseApkFile/baseProguardMappingFile/baseResourceRFile 参数中;
  4. 运行 tinkerPatchRelease task 构建补丁包,补丁包将位于 build/outputs/tinkerPatch 中。

搞定!


后面就是将差异包提交的Tinker的Web上了。


差异包的发布可根据需要选择条件,不再啰嗦了。大家可以自己去看下介绍,没什么难度。有不懂的可以直接评论,第一次写这么长的博客,自我感觉都很烂,但这是一个锻炼的过程,而且没有足够的时间来总结,只是碰巧今天又点时间就先写上来了。公司一直都忙忙忙啊!!!!!受不了了,再看看咱们的IOS多爽,3个月没做过项目,爽死了!不过谁叫我们是Android屌丝呢^_^,吐槽归吐槽,还是要把工作干好!最后期待18号年会能给我抽个大奖啊!!!


各位见笑了,有问题Call我,能解决的一定尽力,帮不到的一起努力!祝自己2017工作顺利,身体健康,家庭和睦!祝大家步步高升!

















  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值