Android热修复——Tinker的集成
前言
做前端开发的都知道,当我们项目做完了以后,都会把应用上传到应用市场上供用户下载使用,比如上传到应用宝啊,应用汇啊,360啊,小米,华为,魅族啊,等等
但是,有时候我们会经常遇到一些很扯淡的事情,刚刚熬夜加班将项目发到应用市场上,第二天,又发现一个严重bug,难道是开会研究看看是否能在下一版解决?还是将bug解决了,
在给测试进行测试,然后再发版?如果从新发版,这个成本太高了,那怎么办呢,今天我们就来谈一谈热修复——Tinker!
现在市场上的热修复工具或者框架有很多很多,比较出名的有阿里的 AndFix、美团的 Robust 以及 QZone 的超级补丁方案。这个方案各有利弊,但是今天我们不说这几个方案,我们来聊一聊另一个补丁方案——Tinker。首先我们上一张图:
Tinker热补丁方案·不仅支持类、So以及资源的替换,它还是2.X-7.X的全平台支持。
在官网上,介绍这个Tinker,用了一句话:Tinker 已运行在微信的数亿 Android 设备上,那么为什么你不使用 Tinker 呢? ps:别人几亿的用户量在用Tinker,都不担心出现什么问题,
你们几个用户量的应用,还整天瞎担心。
这篇文章,主要是和大家聊一下怎么集成这个Tinker,并不会设计很多原理的东西,如果需要了解更深入的原理性的东西,可以到官网看看。点击官网http://tinkerpatch.com/Docs/intro
集成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
}
}
第二步 集成 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")
}
注意,若使用 annotation 自动生成 Application, 需要单独引入 Tinker 的 tinker-android-anno 库。除此之外,我们无需再单独引入 tinker 的其他库。
为了简单方便,我们将 TinkerPatch 相关的配置都放于 tinkerpatch.gradle 中, 我们需要将其引入:
apply from: 'tinkerpatch.gradle'
第三步 配置 tinkerpatchSupport 参数
好了,接下来我们就在app目录下创建这个tinkerpatch.gradle,如图所示的目录
打开tinkerpatch.gradle,将 TinkerPatch 相关的配置都放于tinkerpatch.gradle中。
apply plugin: 'tinkerpatch-support' /**
* TODO: 请按自己的需求修改为适应自己工程的参数
*/ //基包路径
def bakPath = file("${buildDir}/bakApk/")
//基包文件夹名(打补丁包的时候,需要修改)
def baseInfo = "app-1.0.1-1018-17-29-31"
//版本名称
def variantName = "debug" /**
* 对于插件各参数的详细解析请参考
*
*/
tinkerpatchSupport {
//可以在debug的时候关闭 tinkerPatch
tinkerEnable = true
//是否使用一键接入功能 默认为false 是否反射 Application 实现一键接入;
// 一般来说,接入 Tinker 我们需要改造我们的 Application, 若这里为 true, 即我们无需对应用做任何改造即可接入。
reflectApplication = true
//将每次编译产生的 apk/mapping.txt/R.txt 归档存储的位置
autoBackupApkPath = "${bakPath}"
appKey = "这里的appKey修改成你自己的appkey"// 注意!!! 需要修改成你的appkey /** 注意: 若发布新的全量包, appVersion一定要更新 **/
appVersion = "1.0.1" def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
def name = "${project.name}-${variantName}"
/**
* 基准包的文件路径, 对应 tinker 插件中的 oldApk 参数;编译补丁包时,
* 必需指定基准版本的 apk,默认值为空,则表示不是进行补丁包的编译
*/
baseApkFile = "${pathPrefix}/${name}.apk" /**
* 基准包的 Proguard mapping.txt 文件路径, 对应 tinker 插件 applyMapping 参数;在编译新的 apk 时候,
* 我们希望通过保持基准 apk 的 proguard 混淆方式,
* 从而减少补丁包的大小。这是强烈推荐的,编译补丁包时,我们推荐输入基准 apk 生成的 mapping.txt 文件。
*/
baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
/**
* 基准包的资源 R.txt 文件路径, 对应 tinker 插件 applyResourceMapping 参数;在编译新的apk时候,
* 我们希望通基准 apk 的 R.txt 文件来保持 Resource Id 的分配,这样不仅可以减少补丁包的大小,
* 同时也避免由于 Resource Id 改变导致 remote view 异常
*/
baseResourceRFile = "${pathPrefix}/${name}-R.txt"
/**
* 若有编译多flavors需求, 可以参照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
* 注意: 除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息(相关工具:walle 或者 packer-ng)
**/
} /**
* 用于用户在代码中判断tinkerPatch是否被使能
*/
android {
defaultConfig {
buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
}
}
/**
* 一般来说,我们无需对下面的参数做任何的修改
* 对于各参数的详细介绍请参考:
* https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
*/
tinkerPatch {
ignoreWarning = false
useSign = true //是否需要签名,打正式包如果这里是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
}
}
简单的说一下这里的参数配置:如图
这里还需要注意一个地方,就是appKey,在我们登录tinker的官网,并且添加一个app版本以后,都会生成一个appkey,我们要把自己的appkey填到上面的配置中,附上一张图
第四步 初始化 TinkerPatch SDK
官方给了我们两种方式来初始化TinkerPatch SDK,第一种是reflectApplication = true 的情况,另一种reflectApplication = false的情况,今天我们说reflectApplication = true这种情况,另一种情况,大家可以到官网中看看
简单来说一下这两种情况的区别啊,当reflectApplication = true这种情况是不需要更改我们项目的Application类,而reflectApplication = false的情况是需要改动Application这个类。
初始化TinkerPatch SDK
package com.example.administrator.tinkerdemotest; import android.app.Application; import com.tencent.tinker.loader.app.ApplicationLike;
import com.tinkerpatch.sdk.TinkerPatch;
import com.tinkerpatch.sdk.loader.TinkerPatchApplicationLike; /**
* Created by Administrator on 2017/10/18 0018.
*
* reflectApplication = true 时
*/ public class tinkerApplication extends Application { private ApplicationLike tinkerApplicationLike;
@Override
public void onCreate() {
super.onCreate(); if (BuildConfig.TINKER_ENABLE) {
// 我们可以从这里获得Tinker加载过程的信息
tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike(); // 初始化TinkerPatch SDK, 更多配置可参照API章节中的,初始化SDK
TinkerPatch.init(tinkerApplicationLike)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true); // 每隔3个小时去访问后台时候有更新,通过handler实现轮训的效果
new FetchPatchHandler().fetchPatchWithInterval(3);
}
}
}
最后在加上FetchPatchHandler这个类
package com.example.administrator.tinkerdemotest; import android.os.Handler;
import android.os.Message; import com.tinkerpatch.sdk.TinkerPatch; /**
* Created by Administrator on 2017/10/18 0018.
*/ public class FetchPatchHandler extends Handler { public static final long HOUR_INTERVAL = 3600 * 1000;
private long checkInterval; /**
* 通过handler, 达到按照时间间隔轮训的效果
*/
public void fetchPatchWithInterval(int hour) {
//设置TinkerPatch的时间间隔
TinkerPatch.with().setFetchPatchIntervalByHours(hour);
checkInterval = hour * HOUR_INTERVAL;
//立刻尝试去访问,检查是否有更新
sendEmptyMessage(0);
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//这里使用false即可
TinkerPatch.with().fetchPatchUpdate(false);
//每隔一段时间都去访问后台, 增加10分钟的buffer时间
sendEmptyMessageDelayed(0, checkInterval + 10 * 60 * 1000);
}
}
最后将AndroidManifest.xml中的添加上相应的网络和SD的权限,还要在application中加上 android:name=".tinkerApplication",附上代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.tinkerdemotest"> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:name=".tinkerApplication"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>
好了,到这里,集成Tinker的代码基本上已经完成了,现在运行看看如图
双击assembleDebug就可以运行项目了,结果如图:
然后在app-->build下有个app-debug.apk的包,我们将这个包安装到手机上,就相当于是我们本地的应用,在里面我加了一句话,如图
接着我们打有补丁的包,打补丁的包之前,我们的改两个地方,在tinkerpatch.gradle中找到如图中的代码,我们需要将baseInfo,和variantName改成和自己的一直如图:
改完以后,我们就可以打补丁的包了,如图
将baseInfo的值改为 右图中1所对应的值,variantName的值改为右图2对应的值。改完以后,我们就可以打补丁的包了,如图
然后在build --> outputs --> tinkerPatch 中就可以找到我们的补丁的包了,如图
最后将我们的补丁包上传到tinker官网,就可以使用了,如图
最后附上一条动态的效果图。注意:一定要把app进程杀死,才会有效果。
源码链接:https://github.com/343661629/Tinker
Android热修复——Tinker的集成的更多相关文章
- Android 热修复 Tinker接入及源码浅析
一.概述 放了一个大长假,happy,先祝大家2017年笑口常开. 假期中一行代码没写,但是想着马上要上班了,赶紧写篇博客回顾下技能,于是便有了本文. 热修复这项技术,基本上已经成为项目比较重要的模块 ...
- Android 热修复 Tinker接入及源代码浅析
本文已在我的公众号hongyangAndroid首发.转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/54882693本文出自张鸿 ...
- Android 热修复 Tinker platform 中的坑,以及详细步骤(二)
操作流程: 一.注册平台账号: http://www.tinkerpatch.com 二.查看操作文档: http://www.tinkerpatch.com/Docs/SDK 参考文档: https ...
- Android热修复之微信Tinker使用初探
文章地址:Android热修复之微信Tinker使用初探 前几天,万众期待的微信团队的Android热修复框架tinker终于在GitHub上开源了. 地址:https://github.com/ ...
- Android 热修复方案Tinker
转自:http://blog.csdn.net/l2show/article/details/53925543 Android 热修复方案Tinker(一) Application改造 Android ...
- Android 热修复方案Tinker(一) Application改造
基于Tinker V1.7.5 Android 热修复方案Tinker(一) Application改造 Android 热修复方案Tinker(二) 补丁加载流程 Android 热修复 ...
- Android热修复技术总结
https://blog.csdn.net/xiangzhihong8/article/details/77718004 插件化和热修复技术是Android开发中比较高级的知识点,是中级开发人员通向高 ...
- 深入探索Android热修复技术原理读书笔记 —— 资源热修复技术
该系列文章: 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍 深入探索Android热修复技术原理读书笔记 -- 代码热修复技术 1 普遍的实现方式 Android资源的热修复,就 ...
- 全面了解Android热修复技术
WeTest 导读 本文探讨了Android热修复技术的发展脉络,现状及其未来. 热修复技术概述 热修复技术在近年来飞速发展,尤其是在InstantRun方案推出之后,各种热修复技术竞相涌现.国内大部 ...
随机推荐
- JavaScript学习-1
本章目录: --------①数据类型. --------②定义变量. --------③类型转换. --------④运算符. --------⑤比较符. --------⑥if语句. ------ ...
- Itellj Idea使用技巧
模板设置: 类模板:File–>Settings–>Editor–>File and Code Templates–>Includes–>File Header 输入缩写 ...
- 保存xml报错 'UTF_8' is not a supported encoding name
ArgumentException: 'UTF_8' is not a supported encoding name. For information on defining a custom en ...
- 2019/1/9 6系列所有装置编号与SIM卡信息抓取
一.报错:File "G:/station/6系列装置信息明细.py", line 12, in <module>workbook.save(r'.\6系列装置明细表. ...
- html迪士尼网页实现代码
html body> <div> <!-- 导航设置 --> <header> <nav ...
- P1147连续自然数和-(尺取法)
https://www.luogu.org/problemnew/show/P1147 题意:输入一个n,求连续几个数加起来等于n,输出这几个连续的数的第一个和最后一个.10<=n<=20 ...
- Linux 进程通信方式
转载文章 进程通信的方式 管道( pipe ): 管道包括三种: 普通管道PIPE: 通常有两种限制,一是单工,只能单向传输;二是只能在父子或者兄弟进程间使用. 流管道s_pipe: 去除了第一种限制 ...
- Linux - 操作系统
操作系统(科普章节) 目标 了解操作系统及作用 1. 操作系统(Operation System,OS) 操作系统作为接口的示意图 没有安装操作系统的计算机,通常被称为 裸机 如果想在 裸机 上运行自 ...
- FortiGate安全策略说明
1.安全策略原理 1)为了对数据流进行统一控制,方便用户配置和管理,FGT设备引入了安全策略的概念.通过配置安全策略,防火墙能够对经过设备的数据流进行有效的控制和管理. 2)当防火墙收到数据报文时,把 ...
- 【实习】从ubuntu迁移过来的代码,在centos上编译问题的解决汇总
目前自己的开发环境(同将来线上环境)是centos 7.我这里主要实现服务端.需要组里其他同学提供一个接口(视频编辑).公司内部自己开发环境 通常是台式ubuntu16.04.所以提供视频处理接口是在 ...