1.導(dǎo)入依賴及插件



2.配置插件腳本?? tinker-support.gradle
applyplugin:'com.tencent.bugly.tinker-support'
def bakPath = file("${buildDir}/bakApk/")
def baseApkDir ="app-0825-11-40-17"
tinkerSupport {
? ? enable =true??// 開啟tinker-support插件,默認(rèn)值true
? autoBackupApkDir ="${bakPath}"??? // 指定歸檔目錄,默認(rèn)值當(dāng)前module的子目錄tinker
? ? //建議設(shè)置true,用戶就不用再自己管理tinkerId的命名,插件會為每一次構(gòu)建的base包自動生成唯一的tinkerId
? ? autoGenerateTinkerId =true
? ? //tinkerId必須保證唯一性,如果兩個base包的tinkerid是一樣的,并且都聯(lián)網(wǎng)激活了,那么后續(xù)補(bǔ)丁上傳到后臺的時候會出現(xiàn)匹配錯誤
? ? tinkerId ="if autoGenerateTinkerId=true ,no need set here"
? ? // 是否啟用覆蓋tinkerPatch配置功能,默認(rèn)值false
// 開啟后tinkerPatch配置不生效,即無需添加tinkerPatch
? ? overrideTinkerPatchConfiguration =true
? ? // 編譯補(bǔ)丁包時,必需指定基線版本的apk,默認(rèn)值為空
// 如果為空,則表示不是進(jìn)行補(bǔ)丁包的編譯
// @{link tinkerPatch.oldApk }
? ? baseApk ="${bakPath}/${baseApkDir}/app-release.apk"
? ? // 對應(yīng)tinker插件applyMapping
? ? baseApkProguardMapping ="${bakPath}/${baseApkDir}/app-release-mapping.txt"
? ? // 對應(yīng)tinker插件applyResourceMapping
? ? baseApkResourceMapping ="${bakPath}/${baseApkDir}/app-release-R.txt"
//? ? buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
// 是否開啟加固模式,默認(rèn)為false
? ? isProtectedApp =true
? ? enableProxyApplication =false
? ? supportHotplugComponent =true
}
/**
* 一般來說,我們無需對下面的參數(shù)做任何的修改
*/
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" //? 可選,設(shè)置mapping文件,建議保持舊apk的proguard混淆方式
//applyResourceMapping = "${bakPath}/${appName}/app-debug-R.txt" // 可選,設(shè)置R.txt文件,通過舊apk文件保持ResId的分配
? ? }
}
3.配置AndroidMainfirst
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


4.配置Application
public class SampleApplicationextends TinkerApplication {
public SampleApplication() {
super(ShareConstants.TINKER_ENABLE_ALL, "com.xx.xxx.SampleApplicationLike",
? ? ? ? ? ? ? "com.tencent.tinker.loader.TinkerLoader", false);
? ? }}
SampleApplicationLike?是Application的代理類,以前所有在Application的實(shí)現(xiàn)必須要全部拷貝到這里
public class SampleApplicationLike extends DefaultApplicationLike {
public static final StringTAG ="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();
? ? ? ? Beta.enableHotfix =true;? // 設(shè)置是否開啟熱更新能力,默認(rèn)為true
? ? ? ? Beta.canAutoDownloadPatch =true;? // 設(shè)置是否自動下載補(bǔ)丁,默認(rèn)為true
? ? ? ? Beta.canAutoPatch =true;? // 設(shè)置是否自動合成補(bǔ)丁,默認(rèn)為true
? ? ? ? Beta.canNotifyUserRestart =true;// 設(shè)置是否提示用戶重啟,默認(rèn)為false
// 補(bǔ)丁回調(diào)接口
? ? ? ? Beta.betaPatchListener =new BetaPatchListener() {
@Override
? ? ? ? ? ? public void onPatchReceived(String patchFile) {
Toast.makeText(getApplication(), "補(bǔ)丁下載地址" + patchFile, Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
@Override
? ? ? ? ? ? public void onDownloadReceived(long savedLength, long totalLength) {
Toast.makeText(getApplication(),
? ? ? ? ? ? ? ? ? ? ? ? String.format(Locale.getDefault(), "%s %d%%",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Beta.strNotificationDownloading,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (int) (totalLength ==0 ?0 : savedLength *100 / totalLength)),
? ? ? ? ? ? ? ? ? ? ? ? Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
@Override
? ? ? ? ? ? public void onDownloadSuccess(String msg) {
Toast.makeText(getApplication(), "補(bǔ)丁下載成功", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
@Override
? ? ? ? ? ? public void onDownloadFailure(String msg) {
Toast.makeText(getApplication(), "補(bǔ)丁下載失敗", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
@Override
? ? ? ? ? ? public void onApplySuccess(String msg) {
Toast.makeText(getApplication(), "補(bǔ)丁應(yīng)用成功", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
@Override
? ? ? ? ? ? public void onApplyFailure(String msg) {
Toast.makeText(getApplication(), "補(bǔ)丁應(yīng)用失敗", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
@Override
? ? ? ? ? ? public void onPatchRollback() {
}
};
? ? ? ? // 設(shè)置開發(fā)設(shè)備,默認(rèn)為false,上傳補(bǔ)丁如果下發(fā)范圍指定為“開發(fā)設(shè)備”,需要調(diào)用此接口來標(biāo)識開發(fā)設(shè)備
? ? ? ? Bugly.setIsDevelopmentDevice(getApplication(), true);
? ? ? ? // 多渠道需求塞入
// String channel = WalleChannelReader.getChannel(getApplication());
// Bugly.setAppChannel(getApplication(), channel);
// 這里實(shí)現(xiàn)SDK初始化,appId替換成你的在Bugly平臺申請的appId
? ? ? ? Bugly.init(getApplication(), "d9e0ae879b", 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);
? ? ? ? // TODO: 安裝tinker
? ? ? ? Beta.installTinker(this);
? ? }
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void registerActivityLifecycleCallback(
Application.ActivityLifecycleCallbacks callbacks) {
getApplication().registerActivityLifecycleCallbacks(callbacks);
? ? }
@Override
? ? public void onTerminate() {
super.onTerminate();
? ? ? ? Beta.unInit();
? ? }
}
MainActivity中添加
override fun onBackPressed() {
super.onBackPressed()
Log.e("MainActivity", "onBackPressed")
Beta.unInit()
}
5.打包及生成補(bǔ)丁
1.打包(未發(fā)現(xiàn)bug?補(bǔ)丁生成之前):

2.修復(fù)bug 生成補(bǔ)丁

生成的補(bǔ)丁包在build/outputs/patch目錄下:

6.上傳補(bǔ)丁及修復(fù)



打開應(yīng)用后程序關(guān)閉后臺后再次啟動時自動顯示:(補(bǔ)丁剛上傳之后需等待10分左右會有結(jié)果)
