Almost everything on this group is a question, and not a discussion,
so I thought I'd do something a little different.  Here I share a
little code that I put together yesterday.

I have a general-purpose extension of the Android Application class,
where I put together useful capabilities that all of my projects tend
to share in common.

I recently added the Google Analytics for Mobile SDK jar file to my
application class.  (This could be done to an activity class as well.)
I implemented the following methods to support the tracker easily in
the rest of my app's activities.

  GoogleAnalyticsTracker tracker = null;

  public void trackApp(String identifier)
  {
    if (tracker != null) return;
    tracker = GoogleAnalyticsTracker.getInstance();
    tracker.start(identifier, this);
  }

  public void trackActivity(String activity)
  {
    if (tracker != null)
      tracker.trackPageView("/" + shortAppName() + "/" + activity);
  }

  public void trackEvent(String event, String arg1, int arg2)
  {
    if (tracker != null)
      tracker.trackEvent(shortAppName(), event, arg1, arg2);
  }

  public void dispatchTracker()
    { if (tracker != null) tracker.dispatch(); }

I just throw the Analytics JAR file in my project's lib/ folder, add
the library to the Eclipse project, and now I can call these methods
to track events and activity invocations.  Simple enough.

There is one problem with this approach, and that is now a dependence
on an import of the GoogleAnalyticsTracker class, and therefore a
dependence on the Analytics JAR file in all of the projects that use
these methods.

Since my general-purpose class may be used by some other projects that
do not need Analytics, I thought I'd make these methods detect the JAR
file at runtime, rather than require the JAR in every project.

So I use the Java "reflection" mechanisms to detect if the JAR is
available, and if so, to indirectly invoke the methods instead.  If
the JAR is not present, then I decided that calling these methods
should just do nothing.

Here are the same methods, written to make Analytics an optional
component.  Some people may complain that it adds a lot of bloat to
the projects that don't use those features, but the difference in
size is equivalent to a very small PNG drawable file.

  Object tracker = null;
  private final Method gat_trackPageView;
  private final Method gat_trackEvent;
  private final Method gat_dispatch;
  private final Method gat_stop;

  /**
   * Register the app for analytics tracking on application startup.
   * @param activity the Google Analytics "web property ID" for app
   */
  public void trackApp(String identifier)
  {
    if (tracker != null) return;
    try
    {
      String classname =
        "com.google.android.apps.analytics.GoogleAnalyticsTracker";
      Class<?> gat = Class.forName(classname);
      Class<?>[] argTypes = null;
      Method tracker_getInstance = gat.getMethod("getInstance",
                                                 argTypes);
      Object[] args = null;
      tracker = tracker_getInstance.invoke(null, args);
      argTypes = new Class<?>[] { String.class, Context.class };
      Method tracker_start = gat.getMethod("start", argTypes);
      args = new Object[] { identifier, this };
      tracker_start.invoke(tracker, args);
      //
      argTypes = new Class<?>[] { String.class };
      gat_trackPageView = gat.getMethod("trackPageView", argTypes);
      argTypes = new Class<?>[] { String.class, String.class,
                                  String.class, Integer.TYPE };
      gat_trackEvent = gat.getMethod("trackEvent", argTypes);
      argTypes = null;
      gat_dispatch = gat.getMethod("dispatch", argTypes);
      gat_stop = gat.getMethod("stop", argTypes);
    }
    catch (Exception e)
    {
      // ignored if the GoogleAnalyticsTracker jar is not found
      Log.w(shortAppName() +
            "GoogleAnalyticsTracker not available. No tracking.");
      tracker = null;
    }
  }

  /**
   * Track the user's use of a given activity (or any string).
   * @param activity the name of the activity to be logged
   */
  public void trackActivity(String activity)
  {
    if (tracker == null) return;
    final Object[] args = { null };
    String page = "/" + shortAppName() + "/" + activity;
    args[0] = page;
    try { gat_trackPageView.invoke(args); }
    catch (Exception e) { ; }
  }

  /**
   * Track an event that occurs in the application.
   * @param event the name of the event
   * @param arg1 an arbitrary string to be categorized
   * @param arg2 an arbitrary integer to be summed
   */
  public void trackEvent(String event, String arg1, int arg2)
  {
    if (tracker == null) return;
    final Object[] args = { null, null, null, null };
    args[0] = shortAppName();
    args[1] = event; args[2] = arg1; args[3] = new Integer(arg2);
    try { gat_trackEvent.invoke(tracker, args); }
    catch (Exception e) { ; }
  }

  /**
   * Post all pending tracking messages as network is available.
   */
  public void dispatchTracker()
  {
    if (tracker == null) return;
    try { gat_dispatch.invoke(tracker, (Object[])null); }
    catch (Exception e) { ; }
  }

  /**
   * End the tracking of the application on app shutdown.
   */
  public void stopTracker()
  {
    if (tracker == null) return;
    try { gat_stop.invoke(tracker, (Object[])null); }
    catch (Exception e) { ; }
    tracker = null;
  }

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to