在Google Analytics中获取崩溃报告

时间:2014-04-10 13:43:58

标签: android google-analytics

我希望收到有关崩溃报告的通知,因为我的Android应用程序的谷歌分析中未被捕获的异常。我按照https://developers.google.com/analytics/devguides/collection/android/v4/exceptions#parsing中给出的步骤进行操作 但我仍然没有收到任何崩溃报告。我的应用程序运行时出现运行时异常。我将ga_reportUncaughtException的代码添加为true:

在我的analytics.xml中。还有什么我需要添加才能在谷歌分析帐户中受到欢迎。请帮忙!

2 个答案:

答案 0 :(得分:6)

Google Analytics中存在未解决的问题。我在API 10到19的实际设备上遇到了相同的行为。

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

EDIT1 :删除了问题,只是为了回答上述问题。

EDIT2:我尝试使用Analytics ExceptionBuilder捕获并发送异常,但它无效。

看起来报告已发送(至少LogCat显示报告了崩溃),但Google不会处理它。

虽然Google回答了这个问题,但我正在使用此解决方法。我想这不是最好的解决方案,代码可以改进,但它适用于我:

  1. 我按照以下步骤https://support.google.com/analytics/answer/2709829?hl=en

  2. 在Google Analytics中创建了自定义维度
  3. 在我的应用程序中,我使用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;
            }
        }
    }
    
  4. 在OnStart()的MainActivity中,我检查共享首选项中是否存在任何存储的堆栈跟踪。如果是,我发送自定义维度并清除共享首选项。

    @Override
    protected void onStart() {
        super.onStart();
        String exception = getExceptionFromSharedPreferences(this);
        if(exception != null && !exception.isEmpty()) {
            MainApplication.googleAnalyticsTracker.sendCustomDimension(1, exception);
        } 
        clearExceptionFromSharedPreferences(this);
    }
    
  5. 最后,我在Google Analytics

  6. 中创建了自定义报告

    Custom report configuration in Google Analytics

    编辑3:

    我意识到我只发送了fileName和lineNumber,而不是我的包中的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 "";
    }
    

答案 1 :(得分:1)

根据我的经验,您需要了解有关Google Analytics中崩溃和异常的两件事:

1)仅存储基本信息 - Google Analytics只会保存异常的名称以及抛出异常的位置(代码文件和行号)。 GA上无法访问您之外的任何信息。这绝对不是理想的,如果您希望跟踪异常的实际内容(主要是调用堆栈),请使用Google Play或实施您自己的解决方案。

2)例外不是实时的。异常信息可能每天收集和更新一次,因此如果您正在尝试异常并且没有立即看到它们,那就给它时间。