2014-04-10 57 views
9

我想在我的Android應用的谷歌分析中收到由於未捕獲的異常導致的崩潰報告的通知。我遵循https://developers.google.com/analytics/devguides/collection/android/v4/exceptions#parsing 中給出的步驟,但仍然沒有收到任何崩潰報告。當我的應用運行時,我有一個運行時異常。我說是真正的ga_reportUncaughtException代碼:在谷歌分析中獲取崩潰報告

真正

在我analytics.xml。還有什麼我需要添加,以便在谷歌分析帳戶中擊中。請幫忙!

+0

我有同樣的問題。你找到解決方案嗎? – Shmuel

+0

@David我沒有得到任何解決方案。所以我用V3 – Anu

+0

我不知道這是否會幫助你,但我發現我錯誤地做了這個 - ga_reportUncaughtException一個字符串,當它應該是一個布爾<布爾名稱=「ga_reportUncaughtExceptions」>真 – Shmuel

回答

1

從我的經驗,你需要了解的崩潰和異常的谷歌Analytics(分析)兩件事情:

1)只有基本信息存儲 - 谷歌Analytics(分析)將只保存異常的名稱和位置(代碼文件,行號)拋出異常的地方。 GA以外的任何信息都無法獲取。這絕對不是理想之選,如果您希望追蹤例外(主要是調用堆棧)的實際內容,請使用Google Play或實施您自己的解決方案。

2)例外情況不是實時的。例外信息每天可能會收集並更新一次,因此如果您正在嘗試使用例外情況並且沒有立即看到它們,只需花點時間。

+0

這不是這裏討論的問題。我們知道只存儲基本信息,並且這些異常不是實時的。問題在於他們甚至在幾天之後根本沒有被記錄。 – Shmuel

6

Analytics(分析)中存在一個未解決的問題。我遇到相同的行爲,但是從API 10真正的設備19

https://code.google.com/p/analytics-issues/issues/detail?id=443

EDIT1:刪除問題,剛纔回答中描述的問題。

EDIT2:我試圖使用Analytics ExceptionBuilder捕獲和發送異常,但它不起作用。

它看起來像報告發送(至少LogCat顯示報告崩潰),但它不處理分析。

雖然Google回覆了這個問題,但我正在使用此解決方法。我想這是不是最好的解決方案,該代碼可以改進,但它爲我工作:

  1. 我創建了Analytics(分析)的自定義維度下面這個步驟https://support.google.com/analytics/answer/2709829?hl=en

  2. 在我的應用程序,我創建自定義異常處理程序,使用Analytics ExceptionReporter類。當一個異常被捕獲時,我得到堆棧跟蹤並將其截斷爲150字節(實際上,我只得到堆棧的第一行並將其截斷爲150個字符,我假設1Char = 1字節)。我必須截斷它,因爲這是Google Analytics在發送自定義維度值時允許的最大長度。 堆棧跟蹤存儲在共享首選項中,而不是發送。我試圖直接發送它,但一旦應用程序崩潰就無法工作。

    package com.company.package; 
    
    import java.lang.Thread.UncaughtExceptionHandler; 
    
    import android.content.Context; 
    
    import com.google.android.gms.analytics.ExceptionParser; 
    import com.google.android.gms.analytics.ExceptionReporter; 
    import com.google.android.gms.analytics.GoogleAnalytics; 
    import com.google.android.gms.analytics.HitBuilders; 
    import com.google.android.gms.analytics.Tracker; 
    
    public class GoogleAnalyticsTracker { 
    
        private static Tracker mTracker; 
        private static GoogleAnalytics mGa; 
        private Context mContext; 
    
        public GoogleAnalyticsTracker(Context context, int resource) { 
         mContext = context; 
         mGa = GoogleAnalytics.getInstance(context); 
         mTracker = getTracker(resource); 
    
         Thread.setDefaultUncaughtExceptionHandler(new AnalyticsExceptionReporter(mTracker, 
          Thread.getDefaultUncaughtExceptionHandler(), context)); 
        } 
    
        synchronized Tracker getTracker(int xmlResource) { 
         return mGa.newTracker(xmlResource); 
        } 
    
        public void sendScreenLabel(String screenLabel) { 
         mTracker.setScreenName(screenLabel); 
         mTracker.send(new HitBuilders.AppViewBuilder().build()); 
        } 
    
        public void sendCustomDimension(int index, String value) { 
         mTracker.send(new HitBuilders.AppViewBuilder().setCustomDimension(index, value).build()); 
        } 
    
        private class AnalyticsExceptionReporter extends ExceptionReporter { 
    
         public AnalyticsExceptionReporter(Tracker tracker, UncaughtExceptionHandler originalHandler, Context context) { 
          super(tracker, originalHandler, context); 
          setExceptionParser(new AnalyticsExceptionParser()); 
         } 
    
         @Override 
         public void uncaughtException(Thread t, Throwable e) { 
         String exceptionDescription = getExceptionParser().getDescription(t.getName(), e); 
    
          //Add code to store the exception stack trace in shared preferences 
    
          super.uncaughtException(t, e); 
         } 
        } 
    
        private class AnalyticsExceptionParser implements ExceptionParser { 
    
         @Override 
         public String getDescription(String arg0, Throwable arg1) { 
          StringBuilder exceptionFirsLine = new StringBuilder(); 
          for (StackTraceElement element : arg1.getStackTrace()) { 
           exceptionFirsLine.append(element.toString()); 
           break; 
          } 
    
          //150 Bytes is the maximum allowed by Analytics for custom dimensions values. Assumed that 1 Byte = 1 Character (UTF-8) 
          String exceptionDescription = exceptionFirsLine.toString(); 
          if(exceptionDescription.length() > 150) 
           exceptionDescription = exceptionDescription.substring(0, 149); 
    
          return exceptionDescription; 
         } 
        } 
    } 
    
  3. 在MainActivity時的OnStart(),我檢查是否有在共享偏好的任何存儲的堆棧跟蹤。如果是這樣,我發送自定義維度並清除共享首選項。

    @Override 
    protected void onStart() { 
        super.onStart(); 
        String exception = getExceptionFromSharedPreferences(this); 
        if(exception != null && !exception.isEmpty()) { 
         MainApplication.googleAnalyticsTracker.sendCustomDimension(1, exception); 
        } 
        clearExceptionFromSharedPreferences(this); 
    } 
    
  4. 最後,我在分析

創建一個自定義報告

Custom report configuration in Google Analytics

編輯3:

我意識到,我只發送文件名和行號,但不是我的包中的ExceptionName和Exception的來源。我通過添加代碼來發送該信息,從而改進了答案。

private class AnalyticsExceptionParser implements ExceptionParser { 

    @Override 
    public String getDescription(String arg0, Throwable arg1) { 
     String exceptionDescription = getExceptionInfo(arg1, "", true) + getCauseExceptionInfo(arg1.getCause()); 

     //150 Bytes is the maximum allowed by Analytics for custom dimensions values. Assumed that 1 Byte = 1 Character (UTF-8) 
     if(exceptionDescription.length() > 150) 
      exceptionDescription = exceptionDescription.substring(0, 150); 

     return exceptionDescription; 
    } 
} 
//#endregion 

//#region PRIVATE METHODS 
private String getCauseExceptionInfo(Throwable t) { 
    String causeDescription = ""; 
    while(t != null && causeDescription.isEmpty()) { 
     causeDescription = getExceptionInfo(t, "com.myPackageName", false); 
     t = t.getCause(); 
    } 
    return causeDescription; 
} 

private String getExceptionInfo(Throwable t, String packageName, boolean includeExceptionName) { 
    String exceptionName = ""; 
    String fileName = ""; 
    String lineNumber = ""; 

    for (StackTraceElement element : t.getStackTrace()) { 
     String className = element.getClassName().toString().toLowerCase(); 
     if(packageName.isEmpty() || (!packageName.isEmpty() && className.contains(packageName))){ 
      exceptionName = includeExceptionName ? t.toString() : ""; 
      fileName = element.getFileName(); 
      lineNumber = String.valueOf(element.getLineNumber()); 
      return exceptionName + "@" + fileName + ":" + lineNumber; 
     } 
    } 
    return ""; 
} 
+0

感謝這個答案,它真的幫助了我。是的,它確實回答了這個問題。 – ol0