Google Analytics in Android App - Multiple Actions

I was very pleased to see how easy it is to configure Google Analytics with my application, but the lack of documentation I have with a few questions. The only information I can find is directly from the documentation here , which only considers the presentation of PageViews and Events from a single action. I want to report page views and events in several actions in my application.

Right now in onCreate () of all my actions I call:

tracker = GoogleAnalyticsTracker.getInstance(); tracker.start("UA-xxxxxxxxx", this); 

And in onDestroy () of all my actions:

  tracker.stop(); 

Then I track the pages and events as needed and send them along with another HTTP request that I am executing. But I'm not sure if this is the best way. Should I run start () and stop () in every action, or do I only need to call start () and stop () in my main start activity?

+45
android google-analytics
Jul 09 '10 at 21:30
source share
7 answers

The problem with calling start () / stop () in every action (as suggested by Christian) is that it leads to a new “visit” for every action that your user leads to. If this is suitable for your use, then that’s fine, however, it’s not like most people expect visits to work. For example, it makes it very difficult to compare Android numbers with numbers on the Internet or iphone, since a “visit” on the Internet and iphone is associated with a session, not a page / activity.

The problem with calling start () / stop () in your application is that it leads to unexpectedly long visits, since Android makes no guarantees to terminate the application after closing the last action. Also, if your application does nothing with notifications or services, these background tasks can launch your application and lead to phantom visits. UPDATE: stefano correctly indicates that onTerminate () is never called on a real device, so there is no obvious place to stop calling ().

The problem with calling start () / stop () in one “main” action (as suggested by Aurora) is that there is no guarantee that the activity will remain active for the entire time that your user uses for your application. If the “core” activity is destroyed (say, to free up memory), your subsequent attempts to write events to GA in other actions will fail because the session is stopped.

In addition, there is a bug in Google Analytics, at least with version 1.2, which forces it to maintain a strong link to the context that you pass in order to start (), preventing it from receiving garbage collected after its destruction. Depending on the size of your context, this could be a significant memory leak.

A memory leak is simple enough to fix, it can be solved by calling start () using the application, and not the activity instance itself. docs should probably be updated to reflect this.

eg. from within your business:

 // Start the tracker in manual dispatch mode... tracker.start("UA-YOUR-ACCOUNT-HERE", getApplication() ); 

instead

 // Start the tracker in manual dispatch mode... tracker.start("UA-YOUR-ACCOUNT-HERE", this ); // BAD 

Regarding when you need to call start () / stop (), you can implement some kind of reference counting manually by increasing the counter for each call to Activity.onCreate () and decreasing onDestroy () for each of them, and then calling GoogleAnalyticsTracker.stop ( ) when the counter reaches zero.

Google’s new EasyTracker library will take care of this for you.

Alternatively, if you cannot subclass EasyTracker actions, you can manually implement this yourself in your base activity class:

 public abstract class GoogleAnalyticsActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Need to do this for every activity that uses google analytics GoogleAnalyticsSessionManager.getInstance(getApplication()).incrementActivityCount(); } @Override protected void onResume() { super.onResume(); // Example of how to track a pageview event GoogleAnalyticsTracker.getInstance().trackPageView(getClass().getSimpleName()); } @Override protected void onDestroy() { super.onDestroy(); // Purge analytics so they don't hold references to this activity GoogleAnalyticsTracker.getInstance().dispatch(); // Need to do this for every activity that uses google analytics GoogleAnalyticsSessionManager.getInstance().decrementActivityCount(); } } public class GoogleAnalyticsSessionManager { protected static GoogleAnalyticsSessionManager INSTANCE; protected int activityCount = 0; protected Integer dispatchIntervalSecs; protected String apiKey; protected Context context; /** * NOTE: you should use your Application context, not your Activity context, in order to avoid memory leaks. */ protected GoogleAnalyticsSessionManager( String apiKey, Application context ) { this.apiKey = apiKey; this.context = context; } /** * NOTE: you should use your Application context, not your Activity context, in order to avoid memory leaks. */ protected GoogleAnalyticsSessionManager( String apiKey, int dispatchIntervalSecs, Application context ) { this.apiKey = apiKey; this.dispatchIntervalSecs = dispatchIntervalSecs; this.context = context; } /** * This should be called once in onCreate() for each of your activities that use GoogleAnalytics. * These methods are not synchronized and don't generally need to be, so if you want to do anything * unusual you should synchronize them yourself. */ public void incrementActivityCount() { if( activityCount==0 ) if( dispatchIntervalSecs==null ) GoogleAnalyticsTracker.getInstance().start(apiKey,context); else GoogleAnalyticsTracker.getInstance().start(apiKey,dispatchIntervalSecs,context); ++activityCount; } /** * This should be called once in onDestrkg() for each of your activities that use GoogleAnalytics. * These methods are not synchronized and don't generally need to be, so if you want to do anything * unusual you should synchronize them yourself. */ public void decrementActivityCount() { activityCount = Math.max(activityCount-1, 0); if( activityCount==0 ) GoogleAnalyticsTracker.getInstance().stop(); } /** * Get or create an instance of GoogleAnalyticsSessionManager */ public static GoogleAnalyticsSessionManager getInstance( Application application ) { if( INSTANCE == null ) INSTANCE = new GoogleAnalyticsSessionManager( ... ,application); return INSTANCE; } /** * Only call this if you're sure an instance has been previously created using #getInstance(Application) */ public static GoogleAnalyticsSessionManager getInstance() { return INSTANCE; } } 
+78
Jun 06 2018-11-11T00:
source share

The SDK now has an external library that takes care of all this. It is called EasyTracker. You can simply import it and expand the provided activity or ListActivity, create a string resource with your code, and you're done.

+17
Jan 02 '12 at 23:24
source share

The tracker will track only those actions that it performed. So, why don't you subclass Activity that run it every time on onCreate :

 public class GAnalyticsActivity extends Activity{ public void onCreate(Bundle icicle){ super.onCreate(icile); tracker = GoogleAnalyticsTracker.getInstance(); tracker.start("UA-xxxxxxxxx", this); } // same for on destroy } 

Then you extend this class for each action you use:

 public class YourActivity extends GAnalyticsActivity{ public void onCreate(Bundle icicle){ super.onCreate(icile); // whatever you do here you can be sure // that the tracker has already been started } } 
+5
Jul 09 '10 at 21:39
source share

The approach I use is to use the Bound Service (I happen to have used it already, so the creation of additional boiler plate code was saved.)

A Bound Service will only work as long as there are activities associated with it. All actions in my application are tied to this service, so it lasts only as long as the user actively uses my application - therefore a very real session.

I run the tracker with an instance of the Singleton application, which I expanded, and added the static getInstance () method to retrieve the instance:

 // Non-relevant code removed public IBinder onBind(Intent intent) { tracker = GoogleAnalyticsTracker.getInstance(); tracker.startNewSession(PROPERTY_ID, MyApp.getInstance()); } public boolean onUnbind(Intent intent) { tracker.stopSession(); } 

See: http://developer.android.com/guide/topics/fundamentals/bound-services.html

+1
Sep 14 '11 at 18:56
source share

I spent different time between visits in my application, working like this:

I created a Singleer Tracker object for the shell for GoogleAnalyticsTracker, where I keep the last time something is tracked. If this time is more than x seconds, I consider it as a new visit.

Of course, this is only useful if you keep track of everything in your application, and perhaps not the best solution in any situation, works well for my application.

It only supports TrackPageView, but setCustomVar and trackEvent should be easy to implement.

Anywhere you need to track something, just add the line:

  Tracker.getInstance(getApplicationContext()).trackPageView("/HelloPage"); 

I usually do this in onResume activity

Tracking

+1
Sep 27 '11 at 0:20
source share

You will need something like this: http://mufumbo.wordpress.com/2011/06/13/google-analytics-lags-on-android-how-to-make-it-responsive/

This is in the previous version and was used to work very well. Now I am in the same struggle as you, since V2 does not seem very consistent.

+1
Mar 08 '13 at 11:52
source share

I wonder if this can be done using AOP.

Android can only use AOP methods to compile, so maybe something like AspectJ?

There's a bit more info on using AspectJ in Android in this thread . The main problem is that you still need to declare your classes.

0
Aug 16 '12 at 1:21
source share



All Articles