Skip to main content

Android Mobile SDK

Analytics for Android makes it simple to send your data to Intilery.

All of Intilery's client sources are open-source, so you can view Analytics for Android on GitHub

Want to stay updated on releases? Subscribe to the release feed.

Analytics for Android only supports any Android device running API 14 (Android 4.0) and higher. This includes Amazon Fire devices.

Analytics-Android and Unique Identifiers#

One of the most important parts of any analytics platform is the ability to consistently and accurately identify users. To do this, the platform must assign and persist some form of identification on the device, so you can analyze user actions effectively. This is especially important for funnel conversion analysis and retention analysis.

Naturally the Analytics SDK needs a unique ID for each user. The very first time an Android app that uses Intilery launches, the Intilery SDK generates a UUID and saves it on the device’s disk. This is used as the anonymousId and stays constant for the user on the device. To create a new user on the same device, call reset on the Analytics client.

The Intilery SDK also collects the Advertising ID provided by Play Services. Make sure the Play Services Ads library is included as a dependency for your application. This is the ID that should be used for advertising purposes. This value is set to context.device.advertisingId.

Intilery also collects the Android ID as context.device.id. Some destinations rely on this field being the Android ID, so double check the destinations’ vendor documentation if you choose to override the default value.

API call queuing in Analytics-Android#

The Analytics-Android library queues API calls and uploads them in batches. This limits the number of network calls made, and helps save battery on the user’s device.

When you send an event, the library saves it to disk. When the queue size reaches the maximum size you specify (20 by default), the library flushes the queue and uploads the events in a single batch. Since the data is saved immediately, it isn’t lost even if the app is killed or the operating system crashes.

Queue persistance in Analytics-Android#

Analytics-Android uses a persistent disk queue, so the events persist even when the app is killed. On app restart, the library reads them from disk and uploads the events. The queue works on top of Tape, which is designed to even survive process and system crashes.

Analytics-Android saves up to 1000 calls on disk, and these never expire.

Getting Started#

Step 1: Install the Library#

The easiest way to install the Analytics-Android library is using a build system like Gradle. This makes it simple to upgrade versions and add destinations. The library is distributed using Maven Central. Just add the analytics module to your build.gradle file as in the example lines below:

dependencies {  implementation 'com.intilery.analytics.android:analytics:1.0.0'  }

Step 2. Initialize the Client#

We recommend initializing the client in your Application subclass. You’ll need your Intilery Write Key for your Android Source.

Java#

// Create an analytics client with the given context and Intilery write key.Analytics analytics = new Analytics.Builder(context, YOUR_WRITE_KEY)  .trackApplicationLifecycleEvents() // Enable this to record certain application events automatically!  .recordScreenViews() // Enable this to record screen views automatically!  .build();
// Set the initialized instance as a globally accessible instance.Analytics.setSingletonInstance(analytics);

Kotlin#

// Create an analytics client with the given context and Intilery write key.val analytics = Analytics.Builder(context, YOUR_WRITE_KEY)  .trackApplicationLifecycleEvents() // Enable this to record certain application events automatically!  .recordScreenViews() // Enable this to record screen views automatically!  .build()
// Set the initialized instance as a globally accessible instance.Analytics.setSingletonInstance(analytics);

Notes:

  • You can automatically track lifecycle events such as Application Opened, Application Installed, Application Updated to start quickly with core events. These are optional, but highly recommended.

Customize the Client (Optional)#

The entry point of the library is through the Analytics class. As you might have seen in the quickstart, here’s how you initialize the Analytics client with it’s defaults.

Java#

Analytics analytics = new Analytics.Builder(context, writeKey).build();

Kotlin#

val analytics = Analytics.Builder(context, writeKey).build()

The Analytics.Builder class lets you customize settings for the Analytics client, including things like the flush interval. Refer to the Javadocs for details on customizable parameters.

We also maintain a global default instance which is initialized with defaults suitable to most implementations.

Java#

// You can also register your custom instance as a global singleton.Analytics.setSingletonInstance(analytics);Analytics.with(context).track(...);

Kotlin#

// You can also register your custom instance as a global singleton.Analytics.setSingletonInstance(analytics)Analytics.with(context).track(...)

In general, Intilery recommends that you use the Builder method because it provides the most flexibility. Remember you can call Analytics.setSingletonInstance only ONCE, so it’s best to put the initialization code inside your custom Application class.

Java#

public class MyApp extends Application {  @Override public void onCreate() {    Analytics analytics = new Analytics.Builder(context, writeKey).build();    Analytics.setSingletonInstance(analytics);
    // Safely call Analytics.with(context) from anywhere within your app!    Analytics.with(context).track("Application Started");  }}

Kotlin#

class MyApp : Application() {  override fun onCreate() {    val analytics = Analytics.Builder(context, writeKey).build()    Analytics.setSingletonInstance(analytics)
    // Safely call Analytics.with(context) from anywhere within your app!    Analytics.with(context).track("Application Started")  }}

Once you initialize an Analytics client, you can safely call any of its tracking methods from any thread. These events are dispatched asynchronously to the Intilery servers.

Note: You should only ever initialize ONE instance of the Analytics client. These are expensive to create and throw away, and in most cases, you should stick to Intilery’s singleton implementation to make using the SDK easier.

Step 3. Add Permissions#

Ensure that the necessary permissions are declared in your application’s AndroidManifest.xml.

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

Data Collection - The Basic Intilery API calls#

The Intilery API calls include:

Identify#

Good to know: For any of the different methods described in this doc, you can replace the properties and traits in the code samples with variables that represent the data collected.

Identify calls let you tie a user to their actions, and record traits about them. It includes a unique User ID and any optional traits you know about them.

Example identify call:

Java#

Analytics.with(context).identify("a user's id", new Traits().putName("John Doe"), null);

Kotlin#

Analytics.with(context).identify("a user's id", Traits().putName("John Doe"), null)

Intilery recommends that you make an Identify call once when the user’s first creates an account, and only using the Identify call later when their traits change. Intilery remembers the previous userIDs and merges the new traits with the old ones.

Java#

// Initially when you only know the user's nameAnalytics.with(context).identify(new Traits().putName("Michael Bolton"));
// Sometime later in your app when the user gives you their emailAnalytics.with(context).identify(new Traits().putEmail("mbolton@example.com"));

Kotlin#

// Initially when you only know the user's nameAnalytics.with(context).identify(Traits().putName("Michael Bolton"))
// Sometime later in your app when the user gives you their emailAnalytics.with(context).identify(Traits().putEmail("mbolton@example.com"))

Remember, you can replace the properties and traits in the code samples with variables that represent the data you actually collected.

The Identify call has the following fields:

userId String,optionalThe database ID for this user.
traits Traits,optionalA map of traits about the user, such as their name, email, address, etc.
options Options, optionalExtra options

The Android library currently automatically sends the userId and anonymousId as traits. Additionally, traits are sent in the context.traits field with every message.

Track#

The Track call lets you record the actions your users perform. Every action triggers what we call an “event”, which can also have associated properties.

To get started, the Analytics-Android SDK can automatically tracks a few key common events using the Intilery Native Mobile Spec, such as the Application Installed, Application Updated and Application Opened. You can enable this option during initialization.

You might also want to track events that indicate success for your mobile app, like Signed Up, Item Purchased or Article Bookmarked. Intilery recommends tracking just a few important events. You can always add more later!

Example track call:

Java#

Analytics analytics = new Analytics.Builder(context, writeKey)  .trackApplicationLifecycleEvents()  .build();
Analytics.with(context).track("Product Viewed", new Properties().putValue("name", "Moto 360"));

Kotlin#

val analytics = Analytics.Builder(context, writeKey)  .trackApplicationLifecycleEvents()  .build()
Analytics.with(context).track("Product Viewed", Properties().putValue("name", "Moto 360"))

This example Track call tells us that your user just triggered the Product Viewed event with a name of “Moto 360.”

The Track call properties can be anything you want to record, for example:

Java#

Analytics.with(context).track("Purchased Item", new Properties().putValue("sku", "13d31").putRevenue(199.99));

Kotlin#

Analytics.with(context).track("Purchased Item", Properties().putValue("sku", "13d31").putRevenue(199.99))

The Track call includes the following fields:

name String,requiredA name for the tracked action.
properties Properties,optionalA map of properties for this action, e.g. revenue if the action was a purchase.
options Options,optionalOptions

Screen#

The Screen method lets you you record whenever a user sees a screen of your mobile app, along with optional extra information about the page being viewed.

You’ll want to record a screen event an event whenever the user opens a screen in your app. This could be a view, fragment, dialog or activity depending on your app.

Not all services support screen, so when it’s not supported explicitly, the screen method tracks as an event with the same parameters.

Example screen call:

Java#

// category "Feed" and a property "Feed Length"Analytics.with(context).screen("Feed", new Properties().putValue("Feed Length", "26"));
// no category, name "Photo Feed" and a property "Feed Length"Analytics.with(context).screen(null, "Photo Feed", new Properties().putValue("Feed Length", "26"));
// category "Smartwatches", name "Purchase Screen", and a property "sku"Analytics.with(context).screen("Smartwatches", "Purchase Screen", new Properties().putValue("sku", "13d31"));

Kotlin#

// category "Feed" and a property "Feed Length"Analytics.with(context).screen("Feed", Properties().putValue("Feed Length", "26"))
// no category, name "Photo Feed" and a property "Feed Length"Analytics.with(context).screen(null, "Photo Feed", Properties().putValue("Feed Length", "26"))
// category "Smartwatches", name "Purchase Screen", and a property "sku"Analytics.with(context).screen("Smartwatches", "Purchase Screen", Properties().putValue("sku", "13d31"))

The screen call has the following fields:

category *String,optional**A category for the screen. Optional if name is provided.
name *String,optional**A name for the screen. Optional if category is provided.
properties Properties,optionalA map of properties for this screen.
options Options,optionalOptions

Find details on the Screen payload in the Intilery Screen call spec.

Automatic Screen Tracking#

The Intilery SDK can automatically instrument screen calls, using the label of the activity you declared in the manifest as the screen’s name. Fragments and views do not trigger screen calls automatically, however you can manually call the Screen method for these.

Java#

Analytics analytics = new Analytics.Builder(context, writeKey)  .recordScreenViews()  .build();

Kotlin#

val analytics = Analytics.Builder(context, writeKey)  .recordScreenViews()  .build()

Context#

Context is a dictionary of extra information you can provide about a specific API call. You can add any custom data to the context dictionary that you want to have access to in the raw logs. Some keys in the context dictionary have semantic meaning and are collected for you automatically, such as information about the user’s device.

Java#

AnalyticsContext analyticsContext = Analytics.with(context).getAnalyticsContext();analyticsContext.putValue(...).putReferrer(...).putCampaign(...);

Kotlin#

val analyticsContext = Analytics.with(context).analyticsContextanalyticsContext.putValue(...).putReferrer(...).putCampaign(...)

You can read more about these special fields in the Intilery Common spec documentation.

To alter data specific to the device object you can use the following:

Java#

AnalyticsContext analyticsContext = Analytics.with(context).getAnalyticsContext();analyticsContext.device().putValue("advertisingId", "1");

Kotlin#

val analyticsContext = Analytics.with(context).analyticsContextanalyticsContext.device().putValue("advertisingId", "1")

To opt out of automatic data collection, clear the context after initializing the client. Do this BEFORE you send any events.

Java#

Analytics analytics = new Analytics.Builder(context, writeKey).defaultOptions(defaultOptions).build();AnalyticsContext context = getAnalyticsContext();context.clear();

Kotlin#

val analytics = Analytics.Builder(context, writeKey).defaultOptions(defaultOptions).build()val context = analytics.analyticsContextcontext.clear()

Utility methods#

Retrieve AnonymousId#

You can retrieve the anonymousId set by the library by using:

Java#

Analytics.with(context).getAnalyticsContext().traits().anonymousId();

Kotlin#

Analytics.with(context).analyticsContext().traits().anonymousId()

Reset#

The reset method clears the SDK’s internal stores for the current user and group. This is useful for apps where users log in and out with different identities on the same device over time.

The example code below clears all information about the user.

Java#

Analytics.with(context).reset();

Kotlin#

Analytics.with(context).reset()

Reset does not clear events in the queue, and any remaining events in the queue are sent the next time the app starts. You might want to call Flush before you call Reset.

Note: When you call reset, the next time the app opens Intilery generates a new AnonymousId. This can impact the number of Monthly Tracked Users (MTUs) you process.

Collecting Stats#

Local device stats help you quickly see how many events you sent to Intilery, the average time bundled destinations took to run, and similar metrics.

Java#

StatsSnapshot snapshot = Analytics.with(context).getSnapshot();log(snapshot.integrationOperationAverageDuration);log(snapshot.flushCount);

Kotlin#

val snapshot = Analytics.with(context).snapshot()log(snapshot.integrationOperationAverageDuration)log(snapshot.flushCount)

Adding debug logging#

If you run into issues while using the Android library, you can enable logging to help trace the issue. Logging also helps you see how long destinations take to complete their calls so you can find performance bottlenecks.

The logging is enabled by default in the default singleton instance if your application is running in debug mode. If you use a custom instance, attach a LogLevel to the Builder and set the logging level there, as in the example below.

Java#

Analytics analytics = new Analytics.Builder(context, writeKey).logLevel(LogLevel.VERBOSE)...build();

Kotlin#

val analytics = Analytics.Builder(context, writeKey).logLevel(LogLevel.VERBOSE)...build()

You can choose to disable logging completely (LogLevel.NONE), enable basic logging for the SDK (LogLevel.BASIC), enable basic logging for Device-mode destination (LogLevel.INFO), or simply log everything (LogLevel.VERBOSE).

Intilery recommends that you turn logging off in production modes of your app.

Privacy methods#

Opt-out#

Depending on the audience for your app (for example, children) or the countries where you sell your app (for example, the EU), you may need to offer the ability for users to opt-out of analytics data collection inside your app. You can turn off ALL destinations including Intilery itself:

Java#

Analytics.with(this).optOut(true);

Kotlin#

Analytics.with(this).optOut(true)

Set the opt-out status for the current device and analytics client combination. This flag persists across device reboots, so you can call it once in your application, such as in a screen where a user can opt out of analytics tracking.

Anonymizing IP#

The Intilery iOS, Android, Analytics.js and Xamarin libraries automatically derive and set the IP address for events recorded on the user’s device. The IP is not collected on the device itself, but instead is filled in by Intilery’s servers when they receive a message.

To prevent Intilery from recording the users’ IP in destinations and S3, you can set the event’s context.ip field to 0.0.0.0. The Intilery servers won’t overwrite this data if it comes from the client, and so do not record the IP address of the client.

Formatting Order Completed Events#

Intilery’s Android library provides several helper methods so you can easily construct both properties objects and products lists so your Order Completed events conform to the Intilery ecommerce specification. Here’s a code example:

Java#

import com.segment.analytics.Analytics;import com.segment.analytics.Properties;import com.segment.analytics.Properties.Product;
// initialize a new properties objectProperties properties = new Properties();
// add orderId and revenue to the properties objectproperties.putValue("orderId", String orderId).putValue("revenue", double revenue);
// initialize a new productProduct product1 = new Product(String id, String sku, double price);
// initialize a second productProduct product2 = new Product(String id, String sku, double price);
// add products to the properties objectproperties.putProducts(product1, product2);
// pass the properties object into your Order Completed eventAnalytics.with(context).track("Order Completed", properties);

Kotlin#

import com.segment.analytics.Analyticsimport com.segment.analytics.Propertiesimport com.segment.analytics.Properties.Product
// initialize a new properties objectval properties = Properties();
// add orderId and revenue to the properties objectproperties.putValue("orderId", orderId).putValue("revenue", revenue)
// initialize a new productProduct product1 = Product(id, sku, price)
// initialize a second productProduct product2 = Product(id, sku, price)
// add products to the properties objectproperties.putProducts(product1, product2)
// pass the properties object into your Order Completed eventAnalytics.with(context).track("Order Completed", properties)

Find details on best practices in event naming as well as the Track method payload in the Intilery Track call spec.