一、集成Bugly熱修復
第一步:添加插件依賴
工程根目錄下“build.gradle”文件中添加:
buildscript {
repositories {
jcenter()
}
dependencies {
// tinkersupport插件,其中l(wèi)atest.release指代最新版本號,也可以指定明確的版本號,例如1.0.3
classpath "com.tencent.bugly:tinker-support:latest.release"
}
}
注意:當前我們版本需要你指定tinker插件版本為1.7.6,避免因為插件版本的變更導致補丁包的生成的問題。 自SDK 1.2.2版本起無需再配tinker插件的classpath。
第二步:集成SDK
(1)gradle配置
在app module的“build.gradle”文件中添加(示例配置):
dependencies {
compile "com.android.support:multidex:1.0.1" // 多dex配置
compile 'com.tencent.bugly:crashreport_upgrade:latest.release'//其中l(wèi)atest.release指代最新版本號,也可以指定明確的版本號,例如1.2.1
}
(2) 在app module的“build.gradle”文件中添加:
// 依賴插件腳本
apply from: 'tinker-support.gradle'
(3) 在build.gradle同級目錄下創(chuàng)建tinker-support.gradle這個文件
apply plugin: 'com.tencent.bugly.tinker-support'
def bakPath = file("${buildDir}/bakApk/")
def appName = "app-0111-15-18-41"
/**
* 對于插件各參數(shù)的詳細解析請參考
*/
tinkerSupport {
// 開啟tinker-support插件,默認值true
enable = true
// 指定歸檔目錄,默認值當前module的子目錄tinker
autoBackupApkDir = "${bakPath}"
// 是否啟用覆蓋tinkerPatch配置功能,默認值false
// 開啟后tinkerPatch配置不生效,即無需添加tinkerPatch
overrideTinkerPatchConfiguration = true
// 編譯補丁包時,必需指定基線版本的apk,默認值為空
// 如果為空,則表示不是進行補丁包的編譯
// @{link tinkerPatch.oldApk }
baseApk = "${bakPath}/${appName}/app-release.apk"
// 對應tinker插件applyMapping
baseApkProguardMapping = "${bakPath}/${appName}/app-release-mapping.txt"
// 對應tinker插件applyResourceMapping
baseApkResourceMapping = "${bakPath}/${appName}/app-release-R.txt"
// 唯一標識當前版本
tinkerId = "1.0.1-base"
// 是否開啟代理Application,設置之后無須改造Application,默認為false
enableProxyApplication = false
}
更詳細的配置項參考tinker-support配置說明
第三步:初始化SDK
(1) enableProxyApplication = false 的情況-----這是Tinker推薦的接入方式,一定程度上會增加接入成本,但具有更好的兼容性。
自定義Application
public class SampleApplication extends TinkerApplication {
public SampleApplication() {
super(ShareConstants.TINKER_ENABLE_ALL, "xxx.xxx.SampleApplicationLike",
"com.tencent.tinker.loader.TinkerLoader", false);
}
}
注意:這個類集成TinkerApplication類,這里面不做任何操作,所有Application的代碼都會放到ApplicationLike繼承類當中
參數(shù)解析
參數(shù)1:tinkerFlags 表示Tinker支持的類型 dex only、library only or all suuport,default: TINKER_ENABLE_ALL
參數(shù)2:delegateClassName Application代理類 這里填寫你自定義的ApplicationLike
參數(shù)3:loaderClassName Tinker的加載器,使用默認即可
參數(shù)4:tinkerLoadVerifyFlag 加載dex或者lib是否驗證md5,默認為false
我們需要您將以前的Applicaton配置為繼承TinkerApplication的類:

自定義ApplicationLike------appId替換成你的在Bugly平臺申請的appId
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, Resources[] resources,
ClassLoader[] classLoader, AssetManager[] assetManager) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime,
applicationStartMillisTime, tinkerResultIntent, resources, classLoader,
assetManager);
}
@Override
public void onCreate() {
super.onCreate();
// 這里實現(xiàn)SDK初始化,appId替換成你的在Bugly平臺申請的appId
Bugly.init(getApplication(), "900029763", true);
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
// you must install multiDex whatever tinker is installed!
MultiDex.install(base);
// 安裝tinker
// TinkerManager.installTinker(this); 替換成下面Bugly提供的方法
Beta.installTinker(this);
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
getApplication().registerActivityLifecycleCallbacks(callbacks);
}
}
注意:tinker需要你開啟MultiDex,你需要在dependencies中進行配置compile "com.android.support:multidex:1.0.1"才可以使用MultiDex.install方法; SampleApplicationLike這個類是Application的代理類,以前所有在Application的實現(xiàn)必須要全部拷貝到這里,在onCreate方法調(diào)用SDK的初始化方法,在onBaseContextAttached中調(diào)用Beta.installTinker(this);。
第四步:AndroidManifest.xml配置
(1) 權(quán)限配置
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
二、測試
第一步:編譯基準包
1、配置基準包的tinkerId
![W7I)VI82DMBLO1HM_5YUV]5.png](http://upload-images.jianshu.io/upload_images/2129339-98f238f704b834f7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
tinkerId最好是一個唯一標識,例如git版本號、versionName等等。 如果你要測試熱更新,你需要對基線版本進行聯(lián)網(wǎng)上報。
強調(diào):基線版本配置一個唯一的tinkerId,而這個基線版本能夠應用補丁的前提是集成過熱更新SDK,
并啟動上報過聯(lián)網(wǎng),這樣我們后臺會將這個tinkerId對應到一個目標版本,
例如tinkerId = "bugly_1.0.0" 對應了一個目標版本是1.0.0,基于這個版本打的補丁包就能匹配到目標版本。
2、執(zhí)行assembleRelease編譯生成基準包:

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

4、上傳基線包到bug平臺
應用升級---全量更新---發(fā)布新升級中上傳基準包
![JFNZH]@$X(O7W~I8C3157@R.png](http://upload-images.jianshu.io/upload_images/2129339-703a9f784479180e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
第二步:修復bug
第三步:根據(jù)基線版本生成補丁包
1、修改待修復apk路徑、mapping文件路徑、resId文件路徑
![XVKXDL]ZXL8$~6)N)7V0KJT.png](http://upload-images.jianshu.io/upload_images/2129339-cb8752a9958bb9ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2、執(zhí)行構(gòu)建補丁包的task

3、生成的補丁包在build/outputs/patch目錄下:

如果你要生成不同編譯環(huán)境的補丁包,只需要執(zhí)行Tinker插件生成的task,比如tinkerPatchRelease就能生成release編譯環(huán)境的補丁包。
補丁版本是怎么匹配到目標版本的,可以雙擊patch包,我們提供的插件會在tinker生成的patch包基礎(chǔ)上插入一個MF文件:

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

點擊發(fā)布新補丁,上傳前面生成的patch包,我們平臺會自動為你匹配到目標版本,你可以選擇下發(fā)范圍(開發(fā)設備、全量設備、自定義),填寫完備注之后,點擊立即下發(fā)讓補丁生效,這樣你就可以在客戶端當中收到我們的策略,SDK會自動幫你把補丁包下到本地。
注:我們方案是基于Tinker方案的實現(xiàn),需要下次啟動才能讓補丁生效。
over