熱更新-Bugly-Tinker使用詳解
Bugly熱更新是基於Tinker使用的。
為什麼使用Bugly呢,因為他目前還沒有收費。
費話不多說了,言歸正傳
使用教程,跟著步驟一步一步教你整合
gradle整合方式
1、新增依賴
compile 'com.tencent.bugly:crashreport_upgrade:1.3.3'//版本號可替換為latest.release表示最新版本
compile 'com.android.support:multidex:1.0.2'//這是谷歌官方提供的分包外掛,必須依賴
注意:Bugly的bug跟蹤功能同樣有。
2、新增Bugly外掛
在專案的gradle中新增外掛,位置如下:
classpath 'com.tencent.bugly:tinker-support:1.1.0'
3、新增tinker的gradle配置,名稱:tinker-support.gradle(名字可自定義),將下面的內容複製貼上即可,如下:
重要的東西寫在前面:下面的bakPath路徑可自定義,打正式包或者debug都會在此路徑下生成一些資訊(自己一看便知)
apply plugin: 'com.tencent.bugly.tinker-support' def bakPath = file("D:/Tinker/bakApk/")//這裡是配置的路徑 /** * 此處填寫每次構建生成的基準包目錄 */ def baseApkDir = "app-0102-10-00-23" /** * 對於外掛各引數的詳細解析請參考4、將剛剛新建的gradle配置放進主model-app中,如下:*/ tinkerSupport { // 開啟tinker-support外掛,預設值true enable = true // tinkerEnable功能開關 tinkerEnable = true // 自動生成tinkerId, 你無須關注tinkerId,預設為false autoGenerateTinkerId = true // 指定歸檔目錄,預設值當前module的子目錄tinker autoBackupApkDir = "${bakPath}" // 是否啟用覆蓋tinkerPatch配置功能,預設值false // 開啟後tinkerPatch配置不生效,即無需新增tinkerPatchoverrideTinkerPatchConfiguration = true // 編譯補丁包時,必需指定基線版本的apk,預設值為空 // 如果為空,則表示不是進行補丁包的編譯 // @{link tinkerPatch.oldApk } baseApk = "${bakPath}/${baseApkDir}/app-release.apk" // baseApk = "${bakPath}/${baseApkDir}/app-debug.apk" // 對應tinker外掛applyMapping baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt" // baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-debug-mapping.txt" // 對應tinker外掛applyResourceMapping baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt" // baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-debug-R.txt" // 構建基準包跟補丁包都要修改tinkerId,主要用於區分 tinkerId = "1.0.3.18010210-base" // 打多渠道補丁時指定目錄 // buildAllFlavorsDir = "${bakPath}/${baseApkDir}" // 是否使用加固模式,預設為false // isProtectedApp = true // 是否採用反射Application的方式整合,無須改造Application enableProxyApplication = true // 支援新增Activity supportHotplugComponent = true } /** * 一般來說,我們無需對下面的引數做任何的修改 * 對於各引數的詳細介紹請參考: * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97 */ tinkerPatch { tinkerEnable = true ignoreWarning = false useSign = false 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 = "D:/Tinker/path" } buildConfig { keepDexApply = false // tinkerId = "base-2.0.1" } }
// 依賴外掛指令碼 apply from: 'tinker-support.gradle'
5、新建一個補丁的儲存路徑,待會兒會在manifest中配置,放在model中沒試過,試過了再更新,如下:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- /storage/emulated/0/Download/com.bugly.upgrade.demo/.beta/apk--> <external-path name="beta_external_path" path="Download/"/> <!--/storage/emulated/0/Android/data/com.bugly.upgrade.demo/files/apk/--> <external-path name="beta_external_files_path" path="Android/data/"/> </paths>6、必不可少的manifest配置,如下:
<!-- Bugly升級SDK配置開始 --> <activity android:name="com.tencent.bugly.beta.ui.BetaActivity" android:theme="@android:style/Theme.Translucent" /> <provider android:name="android.support.v4.content.FileProvider" android:authorities="org.chriszou.redpackthelper.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> <!-- Bugly升級SDK配置結束-->注意:這一步需要注意fileProvider的authorities配置,規則為:包名+“.fileProvider”。包名此處可更新為唯一的標識
7、這是最後一步啦,在Application中初始化Bugly,我是自己封裝的Application,需要自己改下繼承,比如繼承Application,如下:
package org.chris.quick.b; import android.annotation.TargetApi; import android.content.Context; import android.os.StrictMode; import android.widget.Toast; import com.tencent.bugly.Bugly; import com.tencent.bugly.beta.Beta; import com.tencent.bugly.beta.interfaces.BetaPatchListener; import com.tencent.bugly.beta.upgrade.UpgradeStateListener; import org.chris.quick.m.Log; import java.util.Locale; /** * Created by zoulx on 2017/11/20. */ public class BaseTinkerApplication extends BaseApplication { private static final String TAG = "BaseTinkerApplication"; @Override public void onInit() { setStrictMode(); } @Override public void initBuggly() { // 設定是否開啟熱更新能力,預設為true Beta.enableHotfix = true; // 設定是否自動下載補丁 Beta.canAutoDownloadPatch = true; // 設定是否提示使用者重啟 Beta.canNotifyUserRestart = true; // 設定是否自動合成補丁 Beta.canAutoPatch = true; /** * 全量升級狀態回撥 */ Beta.upgradeStateListener = new UpgradeStateListener() { @Override public void onUpgradeFailed(boolean b) { } @Override public void onUpgradeSuccess(boolean b) { } @Override public void onUpgradeNoVersion(boolean b) { Toast.makeText(getApplicationContext(), "最新版本", Toast.LENGTH_SHORT).show(); } @Override public void onUpgrading(boolean b) { Toast.makeText(getApplicationContext(), "onUpgrading", Toast.LENGTH_SHORT).show(); } @Override public void onDownloadCompleted(boolean b) { } }; /** * 補丁回撥介面,可以監聽補丁接收、下載、合成的回撥 */ Beta.betaPatchListener = new BetaPatchListener() { @Override public void onPatchReceived(String patchFileUrl) { Toast.makeText(getApplicationContext(), patchFileUrl, Toast.LENGTH_SHORT).show(); } @Override public void onDownloadReceived(long savedLength, long totalLength) { Toast.makeText(getApplicationContext(), String.format(Locale.getDefault(), "%s %d%%", Beta.strNotificationDownloading, (int) (totalLength == 0 ? 0 : savedLength * 100 / totalLength)), Toast.LENGTH_SHORT).show(); } @Override public void onDownloadSuccess(String patchFilePath) { Toast.makeText(getApplicationContext(), patchFilePath, Toast.LENGTH_SHORT).show(); // Beta.applyDownloadedPatch(); } @Override public void onDownloadFailure(String msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } @Override public void onApplySuccess(String msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } @Override public void onApplyFailure(String msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } @Override public void onPatchRollback() { Toast.makeText(getApplicationContext(), "onPatchRollback", Toast.LENGTH_SHORT).show(); } }; long start = System.currentTimeMillis(); // 這裡實現SDK初始化,appId替換成你的在Bugly平臺申請的appId,除錯時將第三個引數設定為true Bugly.init(this, getBugglyAppId(), true); long end = System.currentTimeMillis(); Log.e("init time--->", end - start + "ms"); } @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); //MultiDex.install(base);//此處需要初始化分包,一定要在Bugly之前 // 安裝tinker Beta.installTinker(); } @TargetApi(9) protected void setStrictMode() { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build()); } }
注意:將自己的bugly ID填入初始化就可以了,這樣子熱更新與Bug跟蹤都能正常使用
8、最後是混淆忽略啦
# Bugly混淆規則 -dontwarn com.tencent.bugly.** -keep public class com.tencent.bugly.**{*;} # 避免影響升級功能,需要keep住support包的類 -keep class android.support.**{*;}完成以上8步那麼就將Bugly整合完畢了。
-------------------------------------------------------我是分割線----------------------------------------------------------------
整合完了,是不是要使用呢?整合So easy,但是我在使用過程中,遇到坑呀,搞死個人呢。
下面是使用步驟
1、準備有問題的包。
先打個正式包,如果是自己用其他渠道打包,可以忽略這一步,如下:
打完了之後就可以在剛才配置的路徑下檢查是否有東西喲(三個檔案),會根據當前時間生成資料夾,如下:
注意:我是打的正式包,所以是release,如果是debug包,那名稱就是debug樣子的。
2、修復有問題的包,將剛剛打的包路徑"app-0108-12-18-26",填入bugly配置gradle中,並將tinkerId改為1.0.3.18010120-patch,如下:
注意:如果是Debug方式打的包,需要修改下面的baseApk、baseApkProguardMapping、baseApkResourceMapping的檔名稱為路徑下面的debug名稱即可
baseApk = "${bakPath}/${baseApkDir}/app-release.apk" // baseApk = "${bakPath}/${baseApkDir}/app-debug.apk" // 對應tinker外掛applyMapping baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt" // baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-debug-mapping.txt" // 對應tinker外掛applyResourceMapping baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"3、上面兩步都完成了之後,就開始打補丁了。
我們之前是打的正式包,所以這裡選擇就是正式補丁,不然會報錯。如下:
4、補丁打好了,會在build資料夾輸出,如下:
4、補丁打好了,那麼就剩下最後一步了,將patch_signed_7zip.apk上傳至bugly平臺即可,去bugly平臺上傳就行了。
注意:上傳時會要求啟動基線包,意思就是把剛剛有問題的包,裝在手機上面啟動一下,一次即可,如果上傳還是提示找不到基本包,那就多啟動幾次就行啦。如果反覆試都不行,就得檢查環境是否整合成功了。重頭再檢查一下是否步驟操作完成了。
到此bugly熱更新就結束了。