1. 程式人生 > >一個很好用的BUG收集工具------Bugly

一個很好用的BUG收集工具------Bugly

在專案上線以後,使用者開始使用時候,總是會遇到各種各樣的bug,特別是crash,所以我們就需要收集這些bug,然後去逐步的修改,盤查問題所在,保障在以後的版本里不會出現相同的問題。大部分人的做法是抓取到APP的Crash資訊,然後儲存到本地,在一個特定的條件下,將統計到的資訊傳送給伺服器。這也是解決辦法的一種方式,但是這個分析的過程就需要我們自己做了,這個過程裡就會發現會產出很多重複的錯誤程式碼,然後還要一遍遍去看,這樣會浪費很多時間。所以這就需要藉助一下第三方的工具,當然市面上有很多這種型別的工具,但是經過對比之後我覺得下面我要給大家講的第三方的bug收集工具---Bugly 是裡面最好用的(個人意見),它裡面還內嵌了微信的熱修復框架tinker,可以在你發現致命bug的時候能夠無需重新發版讓使用者無感知就能把問題修復。(防止了被祭天的危險)。

下面我就給大家介紹一下bugly的使用,後面會介紹整合tinker。

第一步:新增依賴

在Module的build.gradle檔案中新增依賴和屬性配置:

dependencies {
    compile 'com.tencent.bugly:crashreport:latest.release' //其中latest.release指代最新Bugly SDK版本號,也可以指定明確的版本號,例如2.2.0
}

同時整合SDK和NDK

在Module的build.gradle檔案中新增依賴和屬性配置:

android {
    defaultConfig {
        ndk {
            // 設定支援的SO庫架構
abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a' } } } dependencies { compile 'com.tencent.bugly:crashreport:latest.release' //其中latest.release指代最新Bugly SDK版本號,也可以指定明確的版本號,例如2.1.9 compile 'com.tencent.bugly:nativecrashreport:latest.release' //其中latest.release指代最新Bugly NDK版本號,也可以指定明確的版本號,例如3.0
}

同時整合Bugly SDK和NDK的配置如下圖所示,後續更新Bugly SDK和NDK時,只需變更配置指令碼中的版本號即可。

Alt text


注意:自動整合時會自動包含Bugly SO庫,建議在Module的build.gradle檔案中使用NDK的“abiFilter”配置,設定支援的SO庫架構。

如果在新增“abiFilter”之後Android Studio出現以下提示:

NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin.

則在專案根目錄的gradle.properties檔案中新增:

android.useDeprecatedNdk=true

引數配置

  • 在AndroidManifest.xml中新增許可權:
<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.**{*;}

最簡單的初始化

獲取APP ID並將以下程式碼複製到專案Application類onCreate()中,Bugly會為自動檢測環境並完成配置:

CrashReport.initCrashReport(getApplicationContext(), "註冊時申請的APPID", false); 

為了保證運營資料的準確性,建議不要在非同步執行緒初始化Bugly。

第三個引數為SDK除錯模式開關,除錯模式的行為特性如下:

  • 輸出詳細的Bugly SDK的Log;
  • 每一條Crash都會被立即上報;
  • 自定義日誌將會在Logcat中輸出。

建議在測試階段建議設定成true,釋出時設定為false。

Alt text

此外,Bugly2.0及以上版本還支援通過“AndroidManifest.xml”來配置APP資訊。如果同時又通過程式碼中配置了APP資訊,則最終以程式碼配置的資訊為準。

在“AndroidManifest.xml”的“Application”中增加“meta-data”配置項:

<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>

不同於“android:versionName”,“BUGLY_APP_VERSION”配置的是Bugly平臺的APP版本號。

通過“AndroidManifest.xml”配置後的初始化方法如下:

CrashReport.initCrashReport(getApplicationContext());

Bugly預設從“AndroidManifest.xml”檔案中讀取“VersionName”作為版本號,自定義設定請使用參考“高階設定”。

MultiDex注意事項

如果使用了MultiDex,建議通過Gradle的“multiDexKeepFile”配置等方式把Bugly的類放到主Dex,另外建議在Application類的"attachBaseContext"方法中主動載入非主dex:

public class MyApplication extends SomeOtherApplication {
  @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(context);
     Multidex.install(this);
  }
}

增加上報程序控制

如果App使用了多程序且各個程序都會初始化Bugly(例如在Application類onCreate()中初始化Bugly),那麼每個程序下的Bugly都會進行資料上報,造成不必要的資源浪費。

因此,為了節省流量、記憶體等資源,建議初始化的時候對上報程序進行控制,只在主程序下上報資料:判斷是否是主程序(通過程序名是否為包名來判斷),並在初始化Bugly時增加一個上報程序的策略配置。

Context context = getApplicationContext();
// 獲取當前包名
String packageName = context.getPackageName();
// 獲取當前程序名
String processName = getProcessName(android.os.Process.myPid());
// 設定是否為上報程序
UserStrategy strategy = new UserStrategy(context);
strategy.setUploadProcess(processName == null || processName.equals(packageName));
// 初始化Bugly
CrashReport.initCrashReport(context, "註冊時申請的APPID", isDebug, strategy);
// 如果通過“AndroidManifest.xml”來配置APP資訊,初始化方法如下
// CrashReport.initCrashReport(context, strategy);

其中獲取程序名的方法“getProcessName”有多種實現方法,推薦方法如下:

/**
 * 獲取程序號對應的程序名
 * 
 * @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;
}

測試

現在您可以製造一個Crash(建議通過“按鍵”來觸發),來體驗Bugly的能力了。在初始化Bugly的之後,呼叫Bugly測Java Crash介面。

CrashReport.testJavaCrash();

執行到這段程式碼時會發生一個Crash,Logcat的TAG=CrashReportInfo中輸出為:

Alt text

現在您已經可以在“崩潰”頁面看到剛才觸發的Crash issue了(延遲一般在10s以內)。

如果專案包含了Native工程或者使用了程式碼混淆,建議配置符號表檔案,具體請參考“符號表配置

經過上面的步驟的話 我們就完成了bugly收集bugly的功能,下面第二篇的話 我會給大家介紹一下tinker熱修復的整合過程