Treasure Data Android SDK

You can send data from your Android app to Treasure Data, using our Android SDK library. Our Treasure Data procedure doesn’t require any server-side installation in order to track your mobile application’s activities.

Table of Contents

Prerequisites

  • Basic knowledge of Android Development
  • Android 2.3 , or later
  • Any Android device running API 14 (Android 4.0) and higher (for automatic tracking of lifecycle events)
  • Basic knowledge of Treasure Data

GDPR compliance

To support compliance with national and global data privacy requirements such as the European General Data Privacy Regulation, our SDK provides methods that control the collection and tracking of personal data and metadata in applications and websites. When your company defines data privacy policies around personal data, you can use these methods in your code to implement default data collection behaviors, and add controls for individuals to use to manage data collection and privacy themselves.

Untitled-3
Customers of Treasure Data must ensure that their usage of the SDK, including its use that collects personal data, complies with the legal agreement that governs access to and use of the Treasure Data service, including specifically Treasure Data's current Terms of Service (https://www.treasuredata.com/terms/), privacy policy (https://www.treasuredata.com/privacy/), and Privacy Statement for Customer Data (https://www.treasuredata.com/td-downloads/Privacy-Statement-for-Customer-Data.pdf).

How to install Android SDK

Step 1: Install the Library

Gradle

If you use gradle, add the following dependency to dependencies directive in the build.gradle.

dependencies {
  compile 'com.treasuredata:td-android-sdk:0.1.18'
}

Maven

If you use maven, add the following directives to your pom.xml under <dependencies>. Refer to pom.xml in an example Android application project as a good reference.

<dependency>
  <groupId>com.treasuredata</groupId>
  <artifactId>td-android-sdk</artifactId>
  <version>0.1.18</version>
</dependency>

Jar File

If you don’t use Maven, put td-android-sdk-x.x.x-shaded.jar (get the latest here) into (YOUR_ANDROID_PROJECT)/libs.

Step 2: Enable Required Android Permissions

If it’s not already present, add the INTERNET permission to your AndroidManifest.xml file. The following entry should appear between the <manifest> .. </manifest> tags. Refer to the example here.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.treasuredata.android.demo"
  android:versionCode="1"
  android:versionName="1.0"
  android:name=".DemoApp">
  ...

  <!-- required permission -->
  <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

Step 3: Initialize the Library at onCreate() in your Application subclass

For efficient API calls, we highly recommend initializing a TreasureData shared instance at the onCreate() method of your Application subclass.

public class ExampleApp extends Application {

  @Override
  public void onCreate() {

    // Initialize Treasure Data Android SDK
    // @see https://docs.treasuredata.com/articles/android-sdk
    TreasureData.initializeApiEndpoint("https://in.treasuredata.com");
    TreasureData.initializeEncryptionKey("RANDOM_STRING_TO_ENCRYPT_DATA");
    TreasureData.disableLogging();
    TreasureData.initializeSharedInstance(this, "YOUR_WRITE_ONLY_API_KEY");
    TreasureData.sharedInstance.setDefaultDatabase("your_application_name");
    TreasureData.sharedInstance.setDefaultTable("your_event_name");
    TreasureData.sharedInstance.enableAutoAppendUniqId();
    TreasureData.sharedInstance.enableAutoAppendModelInformation();
    TreasureData.sharedInstance.enableAutoAppendAppInformation();
    TreasureData.sharedInstance.enableAutoAppendLocaleInformation();
  }
}

You can get the API key from the (Treasure Data Console). It’s recommended to use a write-only API key for SDKs.

Then, you can use a shared instance from anywhere with the TreasureData.sharedInstance() method.

public class ExampleActivity extends Activity {

  public void onDataLoadSomethingFinished(long elapsedTime) {
    Map<String, Object> event = new HashMap<String, Object>();
    event.put("data_type", "something");
    event.put("elapsed_time", elapsedTime);
    TreasureData.sharedInstance().addEvent("events", event);
  }
}

App lifecycle event tracking is optional and not enable by default. You can track app lifecycle events automatically using : TreasureData#enableAppLifecycleEvent()

App lifecycle events include : Application Install, Application Open, Application Update. You can disable the individual core events as the following:

  • Disable Application Install: disableAppInstalledEvent()
  • Disable Application Open: disableAppOpenEvent()
  • Disable Application Update: disableAppUpdatedEvent()

These events are captured along with relevant metadata, depending on the specific type of event:

Application Open

{
    "td_android_event" = "TD_ANDROID_APP_OPEN";
    "td_app_ver" = "1.0";
    "td_app_ver_num" = 1;
    ...
}

Application Install

{
    "td_android_event" = "TD_ANDROID_APP_INSTALL";
    "td_app_ver" = "1.0";
    "td_app_ver_num" = 1;
    ...
}

Application Update

{
    "td_android_event" = "TD_ANDROID_APP_UPDATE";
    "td_app_ver" = "1.1";
    "td_app_ver_num" = 2;
    "td_app_previous_ver" = "1.0";
    "td_app_previous_ver_num" = 1;
    ...
}

Step 4: Buffer the events locally

Next, call the addEvent(String table, Map<String, Object> record) function, at the appropriate time, within your applications. The following example shows an event sent to the button_clicks table, when the button is clicked.

Untitled-3
We generally recommend to use application's name as a database name, and event name as a table name.
View v = findViewById(R.id.button);
v.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    final Map event = new HashMap<String, Object>();
    event.put("name", "foo bar");
    event.put("age", 42);
    event.put("comment", "hello world");
    td.addEvent("button_clicks", event);
  }
});

With this call, a record, as the following shows, is immediately buffered on the disk.

{
  "td_uuid":"c123470de-3950-4997-b321-07d6f5b4a3",
  "td_os_type":"Android",
  "td_os_ver":"15",
  "td_device":"ISW11SC",
  "td_model":"ISW11SC",
  "td_display":"IMM76D.KDLPL",
  "td_brand":"KDDI",
  "td_board":"ISW11SC",
  "td_app_ver":"1.9.2",
  "td_app_ver_num":"11",
  "td_locale_country":"US",
  "td_locale_lang":"en",
  "name":"foo bar",
  "age":42,
  "comment":"helloworld"
}

By default, all events are buffered on the disk. You need to explicitly flush the buffered data to the cloud. Upload does not occur automatically. The following section describes how to flush the buffer, using the uploadEvents() function.

Step 5: Session Tracking and Events Upload at onStart() / onStop()

Call TreasureData.startSession() and TreasureData.endSession() at onStart() and onStop(). Then, call uploadEvents() at onStop() as well. The uploadEvents() function flushes the buffer and sends the data to the cloud. If upload fails, the function is automatically retried in a background thread.

protected void onStart(Bundle savedInstanceState) {
  TreasureData.startSession(this);
  td.addEvent("on_start_calls", ...); // optional but recommended
  Log.i(TAG, "onStart(): Session ID=" + TreasureData.getSessionId(this)); // You can get the current session ID like this
}

protected void onStop() {
  TreasureData.endSession(this);
  td.addEvent("on_stop_calls", ...); // optional but recommended
  td.uploadEvents();
}

When to upload and how often to upload buffered events depends on the characteristic of your application. Good times to upload include:

  • When the current screen is closing or moving to background
  • When closing the application

If there is any Context that has called startSession() but not endSession(), the session continues. Also, if a new Context calls startSession() within 10 seconds of the last Context calling endSession(), then the session resumes, instead of a new session being created.

Untitled-3
the IP whitelist isn't applied to any import from Android SDK. Also, often times, Android devices have an invalid timestamp (for example, 1970/01/01). For this reason, logs that have a timestamp older than 7 days, and newer than 3 days ahead are currently ignored.

Parameters Captured

Here is a list of parameters captured by the Android SDK:

- td_session_id
- td_uuid : unique ID for the combination of application and device
- td_board : android.os.Build#BOARD
- td_brand : android.os.Build#BRAND
- td_device : android.os.Build#DEVICE
- td_display : android.os.Build#DISPLAY
- td_model : android.os.Build#MODEL
- td_os_ver : android.os.Build.VERSION#SDK_INT
- td_os_type : "Android"
- td_app_ver : android.content.pm.PackageInfo.versionName (from Context.getPackageManager().getPackageInfo())
- td_app_ver_num : android.content.pm.PackageInfo.versionCode (from Context.getPackageManager().getPackageInfo())
- td_locale_country : java.util.Locale.getCountry() (from Context.getResources().getConfiguration().locale)
- td_locale_lang : java.util.Locale.getLanguage() (from Context.getResources().getConfiguration().locale)

Advanced Tips

Opt out

Depending on the countries where you sell your app (e.g. the EU), you may need to offer the ability for users to opt-out of tracking data inside your app.

  • To turn off auto tracking events (when application lifecycle event tracking is enable) : TreasureData#disableAppLifecycleEvent().
  • To turn off custom events (the events you are tracking by TreasureData#addEvent, TreasureData#addEventWithCallback ) : TreasureData#disableCustomEvent. To turn on it again : TreasureData#enableCustomEvent

You can query the state of tracking events by using : TreasureData#isAppLifecycleEventEnabled() and TreasureData#isCustomEventEnabled() The states have effects across device reboots, app updates, so you can simply call this once during your application.

Adding UUID of the device to each event automatically

The UUID of the device is added to each event automatically if you call enableAutoAppendUniqId(). This value won’t change until the application is uninstalled.

td.enableAutoAppendUniqId();
    :
td.addEvent(...);

It outputs the value as a column name td_uuid.

You can reset the UUID and send forget_device_uuid event with the old UUID using TreasureData#resetUniqId().

Sending data with Array type

Android SDK can handle java.util.List or java.lang.String[] to send data with Array type. But, it doesn’t handle JSONArray because the internal library jackson.databind doesn’t handle JSONArray.

event.put("array", Arrays.asList("one", "two", "three"));

Retry uploading and deduplication

This SDK imports events in one manner with the following features:

  • The SDK keeps buffered events with added unique keys and retries to upload the events until confirming the events are uploaded and stored (at least once) on server side
  • The server side remembers the unique keys of all events within the past 1 hour by default and prevents duplicated imports (at most once)

The deduplication window is 1 hour by default, so it’s important not to keep buffered events for more than 1 hour to avoid duplicated events.

Next Steps

For transparency, we are making our Android SDK available as open source on Github. Check the repository to ensure that you have the most recent SDK.


Last modified: Apr 04 2018 15:27:46 UTC

If this article is incorrect or outdated, or omits critical information, let us know. For all other issues, access our support channels.