热更新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的集成使用_第1张图片

差异算法结构图:

热更新Tinker的集成使用_第2张图片

 

对比以上各优势果断选择了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"
}

它的具体含义如下:

参数 默认值 描述
tinkerEnable true 是否开启 tinkerpatchSupport 插件功能。
appKey "" 在 TinkerPatch 平台 申请的 appkey, 例如 sample 中的 'f828475486f91936'
appVersion "" 在 TinkerPatch 平台 输入的版本号, 例如 sample 中的 '1.0.0'。 注意,我们使用 appVersion 作为 TinkerId, 我们需要保证每个发布出去的基础安装包的 appVersion 都不一样。
reflectApplication false 是否反射 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工作顺利,身体健康,家庭和睦!祝大家步步高升!

















你可能感兴趣的:(微信热更新,热修复)