之前用美团的热修复,下发补丁都是通过项目自身后台,这次集成tinker到一个已经上线的小项目里,所以有了本篇文章。
project级别gradle加入:
classpath "com.tencent.bugly:tinker-support:1.2.0"
app级别gradle加入:
apply from: 'tinker-support.gradle'//tinker-support.gradle是一个脚本文件
implementation 'com.tencent.bugly:crashreport_upgrade:latest.release'
//1. 指定tinker依赖版本(注:应用升级1.3.5版本起,不再内置tinker)
//2.为了便于解答问题,这里的tinker版本建议跟随此处demo设置,如果微信更新了tinker版本,bugly会定期同步更新
implementation 'com.tencent.bugly:nativecrashreport:latest.release'
implementation 'com.tencent.tinker:tinker-android-lib:1.9.14.3'
implementation "com.android.support:multidex:1.0.1"
签名设置:
signingConfigs {// 自动化打包配置
release {// 线上环境
keyAlias 'xxx'
keyPassword 'xxx'
storeFile file('xxx.jks')
storePassword 'xxx'
}
debug {// 开发环境
keyAlias 'xxx'
keyPassword 'xxx'
storeFile file('xxx.jks')
storePassword 'xxx'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release//这里很重要
multiDexEnabled = true
}
}
signingConfig signingConfigs.release//这行是在下面操作后自动加入的
该文件完整代码如下(可直接cv食用),注:文件是放在app目录下也就是和src,build等文件夹同级
apply plugin: 'com.tencent.bugly.tinker-support'
def bakPath = file("${buildDir}/bakApk/")
/**
* 此处填写每次构建生成的基准包目录
*/
def baseApkDir = "app-1230-14-53-01"
/**
* 对于插件各参数的详细解析请参考,如果没有特殊需求下面的参数都可以不用更改;如果apk需要加固等可以参考具体描述设置参数
*/
tinkerSupport {
// 开启tinker-support插件,默认值true
enable = true
// 指定归档目录,默认值当前module的子目录tinker
autoBackupApkDir = "${bakPath}"
//建议设置true,用户就不用再自己管理tinkerId的命名,插件会为每一次构建的base包自动生成唯一的tinkerId,默认命名规则是versionname.versioncode_时间戳
//具体参考https://github.com/BuglyDevTeam/Bugly-Android-Demo/wiki/Tinker-ID%E8%AF%A5%E6%80%8E%E4%B9%88%E8%AE%BE%E7%BD%AE
autoGenerateTinkerId = true
//tinkerId必须保证唯一性,如果两个base包的tinkerid是一样的,并且都联网激活了,那么后续补丁上传到后台的时候会出现匹配错误
tinkerId = "patch-1.0.0.0"
// 是否启用覆盖tinkerPatch配置功能,默认值false
// 开启后tinkerPatch配置不生效,即无需添加tinkerPatch
overrideTinkerPatchConfiguration = true
// 编译补丁包时,必需指定基线版本的apk,默认值为空
// 如果为空,则表示不是进行补丁包的编译
// @{link tinkerPatch.oldApk }
baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
// 对应tinker插件applyMapping
baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
// 对应tinker插件applyResourceMapping
baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
// buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
// 是否开启加固模式,默认为false
isProtectedApp = true
enableProxyApplication = false
supportHotplugComponent = true
}
/**
* 一般来说,我们无需对下面的参数做任何的修改
* 对于各参数的详细介绍请参考:
* https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
*/
tinkerPatch {
//oldApk ="${bakPath}/${appName}/app-debug.apk"
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
//tinkerId = "1.0.1-patch"
//applyMapping = "${bakPath}/${appName}/app-debug-mapping.txt" // 可选,设置mapping文件,建议保持旧apk的proguard混淆方式
//applyResourceMapping = "${bakPath}/${appName}/app-debug-R.txt" // 可选,设置R.txt文件,通过旧apk文件保持ResId的分配
}
}
加入TinkerApplication
public class SampleApplication extends TinkerApplication {
public SampleApplication() {
super(ShareConstants.TINKER_ENABLE_ALL, "com.xxx.xxx.SampleApplicationLike",
"com.tencent.tinker.loader.TinkerLoader", false);
}
}
public class SampleApplicationLike extends DefaultApplicationLike {
、
public static final String TAG = "Tinker.SampleApplicationLike";
public SampleApplicationLike(Application application, int tinkerFlags,
boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime,
long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
}
@Override
public void onCreate() {
super.onCreate();
// 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
Beta.autoCheckUpgrade = false;
Bugly.init(instance, "xxxxxx", true);
}
AndroidManifest文件里:路径都要对上
//2019-12-30:如果是使用美团的多渠道,打基础包请务必使用美团的打包命令,已经测试,渠道包可以上报tinkerId到bugly后台,下面的代码为不使用美团打包的,美团打包步骤本文不涉及,参考相关文章即可。
有bug的项目上线之前肯定都是不知道的,所以这里就模拟开始测试打包,注:多渠道打包分发补丁可参考美团的瓦力工具,可以一个补丁适用多个渠道,这里不再详解。好了,如果你要想在debug环境测那么直接shift+f10运行起来,也可以点击“assembleDebug”,如果想在正式打包环境测试那么就需要打出正式包了,也可以点击“assembleRelease”,很明显有时候这几个task命令找不到,所以就看情况使用了
①正式包就是app-release,debug就是app-debug,右边的日期对应生成基础包的日期,所以这里就要注意了,每次上线都要保留左边日期文件夹下的文件,因为打补丁就是用这些文件,这里也体现了版本控制代码的一个好处了,而且bakApk下的日期文件夹不会被覆盖打多少次包就生成多少个,下面的路径和文件名和上面的对应上!第二个是开启混淆后需要的。
// 编译补丁包时,必需指定基线版本的apk,默认值为空
// 如果为空,则表示不是进行补丁包的编译
// @{link tinkerPatch.oldApk }
baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
// 对应tinker插件applyMapping
baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
// 对应tinker插件applyResourceMapping
baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
// 构建基准包和补丁包都要指定不同的tinkerId,并且必须保证唯一性
tinkerId = "base-1.0.1"
②完成①后一定一定一定要把基础包联网运行一遍这时日志会打印“TINKER_ID:base-1.0.1”,这样bugly后台才能识别。接着去改bug代码,随便改几个字符串和基础包不一样就行,修改tinkerId="patch-1.0.1",补丁的和基础包不一样的别忘了,以后每次发版都要修改基础包和补丁版的,由于修改的插件gradle所以需要sync now一下,如果不sync now很大可能出现问题,好了,开始打补丁:
执行补丁task命令,debug和ralease看之前的基础包,打完后控制台会出现:
BUILD SUCCESSFUL in 1m 11s
78 actionable tasks: 9 executed, 69 up-to-date
10:29:54: Task execution finished 'buildTinkerPatchRelease'.
注意补丁的路径是在apk目录平级的patch包下的,如果不是,应该是打补丁的命令出了错,需要看之前介绍对着操作一下。。。
发布补丁后,退出app,然后再次进入app,看到以下日志说明成功,补丁加载完到app里之后一定要杀死进程冷启动才能补丁生效。。。
2019-09-20 10:24:23.504 32657-32657/? I/CrashReport: TINKER_ID:base-1.0.1
2019-09-20 10:24:23.504 32657-32657/? I/CrashReport: NEW_TINKER_ID:patch-1.0.1
文章结束,有什么问题欢迎指出和探讨~~~