項目中之前已經(jīng)接入bugly的異常收集和全量更新SDK,為了應對bug及時修復以及一些改動不太大的需求,準備接入Tinker。而Bugly已經(jīng)對Tinker做了很好的支持,不用從頭到尾接一遍。
Bugly 集成就包含了上報,升級,熱修復三合一。
思考
遇到的問題
1、基準包打出來后必須要進行聯(lián)網(wǎng)上報,意思就是說要在有網(wǎng)絡的手機上啟動一次,Bugly才能上報TinkerId,基于這個版本生成的補丁包就可以匹配到它
2、兩次傳入的tinkerId是否一樣?
不一樣的,編譯補丁包時,tinker會自動讀取基準包AndroidManifest的tinkerId作為package_meta.txt中的TINKER_ID。將本次編譯傳入的tinkerId,作為package_meta.txt的NEW_TINKER_ID。
你必須要上傳build/outputs/patch目錄下的補丁包,
每次發(fā)版都要保留基準包、混淆配置文件、資源Id文件?
當然啦,你不保存基準包,我們打補丁怎么知道要基于哪個版本打補丁?所以建議大家每次發(fā)版注意保存基準apk包,還有對應編譯生成的mapping文件和R.txt文件。
Q:完整的測試流程是怎樣的?
打基準包安裝并上報聯(lián)網(wǎng)(注:填寫唯一的tinkerId)
對基準包的bug修復(可以是Java代碼變更,資源的變更)
修改基準包路徑、修改補丁包tinkerId、mapping文件路徑(如果開啟了混淆需要配置)、resId文件路徑
執(zhí)行buildTinkerPatchRelease打Release版本補丁包
選擇app/build/outputs/patch目錄下的補丁包并上傳(注:不要選擇tinkerPatch目錄下的補丁包,不然上傳會有問題)
編輯下發(fā)補丁規(guī)則,點擊立即下發(fā)
殺死進程并重啟基準包,請求補丁策略(SDK會自動下載補丁并合成)
再次重啟基準包,檢驗補丁應用結果
查看頁面,查看激活數(shù)據(jù)的變化
為什么我的補丁包上傳匹配到的不是我的基準包版本?
原因:你之前測試時使用過和當前基準包版本一樣的tinkerid,bugly補丁下發(fā)是按照tinkerid下發(fā)。 多個基準包使用了同一個tinkerid那說明這幾個基準包都能收到你當前上傳的補丁。
對Tinker的理解
、首先,你需要了解 TinkerId ,相信很多人看他官方的文檔后都知道這個東西,
1、他需要在生成基準包(你要正式往線上發(fā)布的版本)的時候設置tinkerID
2、在打補丁的時候還需要再次設置tinkerID,而且這次的tinker和第一步的id不能相同
很多人對此是很不理解的?原來,你在第一步生成基準包的時候,tinker插件會自動將tinkerID和App當前的版本Version對應起來。例如,你當前的app版本是2.3.1.30,tinkerID設置為2.3.1.30-base,那么這個2.3.1.30和2.3.1.30-base就會對應起來,tinker插件會自動在打包的時候插入到Mainfest.xml文件中。
好了,下面你的2.3.1.30版本app發(fā)現(xiàn)問題,你需要打一個補丁包進行修復,這時候你需要再次設置tinkerID為2.3.1.30-patch-03。tinker插件會自動把基準包的的tinkerID和本次補丁包的tinkerID保存在插件中。此時,當你將這個補丁上傳至bugly平臺,
你的補丁id為2.3.1.30-patch-03 —> 基準包id 2.3.1.30-base ---> 你出現(xiàn)問題的App版本2.3.1.30

一、添加插件依賴,在根目錄的build.gradle中:
classpath "com.tencent.bugly:tinker-support:1.1.1"
二、集成SDK:
app module的build.gradle中添加多dex配置、 添加bugly dependencies
//Tinker
compile "com.android.support:multidex:1.0.3" // 多dex配置
//注釋掉原有bugly的倉庫
//compile 'com.tencent.bugly:crashreport:latest.release'//其中l(wèi)atest.release指代最新版本號,也可以指定明確的版本號,例如1.3.4
compile 'com.tencent.bugly:crashreport_upgrade:1.3.6'
// 指定tinker依賴版本(注:應用升級1.3.5版本起,不再內置tinker)
compile 'com.tencent.tinker:tinker-android-lib:1.9.9'
compile 'com.tencent.bugly:nativecrashreport:3.6.0'
//其中l(wèi)atest.release指代最新版本號,也可以指定明確的版本號,例如2.2.0
app module的build.gradle中添加依賴插件腳本:
// 依賴插件腳本
apply from: 'tinker-support.gradle'
三、初始化SDK:
Tinker 初始化分為兩種情況 本文采用不用改造Application的情況,
據(jù)官方描述,改造Application的初始化方式兼容性會比不改改Application 要好
官方初始化參考
取 enableProxyApplication = true的情況
在自己的Application里面添加如下代碼,別忘記在配置文件配置Application
public void onCreate() {
super.onCreate();
if (sInstance == null) {
sInstance = this;
}
// 這里實現(xiàn)SDK初始化,appId替換成你的在Bugly平臺申請的appId
// 調試時,將第三個參數(shù)改為true
Bugly.init(this, "c45d2fc4ba", true);
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// you must install multiDex whatever tinker is installed!
MultiDex.install(base);
// 安裝tinker
Beta.installTinker();
}
到此為止 Tinker的接入已經(jīng)全部完成,接下來看他是如何使用的,
1、編譯基準包
配置基準包的tinkerId

tinkerId最好是一個唯一標識,例如git版本號、versionName等等。 如果你要測試熱更新,你需要對基線版本進行聯(lián)網(wǎng)上報。
這里強調一下,基線版本配置一個唯一的tinkerId,而這個基線版本能夠應用補丁的前提是集成過熱更新SDK,并啟動上報過聯(lián)網(wǎng),這樣我們后臺會將這個tinkerId對應到一個目標版本,例如tinkerId = "bugly_1.0.0" 對應了一個目標版本是1.0.0,基于這個版本打的補丁包就能匹配到目標版本。
執(zhí)行assembleRelease編譯生成基準包:

這個會在build/outputs/bakApk路徑下生成每次編譯的基準包、混淆配置文件、資源Id文件,如下圖所示:

實際應用中,請注意保存線上發(fā)布版本的基準apk包、mapping文件、R.txt文件,如果線上版本有bug,就可以借助我們tinker-support插件進行補丁包的生成。
啟動apk,上報聯(lián)網(wǎng)數(shù)據(jù)
我們每次冷啟動都會請求補丁策略,會上報當前版本號和tinkerId,這樣我們后臺就能將這個唯一的tinkerId對應到一個版本,大家測試的時候可以打開logcat查看我們的日志,如下圖所示:


打開LogCat 如果看到這兩條日志 ,表示聯(lián)網(wǎng)上報成功了。
如果看不到log,您需要將bugly初始化的第三個參數(shù)設置為true才能看到。
2、對基線版本的bug修復
1、首先是要對有bug的代碼進行修復
2、修改配置,修改點全是基于開始打基準包出來的結果。要保持一致
填寫生成基準線的目錄


3、執(zhí)行構建補丁包的task


大家這里可能會有一個疑問,補丁版本是怎么匹配到目標版本的,可以雙擊patch包,提供的插件會在tinker生成的patch包基礎上插入一個MF文件:


4、上傳補丁包到平臺
上傳補丁包到平臺并下發(fā)編輯規(guī)則

5、測試補丁應用效果
啟動app應用patch
如果匹配到目標版本,后臺就會下發(fā)補丁策略,可以在logcat看到如下日志:



下載成功之后,會立即去合成補丁,可以看到patch合成的日志:

再次重啟app查看效果 發(fā)現(xiàn)Bug 已經(jīng)修復(第一次啟動時加載合成補丁,再次啟動就是使用)
注意上傳補丁后 立刻去啟動app,有時候沒有下載,我猜想可能有延時,具體原因不知。
試著第三次啟動看看吧,這時候會顯示日志,已經(jīng)下載
