Replay.io Android Client Library

The Android client library is open-source, so view the code on Github!

Quickstart for Busy Devs

Four easy steps to go from zero to analytics hero:

Step 1 - Get

If you’ve got a working Gradle build, simply put compile io.replay:replay-android:+ in your Dependencies section and everything should “just work”™. If your setup is more complicated, check out the Installation portion of the Documentation section.

Step 2 - Permit & Configure

Add permissions to the Android Manifest and set your API key in /res/values.

Part A

In your AndroidManifest.xml, add the following lines (if they don’t already exist):

<!-- Required for internet. -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<!-- Optional -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

Part B

Add the configuration XML to your application’s /res/values folder. The xml file can have any name:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--replay api key - REQUIRED -->
    <string name="api_key">API_KEY_HERE</string>
</resources>

Note 1: This XML can also further configure the behavior of the Android client. Check out the documentation for more information.

Note 2: Because these are XML-based resource values, the name of the XML file doesn’t matter. That being said, we recommend something that makes sense to you - asdf.xml isn’t terribly descriptive, whereas replay-io-config.xml is.

Step 3 - Hook

…into the Android Activity lifecycle! If your app’s minimum supported SDK is API 14 (Ice Cream Sandwich) or greater, you don’t need to do anything! Otherwise, you have two options to hook into the Android Lifecycle:

  1. Extend ReplayActivity like so:
import io.replay.framework.ReplayActivity;

public class ExampleActivity0 extends ReplayActivity {

    @Override public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            //regular Activity setup here
    }

    /*for other lifecycle methods, just pretend you're
    extending Activity like normal*/

}
  1. If you already have a parent activity that you inherit from (e.g., you use ActionBarSherlock), you can manually add the lifecycle tracking events to any Activity that you’d like Replay.io to track:
import io.replay.framework.ReplayIO;

public class ExampleActivity1 extends Activity {

    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ReplayIO.onActivityCreate(this);
    }

    @Override public void onStart() {
        super.onStart();
        ReplayIO.onActivityStart(this);
    }

    @Override public void onResume() {
        super.onResume();
        ReplayIO.onActivityResume(this);
    }

    @Override public void onPause() {
        ReplayIO.onActivityPause(this);
        super.onPause();
    }

    @Override public void onStop() {
        ReplayIO.onActivityStop(this);
        super.onStop();
    }
}

(In case you were curious, this is exactly what happens in ReplayActivity.) For more information, check out the the documentation.

Step 4 - Track

You’re ready! Kick things off with ReplayIO.track("string").


Replay-Android Documentation (a deep dive)

Installation

You have a few options for obtaining the Replay.io Android library.

  1. **Gradle ** - recommended
repositories {
    mavenCentral()
}

dependencies {
    compile 'io.replay:replay-android:*version*'
    //e.g., 'io.replay:replay-android:0.+' or 'io.replay:replay-android:1+'
}
  1. Maven
<dependency>
    <groupId>io.replay</groupId>
    <artifactId>replay-android</artifactId>
    <version>1</version>
</dependency>
  1. JAR or AAR - Jump over to MavenCentral to download JARs.
  2. Clone the Repo - If all of the above makes you uncomfortable or doesn’t work, go ahead and clone the repo:
cd ~/
git clone git@github.com:Originate/replay-android.git
cd replay-android
git fetch && git pull origin master

NOTE: if you’re still using ADT/Eclipse and are importing Replay.io as a JAR or cloning the repo, remember to check “Is Library”. If you’re on IntelliJ/Android Studio, you really should be using Gradle.

XML Configuration

The XML file that you place in your app’s /res/values folder can contain a number of different configuration options that change how the Replay-Android client behaves. An example file with the different options follows.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--NOTE: All the parameters **except api_key** have default values which
    will be used if no value is specified-->
    <!--the interval between when events are dispatched to the server -->
    <!-- Default: 60000 ms  - OPTIONAL -->
    <integer name="dispatch_interval">6000</integer>

    <!-- set true to enable event tracking-->
    <!-- Default: true - OPTIONAL-->
    <string name="enabled">true</string>

    <!-- set true to print debug messages-->
    <!-- default: false - OPTIONAL-->
    <string name="debug_mode_enabled">false</string>

    <!-- If the number of events in the database reaches this value, no more
    events will be accepted by the library -->
    <!-- Default: 1200 - OPTIONAL-->
    <integer name="max_queue">1200</integer>

    <!-- Normally events are only sent to the server when the dispatch_interval
    is met but if the number of events reaches flush_at, they will be automatically
    sent-->
    <!--Default: 100 - OPTIONAL-->
    <integer name="flush_at">100</integer>

    <!--replay api key - REQUIRED -->
    <string name="api_key">API_KEY_HERE</string>
</resources>

Lifecycle

Adding hooks to the Android lifecycle allows the Replay.io Android client to better manage resources and determine which processes should run when.

If your app supports Ice Cream Sandwich (minimum), you don’t have to do anything - Replay-Android uses ActivityLifecycleCallbacks (introduced in API Level 14) to hook into the Activity Lifecycle.

If your app is more broadly targeted (e.g., you need support 2.3+), we have a few other options for you!

Option #1: Extend ReplayActivity

In most cases, replacing MyActivity extends Activity with MyActivity extends ReplayActivity should be sufficient.

public class MyActivity extends ReplayActivity {
    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override public void onStart() {
        super.onStart();
    }

    @Override public void onResume() {
        super.onResume();
    }

    @Override public void onPause() {
         super.onPause();
    }

    @Override public void onStop() {
        super.onStop();
    }
}

Overriding ReplayActivity.onCreate() is mandatory. The rest of the lifecycle events are optional - if you don’t override them, we’ll still pick them up.

Option #2: Roll Your Own

If you cannot extend the ReplayActivity base class for some reason (e.g., your Activity inheritance is complicated by ActionBarSherlock), you can totally still use Replay.io. Create an intermediate base class, so your inheritance structure is:

public class MyActivity extends IntermediateBaseClass

and where IntermediateBaseClass is as follows:

public class IntermediateBaseClass extends SherlockActivity{
    @Override public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState); //satisfies ActionBarSherlock
            ReplayIO.onActivityCreate(this);
    }
    //etc.
}

Method Documentation

Tracking Events

In order to track an event. You can use either of the following functions:

ReplayIO.track(String event, Map<String,?> properties);  //or
ReplayIO.track(String event, Object... properties);

To see a list of properties that can be specified go to:

/docs/rest_api/api_special_properties

Note that properties are passed as either a Map<String,?> or as a varargs array of Objects - i.e., "k1", v1, "k2", v2. It is a runtime error to pass an odd-numbered (or null) list to ReplayIO.track(...), and it is expected that the keys will be coercible (i.e., castable) to String.

Set Distinct ID

Once a Distinct ID (or identity) is set, all events from the user will be associated with that Distinct ID. In addition, traits are associated with a particular ID, so the Distinct ID provides a way to link users to a specific set of traits.

ReplayIO.identify(String distinctId);

Set Traits

Setting a user’s traits allows developers to add additional information about a user, such as gender and age.

In order to associate a set of traits with a particular user, you must first use identify(String distinctId) to identify the user.

ReplayIO.updateTraits(Map<String,?> traits); //or
ReplayIO.updateTraits(Object... traits);

To see a list of traits that can be specified go to:

/docs/rest_api/api_special_properties

Debugging

Logging to Logcat is enabled/disabled intially based on the XML parameters file that you create (see Setup Step 2). By default, ReplayIO will start with logging enabled. The XML configuration can be overridden programmatically:

ReplayIO.setDebugMode(true);
ReplayIO.setDebugMode(false);

Enable/disable

The library will track events and create traits IFF it is enabled. The libraryis enabled/disabled intially based on the XML parameters file that you create (see Setup Step 2).

ReplayIO.start();
ReplayIO.stop();

Dispatching

By default, ReplayIO will dispatch event data every minute. However, you may specify the interval (in milliseconds) between when in events are sent in the parameters XML file (see step 2 of setup).

If dispatchInterval == 0, then events are dispatched as soon as they are received. If you would like to manually dispatch all the previously enqueued events/traits, you can use the following function:

ReplayIO.dispatch();

Custom Builds & Misc

Dependencies

If you decide to do a custom build, you should be aware that Replay-Android depends on path/android-priority-jobqueue. However, currently, we are using a custom-modified version. You can find the diff here.

Replay-Android Threading and Database Model

Any call made to the tracking methods (ReplayIO.track(...) and ReplayIO.updateTraits(...)) are moved to a separate background thread as soon as possible. We always persist information to a database. Network calls are naturally made from a separate thread.

All of this means that the Replay-Android client uses minimal system resources and never blocks the UI thread.

Tests

Most of our functionality is covered by tests - if you find something that isn’t please let us know :)

The test suite can be run by:

gradle assembleDebug
gradle assembleDebugTest
gradle connectedAndroidTest

Please note that these tests require a connected Android device - be it emulator, Genymotion, or a real Android phone.