Decoupled Analytics

Posted by in Software

While writing my first app, I’ve decided to try some analytics services. The most obvious one is, of course, Google Analytics (well, it’s an android app after all!). Then, I found out that other services can provide analytics too, like Mixpanel. Unfortunately, most code I found online advocates adding the analytics code somewhere in the Application class (which makes testing a bit tedious).

To solve this issue, I’ve decided to decouple the analytics code from my application code and wrap it in a more limited API. The idea is that an interface (or abstract class) would define the API and I would have concrete implementations for it.

TL;DR: If you want some flexibility or just to try out analytics engines, don’t embed it in your own code. Instead create a wrapper and use it. It makes your code cleaner and is easier to test. Also, Dagger is extremely useful.

The interface

To define the API, I thought what kind of metrics I want from the app. For a first phase, I only want two metrics:

  1. Events – a ping to tell me if something happened – track users’ behaviour:

  2. Timing – a value to tell me how much time it took to perform an action – profiling:

The inspiration for this API is drawn from the GA requirements for the two types. Although initially the methods were part of an interface, the fact that we need a Context reference allowed me to create an abstract class. The abstract class resulted from this definition would be:

The implementations

For testing, I’ve created an inner class in AnalyticsProvider named VoidProvider. The code for both the abstract and inner classes is provided below.

An useful provider

The VoidProvider is useful for testing. For deployed apps, we need to implement e.g. a google analytics provider. Below, in the snippets section I’ve provided a simple implementation.

Usage

Now that we have the providers, we need a nice way to use them. Luckily, Dagger makes this a breeze:

Then, in your application class you can have something like:

Moreover, you can override the module code with something different for debug and production if you have configured your application that way (e.g. have look at U+2020).

Usage

Once the provider has been set up, you can just call it in your code like:

All you need is access to a Context variable (which is available in most places).

Code snippets

The base class and implementation

A concrete implementation

The Dagger module

HTH,


A little experiment: If you find this post and ad below useful, please check the ad out :-)