Skip to content

Instantly share code, notes, and snippets.

@jaredsburrows
Created May 19, 2016 01:23
Show Gist options
  • Save jaredsburrows/6e8eee5ef323f5eddbf8d1b90142198c to your computer and use it in GitHub Desktop.
Save jaredsburrows/6e8eee5ef323f5eddbf8d1b90142198c to your computer and use it in GitHub Desktop.
Google Analytics and Crash Reporting
import android.util.Log;
import com.google.android.gms.analytics.ExceptionParser;
/**
* Custom Analytics Class to display enough debug information in the console.
*
* @author <a href="mailto:jaredsburrows@gmail.com">Jared Burrows</a>
*/
public final class AnalyticsExceptionParser implements ExceptionParser {
// Normal ExceptionParser
/*
V/GAV4 (23004): Thread[GAThread,5,main]: Loaded clientId
W/GAV4 ( 1642): Thread[Thread-1762,5,main]: Using destination https://ssl.google-analytics.com
V/GAV4 (23004): Thread[GAThread,5,main]: putHit called
V/GAV4 (23004): Thread[GAThread,5,main]: Sending hit to service PATH: https: PARAMS: ul=en-us,
ht=1423949563177, sr=720x1280, a=837980596, aid=burrows.apps.appsharer,
cid=bbe25b2c-f781-4766-a0dd-d308d38d51a3, av=1.29-DEBUG, v=1, t=exception, an=App Sharer, tid=UA-41971904-8,
exd=NullPointerException (@MainActivity:onAppAdapterCheckedChanged:111) {main}, _u=.hAAAL, exf=1,
cd=AppSharer - MainActivity,
W/GAV4 ( 1642): Thread[Thread-1762,5,main]: Using destination https://ssl.google-analytics.com
*/
// AnalyticsExceptionParser - watch for the "exd"
/*
V/GAV4 ( 3760): Thread[main,5,main]: Passing exception to original handler.
V/GAV4 ( 3760): Thread[GAThread,5,main]: Loaded clientId
V/GAV4 ( 3760): Thread[main,5,main]: Tracking Exception: IllegalArgumentException
(@MainActivity:onAppAdapterCheckedChanged:103) {main}
V/GAV4 ( 3760): Thread[main,5,main]: Dispatch call queued. Dispatch will run once initialization is complete.
V/GAV4 ( 3760): Thread[main,5,main]: Passing exception to original handler.
V/GAV4 ( 3760): Thread[GAThread,5,main]: putHit called
V/GAV4 ( 3760): Thread[GAThread,5,main]: Sending hit to service PATH: https: PARAMS: ul=en-us,
ht=1423956914953, sr=720x1280, a=131376609, aid=burrows.apps.appsharer,
cid=bbe25b2c-f781-4766-a0dd-d308d38d51a3, av=1.29-DEBUG, v=1, t=exception, an=App Sharer,
tid=UA-41971904-8, exd=java.lang.IllegalArgumentException
V/GAV4 ( 3760): at burrows.apps.appsharer.ui.activity.MainActivity
.onAppAdapterCheckedChanged(MainActivity.java:103)
V/GAV4 ( 3760): at burrows.apps.appsharer.ui.adapter.AppAdapter$1.onClick(AppAdapter.java:67)
V/GAV4 ( 3760): at android.view.View.performClick(View.java:4654)
V/GAV4 ( 3760): at android.view.View$PerformClick.run(View.java:19438)
V/GAV4 ( 3760): at android.os.Handler.handleCallback(Handler.java:733)
V/GAV4 ( 3760): at android.os.Handler.dispatchMessage(Handler.java:95)
V/GAV4 ( 3760): at android.os.Looper.loop(Looper.java:146)
V/GAV4 ( 3760): at android.app.ActivityThread.main(ActivityThread.java:5487)
V/GAV4 ( 3760): at java.lang.reflect.Method.invokeNative(Native Method)
V/GAV4 ( 3760): at java.lang.reflect.Method.invoke(Method.java:515)
V/GAV4 ( 3760): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
V/GAV4 ( 3760): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
V/GAV4 ( 3760): at dalvik.system.NativeStart.main(Native Method)
V/GAV4 ( 3760): , _u=.r3hAAAL, exf=1, cd=AppSharer - MainActivity,
V/GAV4 ( 3760): Thread[GAThread,5,main]: Loaded clientId
V/GAV4 ( 3760): Thread[GAThread,5,main]: putHit called
V/GAV4 ( 3760): Thread[GAThread,5,main]: Sending hit to service PATH: https: PARAMS: ul=en-us,
ht=1423956914955, sr=720x1280, a=131376609, aid=burrows.apps.appsharer,
cid=bbe25b2c-f781-4766-a0dd-d308d38d51a3, av=1.29-DEBUG, v=1, t=exception, an=App Sharer,
tid=UA-41971904-8, exd=IllegalArgumentException (@MainActivity:onAppAdapterCheckedChanged:103) {main},
_u=.rhAAAL, exf=1, cd=AppSharer - MainActivity,
W/GAV4 ( 1642): Thread[Thread-1862,5,main]: Using destination https://ssl.google-analytics.com
W/GAV4 ( 1642): Thread[Thread-1862,5,main]: Using destination https://ssl.google-analytics.com
*/
@Override
public String getDescription(final String s, final Throwable throwable) {
return Log.getStackTraceString(throwable);
}
}
import burrows.apps.lib.base.BaseLibApplication;
import com.google.android.gms.analytics.ExceptionReporter;
/**
* @author <a href="mailto:jaredsburrows@gmail.com">Jared Burrows</a>
*/
public class AnalyticsLibApplication extends BaseLibApplication {
@Override
public void onCreate() {
super.onCreate();
// Setup Google Analytics
AnalyticsManager.init(this.getApplicationContext());
// Setup the Uncaught Exception Handler in order to catch all exceptions
final ExceptionReporter reporter = new ExceptionReporter(AnalyticsManager.getTracker(),
Thread.getDefaultUncaughtExceptionHandler(),
this);
reporter.setExceptionParser(new AnalyticsExceptionParser());
Thread.setDefaultUncaughtExceptionHandler(reporter);
}
}
import android.content.Context;
import burrows.apps.lib.base.R;
import burrows.apps.lib.base.util.LogUtils;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
/**
* https://developers.google.com/analytics/devguides/collection/android/v4/advanced?hl=es
* https://github.com/google/iosched/blob/0a90bf8e6b90e9226f8c15b34eb7b1e4bf6d632e/android/src/main/java/com/google/samples/apps/iosched/util/java
* https://github.com/google/iosched/blob/cf1f30b4c752f275518384a9b71404ee501fc473/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java
*
* @author <a href="mailto:jaredsburrows@gmail.com">Jared Burrows</a>
*/
public final class AnalyticsManager {
private static final String TAG = AnalyticsManager.class.getSimpleName();
private static final int DISPATCH_TIME_SECONDS = 300;
private static Context context;
private static Tracker tracker;
private AnalyticsManager() {
}
public static synchronized void init(final Context applicationContext) {
AnalyticsManager.context = applicationContext;
if (tracker == null && context != null) {
final GoogleAnalytics googleAnalytics = GoogleAnalytics.getInstance(context);
// Make sure we are not in "testing" mode
googleAnalytics.setDryRun(false);
// Dispatch every 5 minutes
googleAnalytics.setLocalDispatchPeriod(DISPATCH_TIME_SECONDS);
tracker = googleAnalytics.newTracker(context.getString(R.string.app_analytics));
// Provide unhandled exceptions reports. Do that first after creating the tracker
tracker.enableExceptionReporting(true);
// Enable Remarketing, Demographics & Interests reports
tracker.enableAdvertisingIdCollection(true);
// Enable automatic activity tracking for your app
tracker.enableAutoActivityTracking(true);
}
}
public static synchronized Tracker getTracker() {
return tracker;
}
public static synchronized void setTracker(final Tracker tracker) {
AnalyticsManager.tracker = tracker;
}
public static boolean sendScreenView(final String screenName) {
if (canSend()) {
tracker.setScreenName(screenName);
tracker.send(new HitBuilders.ScreenViewBuilder().build());
LogUtils.logI(TAG, "Screen View recorded: " + screenName);
return true;
} else {
LogUtils.logI(TAG, "Screen View NOT recorded (analytics disabled or not ready).");
return false;
}
}
public static boolean sendException(final String description, final boolean fatal) {
if (canSend()) {
tracker.send(new HitBuilders.ExceptionBuilder()
.setDescription(description)
.setFatal(fatal)
.build());
return true;
} else {
LogUtils.logI(TAG, "Analytics event ignored (analytics disabled or not ready).");
return false;
}
}
public static boolean sendEvent(final String category, final String action, final String label) {
return sendEvent(category, action, label, 0);
}
public static boolean sendEvent(final String category, final String action, final String label,
final long value) {
if (canSend()) {
tracker.send(new HitBuilders.EventBuilder()
.setCategory(category)
.setAction(action)
.setLabel(label)
.setValue(value)
.build());
LogUtils.logI(TAG, "Event recorded:");
LogUtils.logI(TAG, "Category: " + category);
LogUtils.logI(TAG, "Action: " + action);
LogUtils.logI(TAG, "Label: " + label);
LogUtils.logI(TAG, "Value: " + value);
return true;
} else {
LogUtils.logI(TAG, "Analytics event ignored (analytics disabled or not ready).");
return false;
}
}
private static boolean canSend() {
return context != null && tracker != null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment