1. 程式人生 > >Android線上收集崩潰資訊

Android線上收集崩潰資訊

為什麼要線上收集崩潰資訊?

我們的app上線後後有可能會出現測試階段沒有出現的bug導致崩潰,我們不能及時獲取到崩潰的日誌及時修復,這時就需要在應用崩潰的時候把崩潰的日誌上傳到伺服器以便我們對崩潰的情況進行分析,當然這裡說的是Java 的 UnChecked Exception,Native的 Exception這裡不進行考慮。

怎樣收集發生異常時的資訊

當應用崩潰時,預設會呼叫Thread類中設定的一個UncaughtExceptionHandler中的uncaughtException方法,所以我們只要實現一個UncaughtExceptionHandler物件,在其對應方法中實現對崩潰資訊的儲存或者上傳即可。

具體的設定過程

  1. 一般我們會監控UI執行緒的崩潰資訊,所以需要在Application的onCreate()中將我們實現的UncaughtExceptionHandler物件設定進去
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(Thread.getDefaultUncaughtExceptionHandler()));

UnhandledExceptionHandler即為我們實現的可以自定義捕獲異常的類,具體實現如下:

 public class CrashHandler {

     public
static class UnhandledExceptionHandler implements Thread.UncaughtExceptionHandler { private Thread.UncaughtExceptionHandler uncaughtExceptionHandler; public CrashHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) { this.uncaughtExceptionHandler = uncaughtExceptionHandler; } @Override
public void uncaughtException(Thread thread, Throwable ex) { try { //收集崩潰資訊 getStackTraceInfo(ex); }finally { //走Android預設的崩潰處理邏輯 uncaughtExceptionHandler.uncaughtException(thread, ex); } } } /** * 收集異常資訊 * @param throwable */ private static void getStackTraceInfo(Throwable throwable) { }

我們看到在CrashHandler的構造方法中傳回了Thread.getDefaultUncaughtExceptionHandler(),這是為了在我們處理完異常資訊後系統可以正常的執行崩潰的邏輯。在未捕獲的異常發生時,我們就可以在getStackTraceInfo() 中獲取崩潰的資訊,進行儲存或者上傳。在此處還可以使用以下多種方式獲取當前裝置的多種資訊以便分析:

  • 裝置資訊
使用PackageManager獲取PackageInfo,記錄版本名稱和版本號。 
 使用android.os.Build.class.getDeclaredFields()獲取裝置資訊。
  • 記憶體資訊
使用ActivityManager獲取ActivityManager.MemoryInfo。 
 ActivityManager.getMemoryClass():在當前裝置中,應用可使用最大記憶體,單位MB。
 ActivityManager.getLargeMemoryClass():在manifest中設定android:largeHeap=”true”時,應用可使用最大記憶體,單位MB。
 MemoryInfo.availMem:系統剩餘記憶體
 MemoryInfo.lowMemory:系統是否處於低記憶體執行
 MemoryInfo.threshold:當系統剩餘記憶體低於該值時處於低記憶體執行 
  • 狀態
 MemoryInfo.totalMem:系統總記憶體
 使用android.os.Debug.MemoryInfo獲取程序的記憶體統計資料,以KB為單位。
 android.os.Debug.dumpHprofData():轉儲dump檔案到手機,可使用MAT分析崩潰時應用記憶體狀況。
 Debug.getNativeHeapAllocatedSize():native堆已分配記憶體,位元組為單位。
 Debug.getNativeHeapFreeSize():native堆空閒記憶體,位元組為單位。
 Debug.getNativeHeapSize():native堆總記憶體大小,位元組為單位。
 Debug.MemoryInfo.dalvikPrivateDirty:The private dirty pages used by dalvik.
Debug.MemoryInfo.dalvikPss:The proportional set size for dalvik.
 Debug.MemoryInfo.dalvikSharedDirty:The shared dirty pages used by dalvik.
 Debug.MemoryInfo.nativePrivateDirty:The private dirty pages used by the native heap.
 Debug.MemoryInfo.nativePss:The proportional set size for the native heap.
Debug.MemoryInfo.nativeSharedDirty:The shared dirty pages used by the native heap.
 Debug.MemoryInfo.otherPrivateDirty:The private dirty pages used by everything else.
 Debug.MemoryInfo.otherPss:The proportional set size for everything else.
 Debug.MemoryInfo.otherSharedDirty:The shared dirty pages used by everything else.
 使用Runtime.getRuntime()獲取虛擬機器記憶體資訊,位元組為單位。 
 Runtime.getRuntime().maxMemory():虛擬機器可以使用最大記憶體
 Runtime.getRuntime().freeMemory():執行程式可使用空閒記憶體
 Runtime.getRuntime().totalMemory():執行程式可使用總記憶體大小,當這個值接近maxMemory()時可以發生記憶體溢位。
  • Activity棧
 ActivityManager.getRunningTasks(1)可獲得當前執行任務。 
 RunningTaskInfo對應執行任務。 
 RunningTaskInfo.id:任務id
 RunningTaskInfo.description:任務描述
 RunningTaskInfo.numActivities:Activity數量
 RunningTaskInfo.baseActivity:棧底Activity
 RunningTaskInfo.topActivity:棧頂Activity

更便利的方法

如果我們的應用接入了友盟或者bugly等,可以直接使用這些庫實現崩潰資訊的上傳,可以在其網頁上直觀的檢視