Tinker热修复框架接入
Android现在开发App基本都开始接入
热修复
框架,为的就是能够修复一些线上紧急Bug。热门的热修复框架以及对比,网上介绍的也很多,个人而言就用过腾讯的tinker以及阿里的sophix。
腾讯tinkerTinker简介,根据官方文档接入tinker,然后测试热修复补丁,总是莫名地失败(或许是自己技术太渣)。无奈就不去折腾它,而选择了第三方的tinkerpatch
这个sdk,并测试补丁ok。
注:参照网上的tinker接入博客,以及官方文档,自己总是搞不定,说是自己技术渣吧,也可能。反正我参照阿里的文档接入sophix就很顺利。
闲言少续,言归正传,以下为接入tinkerpatch
的大致步骤
- 在项目根
build.gradle
加入依赖配置
buildscript {
repositories {
...
maven { url 'https://dl.bintray.com/wemobiledev/maven' }
maven { url 'https://dl.bintray.com/tinker/maven' }
}
dependencies {
...
// TinkerPatch 插件
classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.8"
}
}
- 在
app
的build.gradle
中,添加依赖
apply from: '../tinkerpatch.gradle'
dependencies{
// 若使用annotation需要单独引用,对于tinker的其他库都无需再引用
implementation 'com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.8'
annotationProcessor 'com.tinkerpatch.tinker:tinker-android-anno:1.9.8'
//dex分包,用于tinker
implementation "com.android.support:multidex:1.0.3"
...
}
-
根据上面的配置,就需要创建换一个
tinkerpatch.gradle
文件,路径与app
的builde.gradle
同级。一般来说,需要注意两个位置appKey就是你在tinkerpatch平台上的key
sevenZip的版本和路径配置,对应到你本地的路径。(注意,这里可能你会下载不到,maven仓库配置一下阿里的jcenter比较好)
-
7zip文件的下载,7za这个好多人没有,需要https://www.7-zip.org/download.html这里面的download目录下
7-Zip Extra: standalone console version, 7z DLL, Plugin for Far Manager
这一栏。然后解压到你对应路径,配置到下面就好。 com.tencent.mm:SevenZip:1.2.12
有时候加载不出来,你就在app的buidle.gradle
中添加这个依赖implementation com.tencent.mm:SevenZip:1.2.12
来下载,就好。这里用到一个变量
appversionName
需要你配置在gradle中的一个变量,就是app的版本号。可以在根目录的gradle.properties
中配置,如:
appVersionCode=16
appVersionName=2.0.2
注意,有时候AS设置中去掉compile
设置项下的--offline
参数比较好
import java.util.regex.Matcher
import java.util.regex.Pattern
apply plugin: 'tinkerpatch-support'
/**
* TODO: 请按自己的需求修改为适应自己工程的参数
*/
def bakPath = file("${buildDir}/bakApk/")
tinkerpatchSupport {
/** 可以在debug的时候关闭 tinkerPatch **/
tinkerEnable = true
/** 是否使用一键接入功能 **/
reflectApplication = true
/** 是否开启加固模式,只有在使用加固时才能开启此开关 **/
protectedApp = false
/** 补丁是否支持新增 Activity •(exported必须为false•)**/
supportComponent = false
autoBackupApkPath = "${bakPath}"
/** 在tinkerpatch.com得到的appKey **/
appKey = "20155552655555522"
/** 注意: 若发布新的全量包, appVersion一定要更新 **/
appVersion = appVersionName
baseApkFile = "${bakPath}/app-${appVersionName}.apk"
baseProguardMappingFile = "${bakPath}/app-${appVersionName}-mapping.txt"
baseResourceRFile = "${bakPath}/app-${appVersionName}-R.txt"
/**
* (可选)重命名备份文件的格式化字符串,默认为'${appName}-${variantName}'
*
* Available vars:
* 1\. projectName
* 2\. appName
* 3\. packageName
* 4\. buildType
* 5\. versionName
* 6\. versionCode
* 7\. buildTime
* 8\. fileSHA1
* 9\. flavorName
* 10\. variantName
*
* default value: '${appName}-${variantName}'
* Note: plz use single-quotation wrapping this format string
*/
backupFileNameFormat = '${appName}-${variantName}'
/**
* 若有编译多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
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.2.12"
path = "D:\\Android\\7z\\x64\\7za.exe"
}
buildConfig {
keepDexApply = false
}
}
/**
* 如果只想在Release中打开tinker,可以把tinkerEnable赋值为这个函数的return
* @return 是否为release
*/
def isRelease() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern
if (tskReqStr.contains("assemble")) {
println tskReqStr
pattern = Pattern.compile("assemble(\\w*)(Release|Debug)")
} else {
pattern = Pattern.compile("generate(\\w*)(Release|Debug)")
}
Matcher matcher = pattern.matcher(tskReqStr)
if (matcher.find()) {
String task = matcher.group(0).toLowerCase()
println("[BuildType] Current task: " + task)
return task.contains("release")
} else {
println "[BuildType] NO MATCH FOUND"
return true
}
}
其他基本不做修改,或者可以根据自身项目配置。
- 在自定义的
application
中,配置并初始化tinkerpatch
:
private ApplicationLike tinkerApplicationLike;//Tinker
@Override
public void onCreate() {
super.onCreate();
//init tinkerpatch
initTinkerPatch();
...
}
@Override
public void attachBaseContext(Context base) {
super.attachBaseContext(base);
//you must install multiDex whatever tinker is installed!
MultiDex.install(base);
}
/**
* 我们需要确保至少对主进程跟patch进程初始化 TinkerPatch
*/
@SuppressLint("LongLogTag")
private void initTinkerPatch() {
// 我们可以从这里获得Tinker加载过程的信息
if (BuildConfig.TINKER_ENABLE) {
tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
// 初始化TinkerPatch SDK
TinkerPatch.init(tinkerApplicationLike)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true)
.setFetchPatchIntervalByHours(3);
// fetchPatchUpdateAndPollWithInterval 与 fetchPatchUpdate(false)
// 不同的是,会通过handler的方式去轮询
TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
}
}
这里需要注意的是,如果app使用了多进程,就尽可能只初始化一次。多次初始化有没有问题,我没试过。
然后在启动的activity或者你需要的地方自动调用
在activity的需要的地方,调用TinkerPatch.with().fetchPatchUpdate(true);
就会联网请求tinkerpatch
平台上你所发布的对应版本的补丁。-
以上配置ok的话,每次打包就会在
project/app/build/bakapk/
下面生成如app-2.0.2-1012-11-25-31
样式的文件夹,里面有debug
文件夹,下有app-debug.apk以及app-debug-R.txt。如果你运行的release的build,就是release文件夹下
在AS的右侧Gradle栏目下,找到app-build下运行assembleRelease就能生成release的包。
然后将上述的app-release.apk以及app-release-R.txt移动到
bakapk
目录下,并更改名称如app-2.0.2.apk
以及app-2.0.2-R.txt
。(这实在tinkerpatch.gradle
中配置的)。如果开启了混淆,则也需要生成基础包的时候把
mapping.txt
文件也放到如上的bakapk
目录下。运行AS的Gradle下app--tinker--tinkerPatchRelease的task,就会生成补丁包。在app--build--outputs--apk--tinkerPatch--release下有
patch-signed-7z.apk
的补丁包。上传之tinkerpatch平台,你的项目下,创建项目,创建补丁,然后选择发布补丁。
此时app启动,会联网下载补丁,再次退出启动的时候,就会应用补丁。有的可能需要启动三次(冷启动)。
注意的是,这里使用的演示是release构建,如果测试debug,你只需要build 对应debug包,然后tinkerpatch也是debug就行。
还有一点说明,好像tinkerpatch这个平台免费版的下发补丁次数有限制,如果是大型项目,还是自己研究如何使用tinker官方接入方式。或者可以使用阿里的sophix,接入也是很方便。打补丁也方便。