騰訊Bugly學習瞭解
LZ-Says:新的一年,新的開始~ 越是在凌亂的時候,越要堅持住自己!!!
前言
年前的時候,就已經關注了有關熱修復,熱更新的知識,本想著專案當中多少應用一些,可現實殘酷至極~
今天,先從騰訊Bugly開刀,一起來學習瞭解騰訊的Bugly是如何操作~
當然感謝老妖的推薦~ 預祝在鵝廠實現人生巔峰~
本文目標
通過官方文件,以及親自測試,希望大家從過程中能掌握Bugly使用,一起學習~
Hi,Bugly
百度搜索:騰訊Bugly,點選進入官網:
下面引入騰訊官方對Bugly簡述:
騰訊Bugly,為移動開發者提供專業的異常上報和運營統計,幫助開發者快速發現並解決異常,同時掌握產品運營動態,及時跟進使用者反饋。
點選下方立即接入:
當然你可以點選下面的檢視Demo,簡單操作一下:
而LZ這裡選擇:立即接入,(首次需要建立一個產品,和其他三方操作一致):
依次填入相應資訊後點擊儲存:
成功之後顯示如下:
到此,我們可以看到Bugly SDK 提供我們三個使用範圍:
異常上報;
運營統計;
版本升級 (重點)
同時,也可以關注Bugly公眾號,原因嘛:
- 及時檢視每週的精彩牛文;
- 快速檢視您負責產品的資料,比如:日報、趨勢等;
- 接收異常告警,第一時間掌握產品突發狀況
下面分別對提供的三種方式進行使用以及實驗。
一、異常上報
點選“異常上報”,選擇SDK 包 2.6.6的使用指南:
我們先來看下關於異常上報平臺功能介紹:
應用整合SDK後,即可在Web站點檢視應用上報的崩潰資料和聯網資料。
異常概覽 檢視今日實時統計、崩潰趨勢、崩潰排行和TOP20崩潰問題等資訊;
崩潰分析/卡頓分析/錯誤分析 檢視上報問題的列表;
問題詳情 檢視上報問題的詳細資訊;
高階搜尋 通過各種條件快速查詢需要定位分析的異常
Bugly 提供倆種方式進行整合:
SDK 整合;
遠端依賴
相比倆種整合方案,LZ這裡選擇遠端依賴,簡單方便快捷,何樂不為?
LZ操作步驟如下:
1.1 新增遠端依賴:
// 其中latest.release指代最新Bugly SDK版本號,也可以指定明確的版本號,例如2.1 .9
compile 'com.tencent.bugly:crashreport:latest.release'
// 其中latest.release指代最新Bugly NDK版本號,也可以指定明確的版本號,例如3.0
compile 'com.tencent.bugly:nativecrashreport:latest.release'
1.2 設定NDK支援架構:
ndk {
// 設定支援的SO庫架構
abiFilters 'armeabi', 'arm64-v8a' //, 'x86', 'armeabi-v7a', 'x86_64'
}
1.3 點選Sync,同步配置。
1.4 新增許可權
<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" />
如果老帖你搞了混淆操作,為了避免混淆Bugly,在Proguard混淆檔案中增加以下配置:
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
1.5 關於初始化,Bugly提供了倆種方式:
1.5.1 簡單初始化
獲取APP ID並將以下程式碼複製到專案Application類onCreate()中,Bugly會為自動檢測環境並完成配置:
CrashReport.initCrashReport(getApplicationContext(), "註冊時申請的APPID", true);
1.5.2 AndroidManifest+程式碼配置
Bugly2.0及以上版本還支援通過“AndroidManifest.xml”來配置APP資訊。
如果同時又通過程式碼中配置了APP資訊,則最終以程式碼配置的資訊為準。
下面直接從官方地址貼出關鍵程式碼:
<application
<!-- 配置APP ID -->
<meta-data
android:name="BUGLY_APPID"
android:value="<APP_ID>" />
<!-- 配置APP版本號 -->
<meta-data
android:name="BUGLY_APP_VERSION"
android:value="<APP_Version>" />
<!-- 配置APP渠道號 -->
<meta-data
android:name="BUGLY_APP_CHANNEL"
android:value="<APP_Channel>" />
<!-- 配置Bugly除錯模式(true或者false)-->
<meta-data
android:name="BUGLY_ENABLE_DEBUG"
android:value="<isDebug>" />
</application>
設定了AndroidManifest配置引數後,則初始化需要呼叫如下:
CrashReport.initCrashReport(getApplicationContext());
1.6 需要注意
為了保證運營資料的準確性,建議不要在非同步執行緒初始化Bugly。
第三個引數為SDK除錯模式開關,除錯模式的行為特性如下:
輸出詳細的Bugly SDK的Log;
每一條Crash都會被立即上報;
自定義日誌將會在Logcat中輸出。
建議在測試階段建議設定成true,釋出時設定為false。
1.7 增加上報程序控制
這裡再次引用官方描述:
如果App使用了多程序且各個程序都會初始化Bugly(例如在Application類onCreate()中初始化Bugly),那麼每個程序下的Bugly都會進行資料上報,造成不必要的資源浪費。
因此,為了節省流量、記憶體等資源,建議初始化的時候對上報程序進行控制,只在主程序下上報資料:判斷是否是主程序(通過程序名是否為包名來判斷),並在初始化Bugly時增加一個上報程序的策略配置。
So,修改後的BaseApplication初始化方式如下:
private boolean mIsDebug = true;
@Override
public void onCreate() {
super.onCreate();
// 初始化Bugly異常上報
initBugly();
}
private void initBugly() {
Context context = getApplicationContext();
// 獲取當前包名
String packageName = context.getPackageName();
// 獲取當前程序名
String processName = getProcessName(android.os.Process.myPid());
// 設定是否為上報程序
CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(context);
strategy.setUploadProcess(processName == null || processName.equals(packageName));
// 初始化Bugly
CrashReport.initCrashReport(context, "70ecd90765", mIsDebug, strategy);
}
/**
* 獲取程序號對應的程序名
*
* @param pid 程序號
* @return 程序名
*/
private static String getProcessName(int pid) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
String processName = reader.readLine();
if (!TextUtils.isEmpty(processName)) {
processName = processName.trim();
}
return processName;
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
return null;
}
下面,我們搞一個崩潰的玩玩,看看Bugly有木有這麼神奇~
int i = 10 / 0;
執行apk,發現奔潰,接著我們檢視Bugly後臺是否接收到這個異常呢?
嗯哼,不賴~
點選進去檢視詳情,看看這究竟還會有哪兒些意外驚喜?
比某盟強忒多了~!!!人性化哈,有木有???
我們接著看,看看他還有什麼新奇的玩意???
還有?
一個字,好
二個字,很棒
三個字,忒TM6
。。。 。。。
相比某盟,Bugly這點讓人很是nice~
再搞個異常出來試試:
int[] nums = {1, 2, 3};
int num = nums[5];
再來看看結果:
很不錯~哇咔咔~~~LZ準備以後就用它了,這麼人性化,這麼棒的東西~
二、運營統計
經過上面的異常上報,LZ對運營統計這塊也是有了很大的興趣,雖說不懂運營,但是也要看看它提供的運營統計又是如何展示?
MMP,轉悠了半天,發現貌似只能顯示昨天的。。。
好尷尬~
但是,可以顯示一些基本資訊,如下:
三、版本升級 全量升級 (重點一)
哈哈,終於等到你~~~
重點來了,比較感興趣的也終於來了~
操作流程如下:
3.1 引入依賴
// 版本升級
compile 'com.tencent.bugly:crashreport_upgrade:latest.release'
自動整合時會自動包含Bugly SO庫
3.2 設定支援的SO庫架構
ndk {
// 設定支援的SO庫架構
abiFilters 'armeabi', 'arm64-v8a' //, 'x86', 'armeabi-v7a', 'x86_64'
}
3.3 配置許可權
<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" />
3.4 相容高版本
這塊可忽略,引用官方描述:
1.3.1及以上版本,可以不用進行以上配置,aar已經在AndroidManifest配置了,並且包含了對應的資原始檔。
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
在res下定義xml目錄,隨後建立:provider_paths.xml檔案。檔案裡內容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
<external-path name="beta_external_path" path="Download/"/>
<!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
<external-path name="beta_external_files_path" path="Android/data/"/>
</paths>
3.5 統一初始化方式
/**
* 初始化 Bugly
*/
private void initBugly() {
// 引數1:上下文物件
// 引數2:註冊時申請的APPID
// 引數3:是否開啟debug模式,true表示開啟debug模式,false表示關閉除錯模式
Bugly.init(getApplicationContext(), "70ecd90765", true);
}
提示:已經接入Bugly使用者改用上面的初始化方法,不影響原有的crash上報功能; init方法會自動檢測更新,不需要再手動呼叫Beta.checkUpgrade(), 如需增加自動檢查時機可以使用Beta.checkUpgrade(false,false);
引數1:isManual 使用者手動點選檢查,非使用者點選操作請傳false
引數2:isSilence 是否顯示彈窗等互動,[true:沒有彈窗和toast] [false:有彈窗或toast]
基本配置完成後,我們進入後臺管理介面進行升級策略編輯:
3.6 使用
首先,我們需要上傳更新的apk包:
上傳完成後,進行升級策略編輯(在這裡,你會深刻體會到Bugly的人性化):
下面簡單介紹下:
升級方式: 1.推薦升級(可不升級); 2.強制升級
策略下發條件:
指定源版本:可以選擇指定的版本進行升級,也可以通知所有已發版本進行升級;
升級渠道:LZ猜測應該是APK下發渠道;
網路環境:指定在某種特定網路環境下進行升級,也可以是所有環境
策略啟動條件: 1.立即啟動; 2.手動啟動; 3.定時啟動
策略停止條件:(這塊可以進行灰度測試時,隨機通知固定使用者數進行測試)
定時停止;
下發上線人數;
啟用上線人數
自動彈窗規則: 1.總彈窗次數; 2.彈窗間隔時間
最重要的便是彈框樣式,預設提供三種固定樣式,當然你也可以自定義彈框樣式!!!
編輯完成之後,如下:
啟動應用,稍等一下:
這裡充分說明的選的圖片一定要小,一定要小,一定要小!!!不然圖片位置一直顯示loading。。。
點選立即更新後,立即更新變成當前下載進度。下載完成後自動安裝:
簡單的使用,相信大家已經胸有成竹,下面進入目前階段的知識問答階段~
Issue 1: 我想飛,能帶我飛麼?
你想怎麼飛?
我想怎麼設定就怎麼設定,如下:
設定自動初始化
設定開關自動檢查
設定升級檢查週期
設定初始化延遲
設定通知欄圖示
設定更新彈窗bannner圖
設定更新資源儲存目錄
設定開啟顯示打斷策略
設定自定義UI
設定升級對話方塊生命週期回撥
小Case~瞧好吧~~~
將BaseApplication初始化Bugly替換如下方法:
private void initHeightBugly() {
/**
* true表示app啟動自動初始化升級模組;
* false不會自動初始化;
* 開發者如果擔心sdk初始化影響app啟動速度,可以設定為false,
* 在後面某個時刻手動呼叫Beta.init(getApplicationContext(),false);
*/
Beta.autoInit = true;
/**
* true表示初始化時自動檢查升級;
* false表示不會自動檢查升級,需要手動呼叫Beta.checkUpgrade()方法;
*/
Beta.autoCheckUpgrade = true;
/**
* 設定升級檢查週期為60s(預設檢查週期為0s),60s內SDK不重複向後臺請求策略);
*/
Beta.upgradeCheckPeriod = 60 * 1000;
/**
* 設定啟動延時為1s(預設延時3s),APP啟動1s後初始化SDK,避免影響APP啟動速度;
*/
Beta.initDelay = 1 * 1000;
/**
* 設定通知欄大圖示,largeIconId為專案中的圖片資源;
*/
Beta.largeIconId = R.drawable.hlq_img;
/**
* 設定狀態列小圖示,smallIconId為專案中的圖片資源Id;
*/
Beta.smallIconId = R.drawable.img;
/**
* 設定更新彈窗預設展示的banner,defaultBannerId為專案中的圖片資源Id;
* 當後臺配置的banner拉取失敗時顯示此banner,預設不設定則展示“loading“;
*/
Beta.defaultBannerId = R.drawable.timg;
/**
* 設定sd卡的Download為更新資源儲存目錄;
* 後續更新資源會儲存在此目錄,需要在manifest中新增WRITE_EXTERNAL_STORAGE許可權;
*/
Beta.storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
/**
* 點選過確認的彈窗在APP下次啟動自動檢查更新時會再次顯示;
*/
Beta.showInterruptedStrategy = true;
/**
* 只允許在MainActivity上顯示更新彈窗,其他activity上不顯示彈窗;
* 不設定會預設所有activity都可以顯示彈窗;
*/
Beta.canShowUpgradeActs.add(MainActivity.class);
/***** 統一初始化Bugly產品,包含Beta *****/
Bugly.init(this, APP_ID, true);
}
再次啟動app檢視效果:
Issue 2: 我想設定手動檢測更新,怎麼破?
一般來說,LZ建議,可以設定自動彈框次數,然後搭配手動檢測版本更新。這樣比較合理點。
那麼下面的例子,只是簡單禁用了啟動自動更新,然後配合使用者手動點選檢測更新。嗯,就是這樣~
首先,需要設定自動更新為false,也就是不自動更新:
Beta.autoCheckUpgrade = false;
接著,通過Button的點選事件,進行手動呼叫檢測更新方法:
public void getUpdateVersion(View view) {
// 手動檢測更新
Beta.checkUpgrade();
}
檢視效果:
Issue 3: 陽陽說,捎帶著來個詳情唄。
private void getUpdateVersionInfo() {
if (mBtnID == null)
return;
/***** 獲取升級資訊 *****/
UpgradeInfo upgradeInfo = Beta.getUpgradeInfo();
if (upgradeInfo == null) {
mBtnID.setText("無升級資訊");
return;
}
StringBuilder info = new StringBuilder();
info.append("id: ").append(upgradeInfo.id).append("\n");
info.append("標題: ").append(upgradeInfo.title).append("\n");
info.append("升級說明: ").append(upgradeInfo.newFeature).append("\n");
info.append("versionCode: ").append(upgradeInfo.versionCode).append("\n");
info.append("versionName: ").append(upgradeInfo.versionName).append("\n");
info.append("釋出時間: ").append(upgradeInfo.publishTime).append("\n");
info.append("安裝包Md5: ").append(upgradeInfo.apkMd5).append("\n");
info.append("安裝包下載地址: ").append(upgradeInfo.apkUrl).append("\n");
info.append("安裝包大小: ").append(upgradeInfo.fileSize).append("\n");
info.append("彈窗間隔(ms): ").append(upgradeInfo.popInterval).append("\n");
info.append("彈窗次數: ").append(upgradeInfo.popTimes).append("\n");
info.append("釋出型別(0:測試 1:正式): ").append(upgradeInfo.publishType).append("\n");
info.append("彈窗型別(1:建議 2:強制 3:手工): ").append(upgradeInfo.upgradeType);
mBtnID.setText(info);
}
檢視效果:
Issue 4: UI天馬星空,非要個性的升級框,怎麼破?
比如說,要實現下面這個效果,腫麼破呢?(PS:不能嫌棄哦~~~)
騰訊的貼心小夥伴當然為我們想到了嘍:
1. 在BaseApplication初始化的時候,設定如下:
Beta.upgradeDialogLayoutId = R.layout.upgrade_dialog;
Beta.strUpgradeDialogInstallBtn="立即更新";
Beta.strUpgradeDialogCancelBtn="";
2. 建立upgrade_dialog檔案,依據官方文件進行設定:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#8000"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/imageview"
android:layout_width="280dp"
android:layout_height="140dp"
android:scaleType="fitXY"
android:src="@drawable/update_title" />
<android.support.v7.widget.LinearLayoutCompat
android:layout_width="280dp"
android:layout_height="wrap_content"
android:background="#fff"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:padding="10dp"
android:tag="beta_title"
android:textColor="#273238"
android:textSize="18sp"
tools:text="title" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#99273238" />
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:overScrollMode="never"
android:padding="6dp"
android:scrollbars="none">
<android.support.v7.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 【必設】升級資訊控制元件tag:beta_upgrade_info-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="beta_upgrade_info"
android:text="info"
android:textColor="#757575"
android:textSize="14sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:text="@string/strUpgradeDialogFeatureLabel"
android:textColor="#273238"
android:textSize="14sp" />
<!-- 【必設】更新屬性控制元件tag:beta_upgrade_feature-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="beta_upgrade_feature"
android:text="feature"
android:textColor="#273238"
android:textSize="14sp" />
</android.support.v7.widget.LinearLayoutCompat>
</ScrollView>
<!-- 【必設】確認按鈕tag:beta_confirm_button-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff00"
android:ellipsize="end"
android:gravity="center"
android:padding="10dp"
android:tag="beta_confirm_button"
android:textColor="#273238"
android:textSize="16sp"
android:textStyle="bold" />
</android.support.v7.widget.LinearLayoutCompat>
<!-- 【必設】取消按鈕tag:beta_cancel_button-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@android:drawable/ic_menu_close_clear_cancel"
android:tag="beta_cancel_button"
android:visibility="gone" />
</LinearLayout>
然後,執行一波瞅瞅~
Issue 5: 小夥子說了,我不想用騰訊的,也不想僅僅自定義提示框,我想自己玩,怎麼破?
文末底部附上Bugly SDK下載地址以及關於自定義Activity官方連結:
嘿嘿嘿,小夥伴自己玩去吧~很是easy~
這裡簡單附上官方demo關鍵程式碼:
package com.bugly.upgrade.demo;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import com.tencent.bugly.beta.Beta;
import com.tencent.bugly.beta.download.DownloadListener;
import com.tencent.bugly.beta.download.DownloadTask;
/**
* 自定義Activity.
*/
public class UpgradeActivity extends Activity {
private TextView tv;
private TextView title;
private TextView version;
private TextView size;
private TextView time;
private TextView content;
private Button cancel;
private Button start;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_upgrade);
tv = getView(R.id.tv);
title = getView(R.id.title);
version = getView(R.id.version);
size = getView(R.id.size);
time = getView(R.id.time);
content = getView(R.id.content);
cancel = getView(R.id.cancel);
start = getView(R.id.start);
updateBtn(Beta.getStrategyTask());
tv.setText(tv.getText().toString() + Beta.getStrategyTask().getSavedLength() + "");
title.setText(title.getText().toString() + Beta.getUpgradeInfo().title);
version.setText(version.getText().toString() + Beta.getUpgradeInfo().versionName);
size.setText(size.getText().toString() + Beta.getUpgradeInfo().fileSize + "");
time.setText(time.getText().toString() + Beta.getUpgradeInfo().publishTime + "");
content.setText(Beta.getUpgradeInfo().newFeature);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DownloadTask task = Beta.startDownload();
updateBtn(task);
if (task.getStatus() == DownloadTask.DOWNLOADING) {
finish();
}
}
});
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Beta.cancelDownload();
finish();
}
});
Beta.registerDownloadListener(new DownloadListener() {
@Override
public void onReceive(DownloadTask task) {
updateBtn(task);
tv.setText(task.getSavedLength() + "");
}
@Override
public void onCompleted(DownloadTask task) {
updateBtn(task);
tv.setText(task.getSavedLength() + "");
}
@Override
public void onFailed(DownloadTask task, int code, String extMsg) {
updateBtn(task);
tv.setText("failed");
}
});
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
Beta.unregisterDownloadListener();
}
public void updateBtn(DownloadTask task) {
switch (task.getStatus()) {
case DownloadTask.INIT:
case DownloadTask.DELETED:
case DownloadTask.FAILED: {
start.setText("開始下載");
}
break;
case DownloadTask.COMPLETE: {
start.setText("安裝");
}
break;
case DownloadTask.DOWNLOADING: {
start.setText("暫停");
}
break;
case DownloadTask.PAUSED: {
start.setText("繼續下載");
}
break;
default:
break;
}
}
public <T extends View> T getView(int id) {
return (T) findViewById(id);
}
}
到此為2018年1月22日23:28:16更新。明日想著完善。雖說依舊官方文件,但是還是要熟悉下整個流程~
四、版本升級 微信Tinker 打補丁 (重點二)
小前言
首先,我們來說下很常見的一個案例:
小A在測試通過之後,釋出了1.0版本,但是在使用者實際使用過程中,突然發現由於小A在某個方面沒有考慮完善,導致使用者在某些特殊場景會發生崩潰閃退的現象。那麼,這個時候怎麼辦呢?
針對以上內容,大家想想怎麼辦呢?
有的小夥伴說了,升級啊,傻啊?但是我們不能總是升級,這樣導致使用者方案,換位思考,如果你正在用的軟體,總是在提示升級,而每次升級毫無新意,似乎壓根沒有變化,一次又一次你煩不煩。那麼最後的方式又是什麼呢?
最好的解決方案當然是,在使用者不知情的情況下,修復。
那麼,在目前情況下,提供了很多種解決方案,而今天,基於騰訊Bugly我們來學習瞭解微信Tinker使用。
為什麼使用微信Tinker?
無需關注Tinker是如何合成補丁的;
無需自己搭建補丁管理後臺;
無需考慮後臺下發補丁策略的任何事情;
無需考慮補丁下載合成的時機,處理後臺下發的策略;
我們提供了更加方便整合Tinker的方式;
我們通過HTTPS及簽名校驗等機制保障補丁下發的安全性;
豐富的下發維度控制,有效控制補丁影響範圍;
我們提供了應用升級一站式解決方案;
目前缺陷
啦啦啦,開車
第一步:工程目錄下build配置外掛
classpath "com.tencent.bugly:tinker-support:latest.release"
第二步:app目錄下建立tinker-support.gradle檔案
apply plugin: 'com.tencent.bugly.tinker-support'
// 建立一個目錄
def bakPath = file("${buildDir}/bakApk/")
/**
* 此處填寫每次構建生成的基準包目錄
* 只需要在每次打補丁包才會更改
*/
def baseApkDir = "app-01-23-00-00"
/**
* 對於外掛各引數的詳細解析請參考
*/
tinkerSupport {
// 開啟tinker-support外掛,預設值true
enable = true
// 指定歸檔目錄,預設值當前module的子目錄tinker
autoBackupApkDir = "${bakPath}"
// 是否啟用覆蓋tinkerPatch配置功能,預設值false
// 開啟後tinkerPatch配置不生效,即無需新增tinkerPatch
overrideTinkerPatchConfiguration = true
// 編譯補丁包時,必需指定基線版本的apk,預設值為空
// 如果為空,則表示不是進行補丁包的編譯
// @{link tinkerPatch.oldApk }
baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
// 對應tinker外掛applyMapping 開啟混淆會生成
baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
// 對應tinker外掛applyResourceMapping
baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
// 構建基準包和補丁包都要指定不同的tinkerId,並且必須保證唯一性
tinkerId = "base-1.0.1"
// 構建多渠道補丁時使用
// buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
// 是否啟用加固模式,預設為false.(tinker-spport 1.0.7起支援)
isProtectedApp = true
// 是否開啟反射Application模式
enableProxyApplication = true
}
/**
* 一般來說,我們無需對下面的引數做任何的修改
* 對於各引數的詳細介紹請參考:
* 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"
}
buildConfig {
keepDexApply = false
}
}
第三步:配置依賴外掛指令碼
apply from: 'tinker-support.gradle'
Sync之後,發現報如下異常:
Error:Could not get unknown property ‘apkVariantData’ for object of type com.android.build.gradle.in
A: Gradle升級到3.0以後去除了apkVariantData這個API,所以我們將3.0的Gradle改為如下:
classpath 'com.android.tools.build:gradle:2.3.3'
之後再次Sync,又報出如下異常:
Error:Cause: buildToolsVersion is not specified.
A: 給build.gradle中設定buildToolsVersion。
buildToolsVersion "26.0.2"
第四步:整合SDK
設定相應許可權:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission