1.tinker集成步驟
- 添加依賴
- 初始化
- 生成補丁
- 下發補丁
1.添加依賴
- 添加project依賴
- 添加model依賴
- 添加tinkerPatch.gradle
添加project依賴:打開項目project的gradle添加以下代碼
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
// TinkerPatch 插件,添加以下兩行代碼就行
classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.9"
classpath "com.tencent.bugly:tinker-support:1.1.5"
}
}
添加model依賴:打開model的gradle文件,如下添加依賴,只需要添加註釋標明部分即可,這裏我是固定使用的1.9.8的tinker
apply plugin: 'com.android.application'
apply from: 'tinkerpatch.gradle'//這裏是需要添加的,這裏是關聯到tinkerpatch.gradle文件,這樣我們就可以單獨在tinkerpatch.gradle配置一切tinker的內容
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.yunmayi.cashier"
minSdkVersion 19
targetSdkVersion 26
versionCode 891
versionName "1.8.4"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } }
}
buildTypes {
release {
minifyEnabled false
multiDexKeepFile file('multidex-android.txt')
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
dexOptions {
jumboMode true
}
lintOptions {
abortOnError false
}
}
repositories {
maven {
url "http://dl.bintray.com/jlmd/maven"
}
}
dependencies {
//這裏也是需要添加的,這是熱修復依賴
annotationProcessor("com.tinkerpatch.tinker:tinker-android-anno:1.9.8")
compileOnly 'com.tinkerpatch.tinker:tinker-android-anno:1.9.8'
implementation 'com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.8'
}
添加tinkerPatch.gradle:這個步驟就是創建上面gradle依賴的tinkerpatch.gradle文件
第一步:新建一個gradle文件,名字叫做tinkerpatch.gradle,創建完成之後就是這樣子了
第二步寫入tinker配置。這裏直接照抄官方的配置就可以,下面是我自己修改過的,下面圖片是我自己的配置
apply plugin: 'tinkerpatch-support'
def bakPath = file("${buildDir}/bakApk/")//這個是編譯基礎包的位置
tinkerpatchSupport {
/** 編譯時是否打開tinker(打開的話會在你的build/bakapk中多生成一個apk,同時編譯速度加長)**/
tinkerEnable = true
/** 是否使用一鍵接入功能 **/
reflectApplication = true
/** 如果用了360加固或者其他之類的加固軟件這個得打開,需要查看tinker官網是否支持你選用的加固工具 **/
protectedApp = false
/** 補丁是否支持新增 Activity (exported必須爲false)**/
supportComponent = false
autoBackupApkPath = "${bakPath}"
/** 在tinkerpatch.com得到的appKey **/
appKey = "應用的appkey"
/** 注意: 若發佈新的全量包, appVersion一定要更新 **/
appVersion = "891"//這個對應的是平臺的補丁版本,是指的新建補丁那個版本,建議和應用版本號同步
/**bakapk目錄下的apk文件
* 所謂基礎包,是你在生成補丁包時,那個拿來對比的安裝包,務必在出版本的時候保留,
**/
baseApkFile = "放置基礎包的路徑"
/**bakapk目錄下的-mapping.txt文件
* 當你的應用開啓混淆時會在bakapk和apk同一個目錄下會生成這個文件,不開啓混淆則不會生成
**/
baseProguardMappingFile = "放置混淆記錄文件的路徑"
/**bakapk目錄下的-R.txt文件
* 在bakapk和apk同一個目錄下會生成這個文件
**/
baseResourceRFile = "資源映射文件"
}
/**
* 用於用戶在代碼中判斷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
}
}
再貼出一下bakapk的目錄結構
2.初始化
直接在application中的onCreate中執行以下方法
private void initTinker() {
/*
* 我們需要確保至少對主進程跟patch進程初始化 TinkerPatch
*/
if (BuildConfig.TINKER_ENABLE) {
// 初始化TinkerPatch SDK, 更多配置可參照API章節中的,初始化SDK
TinkerPatch.init(mApplicationLike)
.setPatchResultCallback(new ResultCallBack() {
@Override
public void onPatchResult(PatchResult patchResult) {
Log.i("patch",patchResult.patchVersion);
}
})
.reflectPatchLibrary()
.fetchPatchUpdate(true)
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true);
// 每隔3個小時去訪問後臺時候有更新,通過handler實現輪訓的效果
new FetchPatchHandler().fetchPatchWithInterval(3);
}
}
FetchPatchHandler的代碼,主要就是一個定時器:
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);
}
}
這樣子,項目就配置好了tinker了,接下來是補丁生成和下發的部分。
3.生成補丁
- 生成基礎文件(apk,R.txt,maping.txt)
- 對比生成補丁
生成基礎文件:
這個步驟一般在實際項目中發生在出版本的時候,操作如下
執行完成之後會在bakapk目錄下生成一個新的文件夾,裏面包含了三個或者兩個文件,把這幾個文件放置到你tinkerpatch.gradle中配置的那個文件目錄下方,這個apk就是提供給用戶的apk
對比生成補丁,當我們發生bug之後,代碼修改後,此時需要生成補丁上去修復故障,在生成基礎文件的時候我們已經將基礎文件放置到對應目錄下了,那麼接下來直接這麼操作:
在編譯完成之後會打印出如下日誌
find the output 後面那個就是補丁包的生成路徑了,路徑下存在打好的補丁包了
4.下發補丁
這時候打開tinker官網找到自己需要發佈的應用,創建好對應版本,然後選擇文件下發就可以了,這個版本是和tinkerPatch.gradle裏面配置的版本對應的。
遇坑總結
1.tinker上傳補丁包顯示非法
這個問題首先檢查你的補丁包大小是否正確,如果正確把電腦時間同步一下,然後重新構建補丁包,如果還有問題聯繫tinker工作人員處理一下(或者升級付費版,騰訊你懂得),上次我也是碰到這個問題沒理他,過幾天就能夠正常上傳了。
2.tinker修復之後程序直接崩潰
這邊列舉一種我碰到的錯誤:在補丁下發並且合成之後,再次打開程序,直接崩潰,顯示資源未找到異常,這時候請檢查你的補丁包文件夾是否有除了.apk之外的其他文件,如果有恭喜,這個文件通過充錢可以解決,首先說下產生原因:
tinker在生成補丁的時候會把設置的部分進行一個對比,一旦發生改變就會添加到補丁包中,這個是可以配置的,例如你的資源文件發生了改變,那麼會多出一個resource.7z的資源補丁包,這時候在補丁包中指定的資源id就變了,就是R.id.xxx對應的那些R文件的資源變了,這時候你需要上傳兩個補丁一個是資源補丁,一個是代碼補丁,不然會NotFoundException,在AS3.0開啓了aapt2之後,莫名的所有資源都會檢測到修改,這個我也不知道爲啥,所以會生成一個巨大的資源補丁包,這時候官方免費的版本是不能上傳太大文件的(所以如果想修改資源,建議使用付費版)。
重點來了:但是實際中如果你不需要替換資源,又想不交錢,那麼可以指定對比的資源,只修改代碼這時候也是能夠解決問題的
配置tinkerPatch.gradle如下:
/**
* 一般來說,我們無需對下面的參數做任何的修改
* 對於各參數的詳細介紹請參考:
* 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"]
}
//修改此處,這邊是修改tinker打包資源時對比的資源選項,其中src是默認的,但是資源文件可以按照需
//要自己配置,我這邊配置只對比AndroidMefest.xml的內容,所以我配置的tinker只能修改代碼,這裏按//照自己需要配置
res {
pattern = ["AndroidManifest.xml"]
ignoreChange = ["res/*","r/*", "assets/*", "resources.arsc",]
largeModSize = 100
}
packageConfig {
}
sevenZip {
zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
// path = "/usr/local/bin/7za"
}
buildConfig {
keepDexApply = false
}
}
其次在安卓8.0之後3小時一次的輪詢據說失效,我沒測試過,大家可以試試,且又聽說在最新版本的tinker中添加了定時輪詢,沒去了解,小夥伴們可以自己試試。
撒有啦啦!!!