Kumulos provides an SDK to ease the integration of the Kumulos Analytics, Push Notification, Crash Reporting and Build features into your Android app. This guide provides an overview of setting up the SDK for your project and sample usage. This assumes that you've deployed your API.

Project Setup

The Kumulos libraries are distributed through JCenter. To install the libraries, edit your app's build.gradle file to add the following:

  • Exclude conflicting meta data files from the build
  • Set up the manifest placeholder for your GCM project
  • Declare source & target compile options
  • Add the Kumulos library dependencies

A sample build.gradle can be seen below.

android {
    defaultConfig {

        // Add the sender ID to use push notifications with GCM
        // Leave blank if you don't want to configure push
        manifestPlaceholders = [
                kumulos_gcm_sender_id: ''

    // Exclude duplicate files from the build
    packagingOptions {
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/ASL2.0'
        exclude 'META-INF/LICENSE'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8

dependencies {
    // Kumulos debug & release libraries
    debugImplementation ''
    releaseImplementation ''

The debugImplementation will have logging enabled with a tag matching com.kumulos.*. When running in debug mode, the log messages should be visible in LogCat.

Run a Gradle sync to install the Kumulos libraries and build your project.


To initialize the SDK, we recommend subclassing the Application class and initializing Kumulos in its onCreate method.

Create an Application class

package com.example;


public class ExampleApp extends Application {

    public void onCreate() {

        KumulosConfig config = new KumulosConfig.Builder("YOUR_API_KEY", "YOUR_SECRET_KEY").build();
        Kumulos.initialize(this, config);

Your API key and secret key can be found on the app dashboard in Kumulos' control panel.

You don't need to initialize Kumulos every time you wish to make an API call. It only needs to be initialized once, after that it will remember the API key and secret key you've given it the first time.

Add your Application to the AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=""

    <!-- Set the android:name to your custom Application class -->


Checking installs of your App

When you run your app on a simulator or install your app on a device, you can check that the SDK has been initialized correctly by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install to see more information.

Recent installs

If you experience any difficulties integrating an SDK or initializing the Kumulos client, please don't hesitate to contact support who are standing by to help!

Installation ID

When initialized for the first time, the Kumulos SDK will create a unique identifier for the app installation that initialized the SDK.

This identifier can be used to target push notifications to a specific device through KScript or the Push Notifications API.

In order to retrieve this installation ID, simply access the class variable:

String id =;

Once you have the installation ID, you can send it to your app's backend to be used later for push targeting. For more information about push targeting, please see the KScript Documentation or push notification documentation as appropriate.


Kumulos provides concise and easy to consume analytics & reporting features. By initializing the SDK, you automatically get session & engagement reporting out the box.

Session Analytics

Kumulos records sessions based on application foreground and background events. When an app enters the background, Kumulos will wait for a configurable idle period. If there are no more foreground events during that idle period, the current session will be closed.

Session analytics

You can configure the idle period to suit your app's use-case. By default the idle period is 40 seconds of inactivity. The idle period does not count towards session duration calculations.

To adjust the idle period, you can configure the SDK as follows:

KumulosConfig config = new KumulosConfig.Builder("YOUR_API_KEY", "YOUR_SECRET_KEY")
Kumulos.initialize(this, config);

Event Tracking

Kumulos allows you to track custom analytics events that can be used as a trigger to fire automation rules (e.g. to trigger a push notification) or as steps in a funnel to track conversion through key user journeys in your app.

Track conversion

To track a custom analytics event, use Kumulos.trackEvent as follows:

JSONObject props = new JSONObject();
props.put("productId", 404);
Kumulos.trackEvent(context, "product.purchased", props);

Event tracking is available offline as all events are persisted locally before being synced to the server in batches in the background.

Checking events from your App

When you run your app on a simulator or install your app on a device, you can check that the SDK is recording events correctly by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install and then click on the Events tab.

Install events

Alternatively, to see counts of all analytics events, including system events such as opened a push notification, recorded by installs of the app in the last 30 days, expand 'Analytics' and click 'Explore' in the left menu. For comparison, the total number of sessions in the same period is shown.

Analytics Explorer

User Association

Kumulos allows associating a user identifier with the current installation ID. This user identifier is useful for performing analytics aggregations & analyses at the user level, for example, funnels completed by users across multiple devices. You can also optionally associate a collection of attributes with the user.

To associate the current app installation with a user, you can use the helper method as shown below:

Kumulos.associateUserWithInstall(context, "unique-user-id");

User association is time-aware, so say two different users log in to the app, their user IDs will be associated with the same install for the time between subsequent calls to the helper method. For example:

Kumulos.associateUserWithInstall(context, "Bob");
// This event will belong to Bob
Kumulos.trackEvent(context, "product.purchased", null);
Kumulos.associateUserWithInstall(context, "Alice");
// This event will belong to Alice
Kumulos.trackEvent(context, "product.purchased", null);


You can optionally associate a collection of attributes with the user for targeting, personalization or attribution. To associate attributes with the user, pass a collection into the helper method as shown.

JSONObject attributes = new JSONObject();
props.put("name", "Shawn");
props.put("age", 25);

Kumulos.associateUserWithInstall(context, "unique-user-id", attributes);

If you do not have a user identifier, use the installation ID generated by the Kumulos SDK.


The Kumulos SDK provides push notifications with GCM. To integrate Kumulos Push into your Android project, you have to complete the following steps:

  1. Set up a Google Project & enable GCM
  2. Configure Push in the Kumulos Agency Console
  3. Integrate SDK components with your Android project
  4. Register for push form the client app

Configuration & Integration

In order to enable push notifications for Android with Kumulos, you'll need to set up a GCM project and configure push for your app. These steps are shown in the following video guide.

Configuring GCM for Android with Kumulos

After configuring Kumulos & GCM, simply follow the SDK integration steps below.

Integrate the SDK

Set up the kumulos_gcm_sender_id manifest placeholder in your app's build.gradle:

android {
    defaultConfig {
        // Add the Google project number to use push notifications with GCM
        manifestPlaceholders = [
            kumulos_gcm_sender_id: '[YOUR_SENDER_ID]'

Ensure that your app has the INTERNET permission and add the Kumulos PushBroadcastReceiver to your AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=""

    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Optionally add the wake lock permission to stop the CPU from sleeping when a message is received -->
    <!-- <uses-permission android:name="android.permission.WAKE_LOCK" /> -->



        <!-- Kumulos Push receiver -->
        <receiver android:name="" android:exported="false">
                <action android:name="com.kumulos.push.RECEIVED" />
                <action android:name="com.kumulos.push.OPENED" />


Register the client app installation to receive push notifications when you consider it appropriate:


The pushRegister() method takes context as a parameter, from where it extracts the device's push token and sends this to Kumulos (so you can then send push notifications to that app on that device).

This will prompt the user whether or not they want to receive push notifications for this app. Therefore, while it is upto you to decide when it is appropriate to do this, we do not recommend doing this as soon as the app is installed (as the user has no incentive to accept at this point). Instead, it is better to wait until the user is actively using the app, which should result in a higher subscription rate.

If you want to unregister the installation, you can use Kumulos.pushUnregister().

Checking Push Registrations

When you run your app on a simulator or install your app on a device, you can check that the install has successfully registered for push notifications by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install and then click on Push tab.

Install push details

Default Push Behavior

By default, the Kumulos PushBroadcastReceiver will show a notification on the notification area of the device when a content push is received.

Tapping this notification will open the main launcher activity of your application and track the push open conversion for you.

Your main activity will receive the push contents in its options bundle under the PushMessage.EXTRAS_KEY.

No action is taken for data pushes by default.

Changing the Push Icon

To change the icon shown in the status bar on Android, you can configure Kumulos with a drawable at initialization time:

KumulosConfig config = new KumulosConfig.Builder("API_KEY", "SECRET_KEY")
Kumulos.initialize(this, config);

Make sure to comply with the status bar icon guidelines so the icon renders correctly on all devices. For help preparing assets, we suggest checking out the Android Asset Studio

Customizing Push Behavior

To customize the behavior of the SDK when a push is received or its notification is tapped, we suggest subclassing the PushBroadcastReceiver and overriding its base methods depending on what you want to customize.

Example extension class:

package com.example;


public class MyPushReceiver extends PushBroadcastReceiver {


Make sure to change the AndroidManifest.xml receiver:

<receiver android:name="com.example.MyPushReceiver" android:exported="false">
        <action android:name="com.kumulos.push.RECEIVED" />
        <action android:name="com.kumulos.push.OPENED" />

Changing the Launched Activity

To change which activity will be launched when the user taps a notification, you can override the PushBroadcastReceiver#getPushOpenActivityIntent(Context, PushMessage).

package com.example;

import android.content.Context;
import android.content.Intent;


public class MyPushReceiver extends PushBroadcastReceiver {

    protected Intent getPushOpenActivityIntent(Context context, PushMessage pushMessage) {
        // TODO implement your own logic here
        return super.getPushOpenActivityIntent(context, pushMessage);

The PushMessage model will not be added to the Intent by default, it is up to you to add it as an extra if desired:

Intent launchIntent = new Intent(context, MyActivity.class);
launchIntent.putExtra(PushMessage.EXTRAS_KEY, pushMessage);

You can return null to track the push conversion and do nothing when the notification is tapped.

If the Intent returned does not describe an Activity, it will be ignored

Customizing the Notification

To customize the notification shown to the user for content pushes, you can override PushBroadcastReceiver#buildNotification(Context, PushMessage).

package com.example;

import android.content.Context;


public class MyPushReceiver extends PushBroadcastReceiver {

    protected Notification buildNotification(Context context, PushMessage pushMessage) {
        // TODO customize the notification
        return super.buildNotification(context, pushMessage);

If you want to handle the open with the broadcast receiver, be sure to set up the content intent of the notification as follows:

Intent openIntent = new Intent(PushBroadcastReceiver.ACTION_PUSH_OPENED);
        openIntent.putExtra(PushMessage.EXTRAS_KEY, pushMessage);

PendingIntent pendingOpenIntent = PendingIntent.getBroadcast(
        (int) pushMessage.getTimeSent(),
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);



This will ensure that the notification conversion is tracked in Kumulos.

If you want to do something else, you can manually track push open conversion using Kumulos#pushTrackOpen(Context, String).

Kumulos.pushTrackOpen(context, pushMessage.getId());

Launching a Service for Background Data Pushes

To launch a service when a background data push is received, you can override PushBroadcastReceiver#getBackgroundPushServiceIntent.

package com.example;

import android.content.Context;
import android.content.Intent;


public class MyPushReceiver extends PushBroadcastReceiver {

    protected Intent getBackgroundPushServiceIntent(Context context, PushMessage pushMessage) {
        // TODO implement your own logic here
        return super.getBackgroundPushServiceIntent(context, pushMessage);

This would easily allow you to handle data processing in the background by launching an IntentService for example.

The PushMessage model will not be added to the Intent by default, it is up to you to add it as an extra if desired:

Intent serviceIntent = new Intent(context, MyIntentService.class);
serviceIntent.putExtra(PushMessage.EXTRAS_KEY, pushMessage);

Return null if you want to do nothing with the data push.

If the Intent returned does not describe a Service, it will be ignored

URL Pushes

Push notifications sent to open a URL will, by default, track the push open if the user taps the notification, and then open the default web browser.

Overriding All Behaviors

If you want to completely replace the logic for handling pushes, you can override PushBroadcastReceiver#onPushReceived(Context, PushMessage).

Bear in mind you will be responsible for all aspects of the push process such as showing a notification to the user, tracking an open conversion using Kumulos#pushTrackOpen(Context, String), or launching any activities or services.

Push Channels

You can create and manage subscriptions to push channels from the SDK. Channels allow you to send push notifications to certain interest groups.

All channel management is performed with an instance of the PushSubscriptionManager class.

You can create an instance using the default constructor:

PushSubscriptionManager manager = new PushSubscriptionManager();

This constructor requires the Kumulos SDK to be initialized as described in the Initialization section of this guide

The push manager exposes several methods to manage subscriptions:

public interface PushSubscriptionManagerInterface {
    void subscribe(Context c, String[] uuids, Kumulos.Callback callback);

    void unsubscribe(Context c, String[] uuids, Kumulos.Callback callback);

    void setSubscriptions(Context c, String[] uuids, Kumulos.Callback callback);

    void clearSubscriptions(Context c, Kumulos.Callback callback);

    void listChannels(Context c, Kumulos.ResultCallback<List<PushChannel>> callback);

    void createChannel(Context c, String uuid, boolean subscribe, Kumulos.ResultCallback<PushChannel> callback);

    void createChannel(Context c, String uuid, boolean subscribe, @Nullable String name, boolean showInPortal, @Nullable JSONObject meta, Kumulos.ResultCallback<PushChannel> callback);

Results are handled with instances of the Kumulos.Callback or Kumulos.ResultCallback<ResultType> classes. For example:

PushSubscriptionManager manager = new PushSubscriptionManager();
manager.listChannels(this, new Kumulos.ResultCallback<List<PushChannel>>() {
    public void onSuccess(List<PushChannel> result) {
        // Handle the result

    // Optional error override
    public void onFailure(Exception e) {
        // Handle the error

Channel visibility and metadata

Channel visiblity and meta data can be controlled when they are created.

Location Tracking

You can send Kumulos location updates and use this to trigger events such as push notifications when an install enters a GeoFence.

How you configure location updates depends on the specific use case of your app. You should consider both accuracy and battery life when making this decision. Refer to the Android developer guide for further information.

Once you have set up location updates from the OS, you can send them to Kumulos like so:

Kumulos.sendLocationUpdate(context, location);

Eddystone Beacon Detection

You can send Kumulos beacon proximity updates and use these to trigger automations such as sending a push notification when an install is in proximity to a beacon.

The Kumulos SDK provides a helper method to notify our services of proximity to a detected beacon.

Kumulos.trackEddystoneBeaconProximity(context, hexNamespace, hexInstance);

Beacon monitoring on Android typically requires a device with BLE, and API level 18+. You can read more about detecting beacons in the Android Nearby reference.


You can call API methods defined in the Kumulos Build service using the method.

To talk to Kumulos, you need three things:

  • your method title (in lowerCamelCase)
  • a method parameters map (field names are also in lowerCamelCase)
  • some response handler code

Parameter maps

Parameters are constructed as a standard Java HashMap<String, String>.

HashMap<String, String> params = new HashMap<String, String>();
params.put("PARAM_NAME_1", "PARAM_VALUE_1");

You can use the static String.ValueOf() method to convert numbers to strings, for example:

int selectedUser=3;
HashMap<String, String> params = new HashMap<String, String>();
params.put("userID", String.valueOf(selectedUser));

Response Handler

As for the response handler, we create an anonymous extension of the class and override its didCompleteWithResult method."YOUR_METHOD_TITLE", params, new ResponseHandler() {
    public void didCompleteWithResult(Object result) {
        // Process the results
        // Do updates to the UI by calling back to the main UI thread with a Handler or posted Runnable

And you're done! You can now make calls to Kumulos from your android application. Read on for a little more information about result handling.

If you are making the request from a background thread, such as an IntentService, you should use the Kumulos#callSync blocking method.

Handling Results

The Object passed in to your response handler will take different forms based on what type of action the API method returns.

Select Actions

Select actions will return an ArrayList of LinkedHashMap<String, Object> and can be cast as such to allow iteration like so:"YOUR_METHOD_TITLE", params, new ResponseHandler() {
    public void didCompleteWithResult(Object result) {
        ArrayList<LinkedHashMap<String, Object>> objects = (ArrayList<LinkedHashMap<String,Object>>) result;
        for (LinkedHashMap<String, Object> item : objects) {
            String field1 = (String) item.get("NAME_OF_FIELD1");
            Integer field2 = (Integer) item.get("NAME_OF_FIELD2");

The objects in the array list are LinkedHashMap<String,Object> instances where the types of the values have been converted to regular Java types such as String, Integer, and Double.

Any nested objects in the object will also be of the LinkedHashMap<String,Object> type.

We would recommend you which you create model instances (e.g. POJO) to suit your client app by casting the HashMap fields to client model fields.

All Other Actions

All other actions in Kumulos currently return number values, either integers of doubles. Therefore, the result value may be either an Integer, or Double.

Please note it is possible that the result will be null in some cases and your code should take this into account.

Handling Data Fields

Kumulos stores data fields as base64 encoded data, so if you receive data from Kumulos, you will have to base64 decode it to access the original data. Similarly, when you send data to Kumulos, you should base64 encode it before transport.

To achieve this, please refer to the Android SDK Base64 utility.


Crash reporting allows you to track unhandled exceptions in your app, and optionally log any caught exceptions for further investigation. Crash reporting is not enabled by default. To enable this feature, simply modify your Kumulos configuration as follows:

KumulosConfig config = new KumulosConfig.Builder("YOUR_API_KEY", "YOUR_SECRET_KEY")
Kumulos.initialize(this, config);

That's it! Unhandled exceptions that lead to crashes will now be recorded automatically and shown in your App Delivery Console.

Note that crash reporting is not available whilst connected to a debugger, but it does work with debug builds.

If you wish to log any caught exceptions, you can record them with the Kumulos#logException(e) helper method:

try {
catch (Throwable e) {

Ensure that crash reporting is enabled when attempting to log exceptions.



Allow customizing ACRA report content by exposing the ACRA configuration builder used by the Kumulos SDK.

Now a KumulosConfig has a getAcraConfigBuilder(Application) method which allows changing fields in the report.

Note if you wish to access this method, it will require adding a compileOnly 'ch.acra:acra-http:5.1.3' dependency to your app's Gradle dependencies.


  • Add support for storing user attributes when associating an install with a user


  • Add event tracking helper which flushes events immediately
  • Embed config in analytics upload task arguments
  • Build config & dependency updates


Fix creation of release lib POM with dependencies


  • Update dependencies


  • Add beacon tracking helper
  • Record push events, location updates, and user associations locally in the event DB

Breaking changes

The following helper methods now take a Context as their first parameter:

  • pushTrackOpen(Context, PushMessage)
  • sendLocationUpdate(Context, Location)
  • associateUserWithInstall(Context, String)


  • Update ACRA to version 5


  • Prevent IllegalStateException from push intents started in the background


  • Add custom event tracking for analytics
  • Add session event recording for session analytics
  • Add user association helper method


  • Add default notification channel "General" for Android 8+
  • Fix reading of sender ID from merged manifest on some devices


  • Add crash reporting with ACRA


  • Add geolocation update helper method
  • Add locale & bundle to stats payload
  • Expose Kumulos.UninitializedException to allow catching this specific exception


  • Use OkHttp instead of Android AsyncHttpClient
  • Add config builder for initialization
  • Add default push notification small icon
  • Allow configuration of push small icon
  • Raise minimum API level to 14

Breaking Changes

  • Removed Kumulos.initWithAPIKeyAndSecretKey, use Kumulos.initialize instead
  • Removed ResponseHandler.onStart and ResponseHandler.onFinish
  • Callbacks are no longer called on the main thread

Migration Guide

In order to initialize Kumulos, you should change your initWithAPIKeyAndSecretKey call to the following:

KumulosConfig config = new KumulosConfig.Builder("API_KEY", "SECRET_KEY").build();
Kumulos.initialize(this, config);

Note this should be done in your application class's onCreate method as specified in the integration guide

To migrate any calls that update the UI from a callback, you should post the UI update back to the main thread as follows:"getThings", new ResponseHandler() {
    public void didCompleteWithResult(@Nullable Object result) {
        // Process the result
        String newText = ...;

        // Post UI updates back to the UI thread
        runOnUiThread(new Runnable() {
            public void run() {
                // Example update to UI component

For more information, see the Android developer guide


  • Prevent IllegalStateException when running on Android O


  • Guard against null actions in stats service


  • Guard against null actions in GCM registration


  • Add push notification URL open handling
  • Add background data push notification handling


  • Add PushSubscriptionManager to allow management of push channels & subscriptions
  • Make constructor of PushMessage package-visible instead of public


  • Allow overriding of ResponseHandler#onSuccess to access raw JSON response from API calls
  • Fix occasional authentication header issues from networking library


  • Fix usage of Kumulos from an arbitrary Thread in a Service where no Looper is bound
  • Add Kumulos#callSync method to perform blocking networking requests, suitable for use in background threads such as an IntentService
  • Fix NullPointerExceptions in some IntentServices
  • Ignore GCM payloads from other push services if used instead of Kumulos


  • Fix java.lang.NullPointerException in response handler if the JSON response fails to parse. In this case, ResponseHandler#didFailWithError will be called.
  • Remove logging of full response body in response parser to prevent cluttering LogCat when data fields are used


  • Move all classes to the package
  • Change debug log tags to match com.kumulos.*
  • Add support for push notifications with GCM
  • Bring minimum SDK to API level 11


  • Add session support to Android
  • Update to android-async-http 1.4.9


We would like to thank Aamir Latif, Alex Eskandari, and David Montiel for their contributions to the Android libraries.

Additionally we'd like to thank the Jackson JSON Parser and OkHttp projects for their excellent work on which we build our library.