当前位置: 首页 > news >正文

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官网,就可以使用了

 

转载于:https://www.cnblogs.com/zxqflying/p/10404974.html

相关文章:

  • csv文件读写处理
  • 友链
  • HTML5 File API 全介绍
  • Grafana 利用Grafana Variables变量配置快速切换不同主机的图表数据展示
  • 在Windos上安装Nginx
  • [UE4]VR手柄按键参考
  • 2019 GDUT Rating Contest II : Problem G. Snow Boots
  • ORACLE查看数据库已安装补丁
  • VueJs之自动打开浏览器配置
  • ssh远程 和 上传/下载工具
  • DQN(Deep Reiforcement Learning) 发展历程(二)
  • Python使用Flask框架,结合Highchart,自定义导出菜单项目及顺序
  • 软件的安装
  • day8 编码2
  • HNOI/AHOI2018题解
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【391天】每日项目总结系列128(2018.03.03)
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Android交互
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • CAP理论的例子讲解
  • express + mock 让前后台并行开发
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Js基础知识(四) - js运行原理与机制
  • Otto开发初探——微服务依赖管理新利器
  • Python实现BT种子转化为磁力链接【实战】
  • Windows Containers 大冒险: 容器网络
  • Xmanager 远程桌面 CentOS 7
  • Zepto.js源码学习之二
  • 翻译--Thinking in React
  • 给新手的新浪微博 SDK 集成教程【一】
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 跨域
  • 普通函数和构造函数的区别
  • 前端面试题总结
  • 区块链技术特点之去中心化特性
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 通过npm或yarn自动生成vue组件
  • 我建了一个叫Hello World的项目
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 一个项目push到多个远程Git仓库
  • 用jQuery怎么做到前后端分离
  • 用简单代码看卷积组块发展
  • HanLP分词命名实体提取详解
  • ​flutter 代码混淆
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • ​一些不规范的GTID使用场景
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #WEB前端(HTML属性)
  • (1)SpringCloud 整合Python
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • ***利用Ms05002溢出找“肉鸡
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .h头文件 .lib动态链接库文件 .dll 动态链接库