Tinker的具体介绍和优劣请移步官网查看
TinkerPatch 平台官网 :http://www.tinkerpatch.com/Docs/intro
下面主要介绍官网介绍的简易配置使用Tinker的方式:
一 :官网注册并新建app
1、需要参数,appKey 新建第一个需要发布的版本
二、项目接入TinkerPatch
(参考官方简易demo:https://github.com/TinkerPatch/tinkerpatch-easy-sample)
(官方全部的demo后期研究: https://github.com/TinkerPatch)
1、新建个测试项目TinkerDemo:
2、根目录build.gradle中加入
classpath("com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.13") { changing = true }
3、引入依赖:
implementation("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.8")
4、配置签名包:
signingConfigs {
release {
storeFile file("...")
storePassword "..."
keyAlias "..."
keyPassword "..."
}
}
buildTypes {
debug {
debuggable true
}
release {
debuggable false
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
...
}
}
5、在app目录下新建文件 tinkerpatch.gradle
(tinker的具体配置参数文件,里面内容 参考官方简易demo:https://github.com/TinkerPatch/tinkerpatch-easy-sample)
tinkerpatch.gradle具体代码如下:
(appKey 就是你在平台申请的appKey ;appVersion = "1.1.0" 和你的app中build.gradle中versionName "1.1.0"统一,只有在全量包更新时才去进行修改)
apply plugin: 'tinkerpatch-support'
import java.util.regex.Matcher
import java.util.regex.Pattern
/**
* TODO: 请按自己的需求修改为适应自己工程的参数
*/
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-1.1.0-0808-18-10-27"
def variantName = "release"
/**
* 对于插件各参数的详细解析请参考
* http://tinkerpatch.com/Docs/SDK
*/
tinkerpatchSupport {
/** 可以在debug的时候关闭 tinkerPatch, isRelease() 可以判断BuildType是否为Release **/
tinkerEnable = true
reflectApplication = true
/**
* 是否开启加固模式,只能在APK将要进行加固时使用,否则会patch失败。
* 如果只在某个渠道使用了加固,可使用多flavors配置
**/
protectedApp = false
/**
* 实验功能
* 补丁是否支持新增 Activity (新增Activity的exported属性必须为false)
**/
supportComponent = true
autoBackupApkPath = "${bakPath}"
appKey = "6125dd27ea01..."
/** 注意: 若发布新的全量包, appVersion一定要更新 **/
appVersion = "1.1.0"
def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
def name = "${project.name}-${variantName}"
baseApkFile = "${pathPrefix}/${name}.apk"
baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
baseResourceRFile = "${pathPrefix}/${name}-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.1.10"
// path = "/usr/local/bin/7za"
}
buildConfig {
keepDexApply = false
}
}
import java.util.regex.Matcher
import java.util.regex.Pattern
/**
* 如果只想在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;
}
}
6、在app下的build.gradle引入 tinkerpatch.gradle文件:
apply from: 'tinkerpatch.gradle'
7、新建SampleApplication(初始化Tinker,不需要修改什么参数,复制过去就能用):
package com.zjsos.www.tinkerdemo;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import com.tencent.tinker.lib.listener.DefaultPatchListener;
import com.tencent.tinker.lib.patch.UpgradePatch;
import com.tencent.tinker.lib.reporter.DefaultLoadReporter;
import com.tencent.tinker.lib.reporter.DefaultPatchReporter;
import com.tencent.tinker.lib.service.PatchResult;
import com.tencent.tinker.loader.app.ApplicationLike;
import com.tinkerpatch.sdk.TinkerPatch;
import com.tinkerpatch.sdk.loader.TinkerPatchApplicationLike;
import com.tinkerpatch.sdk.server.callback.ConfigRequestCallback;
import com.tinkerpatch.sdk.server.callback.RollbackCallBack;
import com.tinkerpatch.sdk.server.callback.TinkerPatchRequestCallback;
import com.tinkerpatch.sdk.tinker.callback.ResultCallBack;
import com.tinkerpatch.sdk.tinker.service.TinkerServerResultService;
import java.util.HashMap;
/**
* Author:Stephen
* Blog: https://me.csdn.net/jifenglie
* Date:2019/8/8
* Description:
*/
public class SampleApplication extends Application {
private static final String TAG = "Tinker.SampleApppatch";
private ApplicationLike tinkerApplicationLike;
public SampleApplication() {
}
@Override
public void attachBaseContext(Context base) {
super.attachBaseContext(base);
//you must install multiDex whatever tinker is installed!
//MultiDex.install(base);
}
/**
* 由于在onCreate替换真正的Application,
* 我们建议在onCreate初始化TinkerPatch,而不是attachBaseContext
*/
@Override
public void onCreate() {
super.onCreate();
initTinkerPatch();
}
/**
* 我们需要确保至少对主进程跟patch进程初始化 TinkerPatch
*/
private void initTinkerPatch() {
// 我们可以从这里获得Tinker加载过程的信息
if (BuildConfig.TINKER_ENABLE) {
tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
// 初始化TinkerPatch SDK
TinkerPatch.init(
tinkerApplicationLike
// new TinkerPatch.Builder(tinkerApplicationLike)
// .requestLoader(new OkHttp3Loader())
// .build()
)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true)
.setFetchPatchIntervalByHours(3)
;
// 获取当前的补丁版本
Log.d(TAG, "Current patch version is " + TinkerPatch.with().getPatchVersion());
// fetchPatchUpdateAndPollWithInterval 与 fetchPatchUpdate(false)
// 不同的是,会通过handler的方式去轮询
TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
}
}
/**
* 在这里给出TinkerPatch的所有接口解释
* 更详细的解释请参考:http://tinkerpatch.com/Docs/api
*/
private void useSample() {
TinkerPatch.init(tinkerApplicationLike)
//是否自动反射Library路径,无须手动加载补丁中的So文件
//注意,调用在反射接口之后才能生效,你也可以使用Tinker的方式加载Library
.reflectPatchLibrary()
//向后台获取是否有补丁包更新,默认的访问间隔为3个小时
//若参数为true,即每次调用都会真正的访问后台配置
.fetchPatchUpdate(false)
//设置访问后台补丁包更新配置的时间间隔,默认为3个小时
.setFetchPatchIntervalByHours(3)
//向后台获得动态配置,默认的访问间隔为3个小时
//若参数为true,即每次调用都会真正的访问后台配置
.fetchDynamicConfig(new ConfigRequestCallback() {
@Override
public void onSuccess(HashMap<String, String> hashMap) {
}
@Override
public void onFail(Exception e) {
}
}, false)
//设置访问后台动态配置的时间间隔,默认为3个小时
.setFetchDynamicConfigIntervalByHours(3)
//设置当前渠道号,对于某些渠道我们可能会想屏蔽补丁功能
//设置渠道后,我们就可以使用后台的条件控制渠道更新
.setAppChannel("default")
//屏蔽部分渠道的补丁功能
.addIgnoreAppChannel("googleplay")
//设置tinkerpatch平台的条件下发参数
.setPatchCondition("test", "1")
//设置补丁合成成功后,锁屏重启程序
//默认是等应用自然重启
.setPatchRestartOnSrceenOff(true)
//我们可以通过ResultCallBack设置对合成后的回调
//例如弹框什么
//注意,setPatchResultCallback 的回调是运行在 intentService 的线程中
.setPatchResultCallback(new ResultCallBack() {
@Override
public void onPatchResult(PatchResult patchResult) {
Log.i(TAG, "onPatchResult callback here");
}
})
//设置收到后台回退要求时,锁屏清除补丁
//默认是等主进程重启时自动清除
.setPatchRollbackOnScreenOff(true)
//我们可以通过RollbackCallBack设置对回退时的回调
.setPatchRollBackCallback(new RollbackCallBack() {
@Override
public void onPatchRollback() {
Log.i(TAG, "onPatchRollback callback here");
}
});
}
/**
* 自定义Tinker类的高级用法, 使用更灵活,但是需要对tinker有更进一步的了解
* 更详细的解释请参考:http://tinkerpatch.com/Docs/api
*/
private void complexSample() {
//修改tinker的构造函数,自定义类
TinkerPatch.Builder builder = new TinkerPatch.Builder(tinkerApplicationLike)
.listener(new DefaultPatchListener(this))
.loadReporter(new DefaultLoadReporter(this))
.patchReporter(new DefaultPatchReporter(this))
.resultServiceClass(TinkerServerResultService.class)
.upgradePatch(new UpgradePatch())
.patchRequestCallback(new TinkerPatchRequestCallback());
//.requestLoader(new OkHttpLoader());
TinkerPatch.init(builder.build());
}
}
8、配置-SampleApplication
三、使用Tinker:
1、在Teriminal环境下执行 gradlew assembleRelease 生成基准包,我们后面需要根据此基准包生成补丁包
2、把基准包放到一个安全的位置,确保不会被clean掉(连同bakApk文件夹一同转移)
(最好自己在app根目录自己新建个文件夹单独保存此基准包,后面补丁包需要根据此基准包进行生成)
3、clean项目
4、修改def baseInfo = "app-1.1.0-0809-09-36-28" 和你生成包的基准包文件夹名称统一
5、把基准包还放回build文件夹下
6、修改代码,设置直观的更新成功的标志
7、在Teriminal环境下执行 gradlew tinkerPatchRelease 生成补丁包
(补丁包会生成两个,建议选择后面压缩后的,体积小,更容易下载;签名配置错误这里会报错,需要注意下)
8、发布补丁包(选择开发预览,可以立即执行更新,全量下发测试几次会有半小时左右延迟)
9、需要安装 -调试工具包 TinkerDebugTool.apk 和 -刚刚生成的基准包
(TinkerDebugTool.apk下载地址,也可以去官网自行下载:TinkerDebugTool.apk-Android其他资源-CSDN下载)
(调试工具包打开开发模式,这样基准包程序才能立即执行更新,下发会有半小时左右延迟)
10、启动基准包程序稍微等待几秒,如果补丁包过大,建议多等待一些时间,让程序去下载补丁包;
11、杀死基准包程序并重新启动程序,这个就会看到更新后的程序(热更新需要重启程序才会生效)
有疑问请留言交流
测试demo:TinkerDemo.zip-Android代码类资源-CSDN下载
没积分的留下邮箱,我看到会发过去的