如何让Google Analytics v4报告我的应用未捕获的异常(崩溃)?

时间:2014-08-17 17:18:55

标签: android google-analytics

我一直在这个墙上撞墙几个小时。 Google Analytics的v4 docs指定了两种不同的方式让您的应用报告未捕获的异常。我无法工作。在这两种情况下,当我在我的应用程序中触发未捕获的异常(我自己的代码使用虚拟名称)时,我在LogCat中看到这样的行:

08-17 17:33:30.248: V/GAV4(8968): Thread[main,5,main]: Tracking Exception: MyException (@MyClass:myMethod:143) {main}
08-17 17:33:30.248: V/GAV4(8968): Thread[main,5,main]: Dispatch call queued. Dispatch will run once initialization is complete.
08-17 17:33:30.248: V/GAV4(8968): Thread[main,5,main]: Passing exception to original handler.

...然后是我的异常的堆栈跟踪,最后是:

08-17 17:33:44.282: I/Process(8968): Sending signal. PID: 8968 SIG: 9

从LogCat看,GA​​似乎从未真正将异常发送给Google的服务器!

如果有人设法在他们的Google Analytics控制台中报告未被捕获的异常,那么如果他们能够与我们分享他们是如何做到这一点的话,那就太棒了。我已经在其他人看到过这样的问题(例如,herehere),但没有确认报告未捕获的异常。

我在GA控制台中显示了屏幕视图,所以我必须做正确的事情。但不是未被捕获的例外。我假设一个人应该在行为>下寻找他们。崩溃和例外,我已将结束日期设置为今天(默认情况下似乎设置为昨天)。最后,在我的analytics_global_config.xml中,我有:

<integer name="ga_dispatchPeriod">1</integer>

因为否则默认值为1800秒,在这种情况下,我假设在GA控制台发生后至少30分钟内无法看到异常。 ga_dryRun也是假的。

3 个答案:

答案 0 :(得分:7)

正如@xitx所指出的那样,在人们设备上安装的Google Play服务库的更高版本中看起来像there's a bug。因为当我在模拟器上为相对较旧的设备(API 9,并且可能运行旧的Google Play服务库)运行现有代码时,崩溃确实会自动报告给GA的控制台。这是崩溃发生时LogCat所说的内容:

08-31 12:27:59.522: V/GAV4(335): Thread[GAThread,5,main]: Sending hit to store  PATH: https:  PARAMS: ul=en-us,  ht=1409484468454,  sr=480x800,  a=746864705,  sf=100.0,  aid=com.redula.vsavings,  cid=32da19a1-7e15-4c83-aaa9-f3f1d502b775,  av=1.2,  v=1,  t=exception,  an=Savings Organiser,  tid=UA-XXXXXXXX,  exd=NullPointerException (@HomeActivity:connectToInAppBillingService:202) {main},  _u=.2nKKhAAAL,  exf=1,  
08-31 12:27:59.622: V/GAV4(335): Thread[GAThread,5,main]: PowerSaveMode initiated.
08-31 12:27:59.652: V/GAV4(335): Thread[GAThread,5,main]: PowerSaveMode terminated.
08-31 12:27:59.652: V/GAV4(335): Thread[GAThread,5,main]: Dispatch running...
08-31 12:27:59.702: V/GAV4(335): Thread[GAThread,5,main]: User-Agent: GoogleAnalytics/3.0 (Linux; U; Android 2.3.1; en-us; sdk Build/GSI11)
08-31 12:27:59.702: V/GAV4(335): Host: ssl.google-analytics.com
08-31 12:27:59.702: V/GAV4(335): GET /collect?ul=en-us&ht=1409484468454&sr=480x800&a=746864705&sf=100.0&aid=com.redula.vsavings&cid=32da19a1-7e15-4c83-aaa9-f3f1d502b775&av=1.2&v=1&t=exception&an=Savings+Organiser&tid=UA-XXXXXXX&exd=NullPointerException+%28%40HomeActivity%3AconnectToInAppBillingService%3A202%29+%7Bmain%7D&_u=.2nKKhAAAL&_v=ma4.0.2&exf=1&qt=11249&z=2 HTTP/1.1
08-31 12:28:00.482: V/GAV4(335): Thread[GAThread,5,main]: sent 1 of 1 hits
08-31 12:28:00.492: V/GAV4(335): Thread[GAThread,5,main]: PowerSaveMode initiated.
08-31 12:32:48.562: I/Process(335): Sending signal. PID: 335 SIG: 9

这就是GA控制台在一分钟内发生的崩溃:

enter image description here

我知道你只能获得堆栈跟踪的第一行,但现在这对我有用。其他各种各样的人都有自己的方法来获取整个堆栈跟踪(例如,参见@ xitx&#39; s评论和here)。

因此,我计划使用现有代码并等待Google将修补程序发送到更高版本的Google Play服务中。一旦他们的修复程序发布,我的应用程序应该按原样运行。

为了记录,我在我的跟踪器的XML文件(res / xml / app_tracker_config.xml)中使用它:

<bool name="ga_reportUncaughtExceptions">true</bool>

我的getTracker()实现:

public class MyApp extends Application {

 private static Tracker tracker = null;

 synchronized Tracker getTracker() {
    if (tracker == null) {
        GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);
        analytics.enableAutoActivityReports(this);
        tracker = analytics.newTracker(R.xml.app_tracker_config);
        tracker.enableAdvertisingIdCollection(true);
    }
    return tracker;
 }
}

然后在onCreate()中为我的主屏幕活动我这样做以初始化GA:

((MyApp) getApplication()).getTracker();

编辑(额外信息):全局配置文件,res / xml / analytics_global_config.xml:

<?xml version="1.0" encoding="utf-8"?>
  <resources>
    <string name="ga_logLevel">verbose</string>
    <integer name="ga_dispatchPeriod">1</integer>
    <bool name="ga_dryRun">false</bool>
</resources>

我的应用程序的清单引用application元素的子标记中的此文件:

    <meta-data
        android:name="com.google.android.gms.analytics.globalConfigResource"
        android:resource="@xml/analytics_global_config" />

答案 1 :(得分:1)

只需在清单

中添加此内容即可
<meta-data 
    android:name="com.google.android.gms.analytics.globalConfigResource"              
    android:resource="@xml/tracker.xml" />

之后你应该开始接收这个logcat:

V/GAV4﹕ Thread[main,5,main]: Tracking Exception: ArithmeticException (@MyActivity:onResume:111) {main}
V/GAV4﹕ Thread[main,5,main]: Dispatch call queued. Dispatch will run once initialization is complete.
V/GAV4﹕ Thread[main,5,main]: Passing exception to original handler.

重新启动应用程序后:

V/GAV4﹕ Thread[client_id_fetcher,5,main]: Loaded client id from disk.
V/GAV4﹕ Thread[main,5,main]: Loading Tracker config values.
V/GAV4﹕ Thread[main,5,main]: [Tracker] trackingId loaded: UA-XXXXXXXX-X
V/GAV4﹕ Thread[main,5,main]: [Tracker] session timeout loaded: 300000
V/GAV4﹕ Thread[main,5,main]: ExceptionReporter created, original handler is com.android.internal.os.RuntimeInit$UncaughtHandler
V/GAV4﹕ Thread[main,5,main]: Uncaught exceptions will be reported to Google Analytics.
V/GAV4﹕ Thread[GAThread,5,main]: connecting to Analytics service
V/GAV4﹕ Thread[main,5,main]: service connected, binder: android.os.BinderProxy@42175d30
V/GAV4﹕ Thread[main,5,main]: bound to service
V/GAV4﹕ Thread[GAThread,5,main]: connect: bindService returned true for Intent { act=com.google.android.gms.analytics.service.START cmp=com.google.android.gms/.analytics.service.AnalyticsService (has extras) }
V/GAV4﹕ Thread[main,5,main]: Connected to service
I/GAV4﹕ Thread[GAThread,5,main]: No campaign data found.
V/GAV4﹕ Thread[GAThread,5,main]: Initialized GA Thread
V/GAV4﹕ Thread[GAThread,5,main]: Loaded clientId
V/GAV4﹕ Thread[GAThread,5,main]: Loaded clientId
V/GAV4﹕ Thread[GAThread,5,main]: putHit called
V/GAV4﹕ Thread[GAThread,5,main]: Sending hit to service   PATH: https:  PARAMS: ul=en-us,  ht=1408554996959,  sr=720x1184,  a=194292074,  aid=<app package>,  cid=9639b81c-b17a-4c3a-a43e-0c1f43a6d5c1,  av=1.5.0.1,  v=1,  t=exception,  an=<app name>,  tid=UA-XXXXXXXX-X,  exd=SQLiteBindOrColumnIndexOutOfRangeException (@MyApp:onCreate:185) {main},  _u=.nKhAAAL,  exf=0

目前在我的项目中,我正在使用此代码(在Application.onCreate()方法中),它的工作正常:

GoogleAnalytics googleAnalytics = GoogleAnalytics.getInstance(this);
applicationPreferences = new ApplicationPreferences(getApplicationContext());
tracker = googleAnalytics.newTracker(R.xml.tracker);
tracker.enableExceptionReporting(true);
String lastErrorString = applicationPreferences.getLastErrorString();
if (lastErrorString != null) {
    applicationPreferences.clearLastErrorString();
    tracker.send(new HitBuilders.ExceptionBuilder().setDescription(lastErrorString).setFatal(true).build());
}
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        applicationPreferences.setLastErrorString(Throwables.getStackTraceAsString(throwable));
        defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
    }
});

注意:Throwables是来自guava的类

没有番石榴的变异但没有完整的堆栈跟踪,只有原始行号和方法包含在报告中:

GoogleAnalytics googleAnalytics = GoogleAnalytics.getInstance(this);
applicationPreferences = new ApplicationPreferences(getApplicationContext());
tracker = googleAnalytics.newTracker(R.xml.tracker);
tracker.enableExceptionReporting(true);
String lastErrorString = applicationPreferences.getLastErrorString();
if (lastErrorString != null) {
    applicationPreferences.clearLastErrorString();
    tracker.send(new HitBuilders.ExceptionBuilder().setDescription(lastErrorString).setFatal(true).build());
}
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        applicationPreferences.setLastErrorString(
            new StandardExceptionParser(getApplicationContext(), null).getDescription(thread.getName(), throwable)
        );
        defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
    }
});

答案 2 :(得分:0)

对于offtopic很抱歉,但是从那个问题开始,我转而使用Crashlytics进行错误收集,它比GA更有效。