• android热修复--Tinker


    这篇只是记录tinker的集成sdk

    现在市场上的热修复工具或者框架有很多很多,比较出名的有阿里的 AndFix、美团的 Robust 以及 QZone 的超级补丁方案。这个方案各有利弊,但是今天我们不说这几个方案,我们来聊一聊另一个补丁方案——Tinker。首先我们上一张图:

    Tinker热补丁方案·不仅支持类、So以及资源的替换,它还是2.X-7.X的全平台支持。

    一:集成sdk

    第一步 添加 gradle 插件依赖

    在项目的Gradle添加依赖

    buildscript {
    repositories {
    jcenter()
    }
    dependencies {
    classpath 'com.android.tools.build:gradle:2.3.2'
    // TinkerPatch 插件
    classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.1.8"
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
    }
    }

    //注意:gradle3.0版本以上的后有不兼容的问题应该,会一直报错,改成2.3版本的没有问题

    第二步 集成 TinkerPatch SDK

    在app中的gradle添加denpendencies 依赖,注意:这两个gradle不是同一个gradle,上面的那个build gradle 是整个项目的,下面这个build gradle是在app里面的,注意区分

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

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

    1 apply from: 'tinkerpatch.gradle'

    第三步 配置 tinkerpatchSupport 参数

    好了,接下来我们就在app目录下创建这个tinkerpatch.gradle,如图所示的目录

    打开tinkerpatch.gradle,将 TinkerPatch 相关的配置都放于tinkerpatch.gradle中。

     1 apply plugin: 'tinkerpatch-support'
     2 
     3 /**
     4  * TODO: 请按自己的需求修改为适应自己工程的参数
     5  */
     6 
     7 //基包路径
     8 def bakPath = file("${buildDir}/bakApk/")
     9 //基包文件夹名(打补丁包的时候,需要修改)
    10 def baseInfo = "app-1.0.0-0220-09-08-09"
    11 //版本名称
    12 def variantName = "debug"
    13 
    14 /**
    15  * 对于插件各参数的详细解析请参考
    16  *
    17  */
    18 tinkerpatchSupport {
    19     //可以在debug的时候关闭 tinkerPatch
    20     tinkerEnable = true
    21     //是否使用一键接入功能 默认为false  是否反射 Application 实现一键接入;
    22     // 一般来说,接入 Tinker 我们需要改造我们的 Application, 若这里为 true, 即我们无需对应用做任何改造即可接入。
    23     reflectApplication = true
    24     //将每次编译产生的 apk/mapping.txt/R.txt 归档存储的位置
    25     autoBackupApkPath = "${bakPath}"
    26     appKey = "1a56e0adbf67926d"// 注意!!!  需要修改成你的appkey
    27 
    28     /** 注意: 若发布新的全量包, appVersion一定要更新 **/
    29     appVersion = "1.0.2"
    30 
    31     def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
    32     def name = "${project.name}-${variantName}"
    33     /**
    34      * 基准包的文件路径, 对应 tinker 插件中的 oldApk 参数;编译补丁包时,
    35      * 必需指定基准版本的 apk,默认值为空,则表示不是进行补丁包的编译
    36      */
    37     baseApkFile = "${pathPrefix}/${name}.apk"
    38 
    39     /**
    40      * 基准包的 Proguard mapping.txt 文件路径, 对应 tinker 插件 applyMapping 参数;在编译新的 apk 时候,
    41      * 我们希望通过保持基准 apk 的 proguard 混淆方式,
    42      * 从而减少补丁包的大小。这是强烈推荐的,编译补丁包时,我们推荐输入基准 apk 生成的 mapping.txt 文件。
    43      */
    44     baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
    45     /**
    46      * 基准包的资源 R.txt 文件路径, 对应 tinker 插件 applyResourceMapping 参数;在编译新的apk时候,
    47      * 我们希望通基准 apk 的 R.txt 文件来保持 Resource Id 的分配,这样不仅可以减少补丁包的大小,
    48      * 同时也避免由于 Resource Id 改变导致 remote view 异常
    49      */
    50     baseResourceRFile = "${pathPrefix}/${name}-R.txt"
    51     /**
    52      *  若有编译多flavors需求, 可以参照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
    53      *  注意: 除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息(相关工具:walle 或者 packer-ng)
    54      **/
    55 }
    56 
    57 /**
    58  * 用于用户在代码中判断tinkerPatch是否被使能
    59  */
    60 android {
    61     defaultConfig {
    62         buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
    63     }
    64 }
    65 /**
    66  * 一般来说,我们无需对下面的参数做任何的修改
    67  * 对于各参数的详细介绍请参考:
    68  * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
    69  */
    70 tinkerPatch {
    71     ignoreWarning = false
    72     useSign = true  //是否需要签名,打正式包如果这里是true,则要配置签名,否则会编译不过去
    73     dex {
    74         dexMode = "jar"
    75         pattern = ["classes*.dex"]
    76         loader = []
    77     }
    78     lib {
    79         pattern = ["lib/*/*.so"]
    80     }
    81 
    82     res {
    83         pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
    84         ignoreChange = []
    85         largeModSize = 100
    86     }
    87     packageConfig {
    88     }
    89     sevenZip {
    90         zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
    91 //        path = "/usr/local/bin/7za"
    92     }
    93     buildConfig {
    94         keepDexApply = false
    95     }
    96 }

    这里还需要注意一个地方,就是appKey,在我们登录tinker的官网,并且添加一个app版本以后,都会生成一个appkey,我们要把自己的appkey填到上面的配置中,附上一张图

    第四步 初始化 TinkerPatch SDK

    官方给了我们两种方式来初始化TinkerPatch SDK,第一种是reflectApplication = true 的情况,另一种reflectApplication = false的情况,今天我们说reflectApplication = true这种情况,另一种情况,大家可以到官网中看看
    简单来说一下这两种情况的区别啊,当reflectApplication = true这种情况是不需要更改我们项目的Application类,而reflectApplication = false的情况是需要改动Application这个类。

    初始化TinkerPatch SDK

     1 package zhangxiaoqiang.com.myapplication;
     2 
     3 /**
     4  * author: Administrator
     5  * created on: 2019/2/19 16:57
     6  * description:
     7  */
     8 
     9 import android.app.Application;
    10 
    11 import com.tencent.tinker.loader.app.ApplicationLike;
    12 import com.tinkerpatch.sdk.TinkerPatch;
    13 import com.tinkerpatch.sdk.loader.TinkerPatchApplicationLike;
    14 
    15 
    16 public class tinkerApplication extends Application {
    17 
    18     private ApplicationLike tinkerApplicationLike;
    19     @Override
    20     public void onCreate() {
    21         super.onCreate();
    22 
    23         if (BuildConfig.TINKER_ENABLE) {
    24             // 我们可以从这里获得Tinker加载过程的信息
    25             tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
    26 
    27             // 初始化TinkerPatch SDK, 更多配置可参照API章节中的,初始化SDK
    28             TinkerPatch.init(tinkerApplicationLike)
    29                     .reflectPatchLibrary()
    30                     .setPatchRollbackOnScreenOff(true)
    31                     .setPatchRestartOnSrceenOff(true);
    32 
    33             // 每隔3个小时去访问后台时候有更新,通过handler实现轮训的效果
    34             new FetchPatchHandler().fetchPatchWithInterval(3);
    35         }
    36     }
    37 }
     1 package zhangxiaoqiang.com.myapplication;
     2 
     3 /**
     4  * author: Administrator
     5  * created on: 2019/2/19 14:44
     6  * description:
     7  */
     8 
     9 
    10 import android.os.Handler;
    11 import android.os.Message;
    12 
    13 import com.tinkerpatch.sdk.TinkerPatch;
    14 
    15 
    16 
    17 public class FetchPatchHandler extends Handler {
    18 
    19     public static final long HOUR_INTERVAL = 3600 * 1000;
    20     private long checkInterval;
    21 
    22 
    23     /**
    24      * 通过handler, 达到按照时间间隔轮训的效果
    25      */
    26     public void fetchPatchWithInterval(int hour) {
    27         //设置TinkerPatch的时间间隔
    28         TinkerPatch.with().setFetchPatchIntervalByHours(hour);
    29         checkInterval = hour * HOUR_INTERVAL;
    30         //立刻尝试去访问,检查是否有更新
    31         sendEmptyMessage(0);
    32     }
    33 
    34 
    35     @Override
    36     public void handleMessage(Message msg) {
    37         super.handleMessage(msg);
    38         //这里使用false即可
    39         TinkerPatch.with().fetchPatchUpdate(false);
    40         //每隔一段时间都去访问后台, 增加10分钟的buffer时间
    41         sendEmptyMessageDelayed(0, checkInterval + 10 * 60 * 1000);
    42     }
    43 }
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     3     package="zhangxiaoqiang.com.myapplication">
     4 
     5     <uses-permission android:name="android.permission.INTERNET"/>
     6     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     7     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     8 
     9     <application
    10         android:allowBackup="true"
    11         android:icon="@mipmap/ic_launcher"
    12         android:label="@string/app_name"
    13         android:roundIcon="@mipmap/ic_launcher_round"
    14         android:supportsRtl="true"
    15         android:name=".tinkerApplication"
    16         android:theme="@style/AppTheme">
    17         <activity android:name=".MainActivity">
    18             <intent-filter>
    19                 <action android:name="android.intent.action.MAIN" />
    20 
    21                 <category android:name="android.intent.category.LAUNCHER" />
    22             </intent-filter>
    23         </activity>
    24     </application>
    25 
    26 </manifest>

    好了,到这里,集成Tinker的代码基本上已经完成了,现在运行看看如图

    双击assembleDebug就可以运行项目了,结果如图:

    然后在app-->build下有个app-debug.apk的包,我们将这个包安装到手机上,就相当于是我们本地的应用,在里面我加了一句话,如图

    接着我们打有补丁的包,打补丁的包之前,我们的改两个地方,在tinkerpatch.gradle中找到如图中的代码,我们需要将baseInfo,和variantName改成和自己的一直如图:

    改完以后,我们就可以打补丁的包了,如图

     将baseInfo的值改为 右图中1所对应的值,variantName的值改为右图2对应的值。改完以后,我们就可以打补丁的包了,如图

     然后在build --> outputs --> tinkerPatch 中就可以找到我们的补丁的包了,如图

     

     最后将我们的补丁包上传到tinker官网,就可以使用了

  • 相关阅读:
    2020最新版Springcloud-Alibaba ZooKeeper篇(三)
    2020最新版SpringCloud(H版&alibaba)框架开发教程(二)
    2020最新版SpringCloud(H版&alibaba)框架开发教程(一)
    String StringBuffer StringBuilder详细分析和面试题
    算法-一个经典sql 题和一个Java算法题
    大数据开发-Flume-频繁产生小文件原因和处理
    大数据开发-Hive-常用日期函数&&日期连续题sql套路
    MapReduce怎么优雅地实现全局排序
    intelliJ IDEA 鼠标光标消失问题
    maven依赖问题的出现原因与解决方式
  • 原文地址:https://www.cnblogs.com/zxqflying/p/10404974.html
Copyright © 2020-2023  润新知