Docs > Android SDK

Android SDK



Copy link to clipboard

In this integration guide we will take you through the most important steps of instrumenting your game with the GameAnalytics Android SDK.


Download & Installation

Copy link to clipboard


Unzip the files and add all files inside the GA/jar folder your Android Studio project in the relative paths specified below (where NAME_OF_MODULE could be ‘app’ or whatever your module is called).

  • NAME_OF_MODULE/libs/gameanalytics.jar Java library.


Unzip the files and import the gameanalytics.aar inside the GA/aar folder and import it by doing File->New->New Module…->Import .JAR/.AAR Package

Then select the .aar file where you downloaded it to and give it subproject name like ‘gameanalytics’ for example.

Using Maven Repository

Add this to your repositories (inside the project build.gradle):

maven { url '' }

and add this to your dependencies (inside the app build.gradle):

// use latest version instead version number in this example
compile 'com.gameanalytics.sdk:gameanalytics-android:3.2.2'

Configure Android Studio

Copy link to clipboard

To use the SDK in Android Studio follow the below steps:

  1. Install Google Play Services from the Android SDK manager (it is listed under the ‘Extra’ folder) and make sure to add its dependencies to the app module’s build.gradle and the app’s AndroidManifest.xml.
  2. Make sure compileSdkVersion is set to 24 in the app module’s build.gradle.
  3. Add permissions as seen in the code sample for AndroidManifest.xml (billing is only needed if IAP is used).

build.gradle (using jar)

android {
    compileSdkVersion 24
    // (more Android stuff)

dependencies {
    //... (other dependencies)

    compile ''
    compile ''

    //... (other dependencies)

build.gradle (using aar)

android {
    compileSdkVersion 24
    // (more Android stuff)

dependencies {
    //... (other dependencies)

    compile project(':gameanalytics')
    // assuming you have imported the aar and used 'gameanalytics' for its module name
    compile ''

    //... (other dependencies)

AndroidManifest.xml (only for jar)

<!-- Rest of AndroidManifest.xml -->
        <!-- Other application stuff -->
        <!-- Other application stuff -->
<!-- Rest of AndroidManifest.xml -->


Using Maven

In the project build.gradle file add the following to the repository section.

maven { url '' }

In the same file you should make sure the following settings are at least supporting version 24 for your app.

compileSdkVersion 24
buildToolsVersion "24.0.2"
targetSdkVersion 24

In the application build.gradle file add the following to the dependencies section.

// use latest version instead version number in this example
compile 'com.gameanalytics.sdk:gameanalytics-android:3.4.2'


Using C++

Copy link to clipboard

If you want to use the native Android SDK from C++ code there is a C++ wrapper. The required files are all located under the cpp folder. It includes the wrapper library for various architectures which you need to link against and a header file which should be included in the code where you need to call the SDK functions from. Before you call any of the main functions you need to call either:

GameAnalyticsJNI.nativeSetContext(activity); // from java code

// or

gameanalytics::jni_setContext(activity); // from C++ code

You also need to put place this inside your JNI_OnLoad function:


You must link against log and android libraries when building.


Storage Permissions

Copy link to clipboard

The SDK will use a database stored that can reach up to several MBs if the user keep being offline for longer periods of time while playing. When the user is back online it will attempt to send the events. Where the database is placed depends on permissions.


If the user’s device has Android API level 19 (Kitkat) or above, the SDK will try use context.getExternalCacheDir() (if it exists) to store its internal database.

If the device is less than Android API level 19 (Kitkat) and if READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions have been added the SDK will also try to use context.getExternalCacheDir().

If the none of the previous mentioned conditions have been met, then context.getCacheDir() will be used for storage of the internal database.



Copy link to clipboard

If your game can change orientation then each time the orientation changes it will cause the activity to destroy and be recreated. This will create a new session in the SDK. To avoid this it is very important to add the following line along with your activity entry in the AndroidManifest.xml file


Here is an example of an activity entry inside the AndroidManifest.xml

    android:label="@string/app_name" >
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />


IMEI plugin

Copy link to clipboard

For specific markets, IMEI and MEID can be used for attribution on Android.

This IMEI plugin respects the behavior of the GameAnalytics Android SDK in terms of device ID reading while additionally allowing the GameAnalytics SDK to read the IMEI and MEID values of a device.

Important: This GameAnalytics plugin is meant to be used only in apps that are NOT being published to the Google Play Store.

Add IMEI plugin to your app

If you are using Maven, add the following IMEI plugin dependency to your build.gradle file next to already existing dependency to Adjust SDK:

implementation 'com.gameanalytics.sdk:gameanalytics-android:+'
implementation 'com.gameanalytics.sdk:sdk:gameanalytics-android-imei:+'

You can also add GameAnalytics IMEI plugin as JAR file which can be downloaded from our Github page.

Add permission

Add the following permission, if it is not already present in your AndroidManifest.xml file:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Remember that after Android 6.0 it might be necessary to request app permission if the Android OS has not already been altered to avoid it.

Use the plugin

Finally, in order to read IMEI and MEID values, you need to call GAImei.readImei() before starting the SDK:


// ...

GameAnalytics.initializeWithGameKey(activity, "[game key]", "[secret key]");

You can call a method GAImei.doNotReadImei() to stop the SDK from reading IMEI and MEID values.



Copy link to clipboard

If your app uses proguard add these rules to your proguard rules:

-keep class  com.gameanalytics.sdk { *; }
-keep class  com.gameanalytics.sdk.** { *; }

-keep class  com.gameanalytics.sdk.GAPlatform { *; }
-keep class  com.gameanalytics.sdk.GAPlatform.** { *; }
-keep class** { *; }


initialize sdk

Copy link to clipboard


Using the SDK

Copy link to clipboard

Now we should be ready for adding code to activate the SDK!

  1. Configuration
  2. Initialization
  3. Adding events or changing dimensions

The configuration and initialization steps should be called inside the onCreate method of the Activity (e.g. class which is created first in the app.

Once step 1 & 2 is done you can add events at different parts of the game code where some relevant action is happening.

Remember to import the GameAnalytics package whenever you need to call the SDK.

import com.gameanalytics.sdk.*;



Copy link to clipboard

The available configuration options are:

  • build
  • available (allowed) custom dimensions
  • available (allowed) resource currencies
  • available (allowed) resource item types


Build is used to specify the current version of your game. Specify it using a string. Recommended to use a 3 digit version like [major].[minor].[patch]

// Set build version
 GameAnalytics.configureBuild("android 1.0.0");

User ID

The SDK will automatically generate a user id and this is perfectly fine for almost all cases.

Sometimes it is useful to supply this user_id manually – for example if you download raw data for processing and need to match your internal user id (could be a database index on your user table) to the data collected through GameAnalytics.

Note that if you introduce this into a game that is already deployed (using the automatic id) it will start counting existing users as new users and your metrics will be affected. Use this from the start of the app lifetime.


Specifying Allowed Values

For certain types it is required to define a whitelist containing possible unique values during the configuration phase.

When the SDK is being used (after initialization) only the specified values will be allowed. 20 values are allowed for each list.

Processing many unique dimension values can be taxing for our servers. A few games with a poor implementation can seriously increase our cost and affect stability. Games will be blocked if they submit too many unique dimension values. We have this configuration requirement to guide users into planning what dimension values can be used.

// Configure available virtual currencies and item types
GameAnalytics.configureAvailableResourceCurrencies("gems", "gold");
GameAnalytics.configureAvailableResourceItemTypes("boost", "lives");

// Configure available custom dimensions
GameAnalytics.configureAvailableCustomDimensions01("ninja", "samurai");
GameAnalytics.configureAvailableCustomDimensions02("whale", "dolphin");
GameAnalytics.configureAvailableCustomDimensions03("horde", "alliance");

Each resource currency string should only contain [A-Za-z] characters.

Enable/disable event submission

If you for GDPR purposes need to disable event submission you can call the following:


By default event submission is of course enabled. You will still receive configs if you have set any for your game even after disabling event submission.



Copy link to clipboard

To initialize the SDK you have two options.

1. With Activity

Since version 2.1.0 of the SDK we recommend that you call this function to initialize, using the apps main activity, and the game key and game secret for your game.

// Initialize
GameAnalytics.initializeWithGameKey(activity, "[game key]", "[secret key]");

2. Without Activity (calling it separately)

Alternatively you can use this function to initialize the SDK, using the game key and game secret for your game.

// Initialize
GameAnalytics.initializeWithGameKey("[game key]", "[secret key]");

Using this approach you MUST call the following function inside your Activity class in the onCreate method, before calling any of the configuration functions and before calling initializeWithGameKey or any other GameAnalytics function:


Don’t have any keys yet? Head over here and register your game at the GameAnalytics website!


Once initialize is called it will start the first session and automatically handle session changes based on activity events. Read more about sessions here including manual session handling.


Below is a common example of the code placed in the main activity class.


import com.gameanalytics.sdk.GameAnalytics;
import com.gameanalytics.sdk.GAPlatform;
import com.gameanalytics.sdk.StringVector;

public class MainActivity extends Activity
    // ... other code from your project ...

    protected void onCreate(Bundle savedInstanceState)
        // ... other code from your project ...

        // Enable log

        // Configure available virtual currencies and item types
        GameAnalytics.configureAvailableResourceCurrencies("gems", "gold");
        GameAnalytics.configureAvailableResourceItemTypes("boost", "lives");

        // Configure available custom dimensions
        GameAnalytics.configureAvailableCustomDimensions01("ninja", "samurai");
        GameAnalytics.configureAvailableCustomDimensions02("whale", "dolphin");
        GameAnalytics.configureAvailableCustomDimensions03("horde", "alliance");

        // Configure build version

        // Initialize
        GameAnalytics.initializeWithGameKey(this, "[game key]", "[secret key]");

        // ... other code from your project ...

    // ... other code from your project ...


event tracking

Copy link to clipboard



Copy link to clipboard

GameAnalytics supports 5 different types of events: Business, Resource, Progression, Error and Design.


Event Description
Business In-App Purchases supporting receipt validation on GA servers.
Resource Managing the flow of virtual currencies – like gems or lives.
Progression Level attempts with Start, Fail & Complete event.
Error Submit exception stack traces or custom error messages.
Design Submit custom event id’s. Useful for tracking metrics specifically needed for your game.


If you are new to GameAnalytics and our Events, please read our event guide here. You will get the most benefit of GameAnalytics when understanding what and how to track.



Copy link to clipboard

Business events are used to track (and validate) real-money transactions.

Some configuration is needed before receipt validation will be active.
Read information about validation and requirements for different platforms here.

Business Event with receipt

When submitting a Business Event supply the following from the IAP procedure.

  • signature (INAPP_DATA_SIGNATURE)

Read more about retrieving these needed fields at the Google documentation here.

Add a business event when an in-app purchase is completed.

GameAnalytics.addBusinessEventWithCurrency("USD", 1000, "item", "id", "cart", "[receipt]", "google_play", "[signature]");
Field Type Description Example
currency string Currency code in ISO 4217 format. USD
amount integer Amount in cents. 99 is 0.99$
itemType string The type / category of the item. GoldPacks
itemId string Specific item bought. 1000GoldPack
cartType string The game location of the purchase.
Max 10 unique values.
receipt base64 string The transaction receipt. Null allowed. null
store string App store used. Can only be google_play at the moment. google_play
signature base64 string The transaction receipt signature. Null allowed. null

If the receipt/signature is null (or is an invalid receipt) then it will be submitted to the GA server but will register as not validated.

Receipt JSON schema

    "orderId": "",
    "packageName": "",
    "productId": "",
    "purchaseTime": 1484080095335,
    "purchaseState": 0,
    "purchaseToken": ""

Example: Correct receipt information

It is possible to use code frameworks that handle IAP flow and of course every is done a bit differently This code example uses the sample code included in Android SDK found under this directory:

android_sdk_folder/extras/google/play_billing/samples/TrivialDrive/src/com/example/android/trivialdrivesample/util assumes you have downloaded Google Play Billing.

First of all the SkuDetails class has been modified slightly in this example to expose all information needed:

public class SkuDetails {
    String mItemType;
    String mSku;
    String mType;
    String mPrice;
    String mTitle;
    String mDescription;
    String mJson;
    String mCurrencyCode;
 int mPriceInCents;

    public SkuDetails(String jsonSkuDetails) throws JSONException {
        this(IabHelper.ITEM_TYPE_INAPP, jsonSkuDetails);

    public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException {
        mItemType = itemType;
        mJson = jsonSkuDetails;
        JSONObject o = new JSONObject(mJson);
        mSku = o.optString("productId");
        mType = o.optString("type");
        mPrice = o.optString("price");
        mTitle = o.optString("title");
        mDescription = o.optString("description");
   mCurrencyCode = o.optString("price_currency_code");
   mPriceInCents = o.optInt("price_amount_micros") / 10000;

    public String getSku() { return mSku; }
    public String getType() { return mType; }
    public String getPrice() { return mPrice; }
    public String getTitle() { return mTitle; }
    public String getDescription() { return mDescription; }
  public String getCurrencyCode() { return mCurrencyCode; }
 public int getPriceInCents() { return mPriceInCents; }

    public String toString() {
        return "SkuDetails:" + mJson;

public void onIabPurchaseFinished(IabResult result, Purchase purchase)
    // Code before business event...

    SkuDetails skuDetails = currentInventory.getSkuDetails(purchase.getSku());
    GameAnalytics.addBusinessEventWithCurrency(skuDetails.getCurrencyCode(), skuDetails.getPriceInCents(), "", purchase.getSku(), "", purchase.getOriginalJson(), "google_play", purchase.getSignature());

    // Code after business event...

// Current inventory is set after querying inventory
public void onQueryInventoryFinished(IabResult result, Inventory inventory)
    if (result.isFailure())
        // Handle failure
        // Other code...
        currentInventory = inventory;

The above example assumes you have setup onIabPurchaseFinished and onQueryInventoryFinished to called on the correct events.

Price (cents) and the currency ISO 4217 format

The amount is an integer with the price cent value. Also the currency has to conform to the ISO 4217 format. Make sure the price is in cents and that the currency strings are returned as required.

For more information regarding business events go here.



Copy link to clipboard

Resource events are used to register the flow of your in-game economy (virtual currencies) – the sink (subtract) and the source (add) for each virtual currency.

Before calling the resource event it is needed to specify what discrete values can be used for currencies and item types in the Configuration phase.

source (add) Gem currency from an in-app purchase.

GameAnalytics.addResourceEventWithFlowType(GAResourceFlowType.Source, "Gems", 400, "IAP", "Coins400");

sink (subtract) Gem currency to buy an item.

GameAnalytics.addResourceEventWithFlowType(GAResourceFlowType.Sink, "Gems", 400, "Weapons", "SwordOfFire");

sink (subtract) Gem currency to source (buy) some amount of another virtual currency (BeamBooster).

GameAnalytics.addResourceEventWithFlowType(GAResourceFlowType.Sink, "Gems", 100, "Boosters", "BeamBooster5Pack");

GameAnalytics.addResourceEventWithFlowType(GAResourceFlowType.Source, "BeamBooster", 5, "Gems", "BeamBooster5Pack");

sink (subtract) 3 BeamBooster currency that were used during a level.

GameAnalytics.addResourceEventWithFlowType(GAResourceFlowType.Sink, "BeamBooster", 3, "Gameplay", "BeamBooster5Pack");
Field Type Description Example
flowType enum A defined enum for sourcing and sinking resources. GAResourceFlowType.Sink
currency string The resource type/currency to track. Has to be one of the configured available resource currencies.
This string can only contain [A-Za-z] characters.
Gems, BeamBoosters, Coins
amount float Amount sourced or sinked. 0 or negative numbers are not allowed. 100.0
itemType string For sink events it can describe an item category you are buying (Weapons) or a place (Gameplay) the currency was consumed. For source events it can describe how the currency was gained. For example “IAP” (for in-app purchase) or from using another currency (Gems). Has to be one of the configured available itemTypes. Weapons, IAP, Gameplay, Boosters
itemId string For sink events it can describe the specific item (SwordOfFire) gained. If consumed during Gameplay you can simply use “Consumed”. For source events it describes how the player got the added currency. This could be buying a pack (BoosterPack5) or earned through Gameplay when completing a level (LevelEnd). BoosterPack5, SwordOfFire, LevelEnd, Coins400

Be careful to not call the resource event too often! In a game where the user collect coins fairly fast you should not call a Source event on each pickup. Instead you should count the coins and send a single Source event when the user either complete or fail the level.

For more information about the resource event go here.



Copy link to clipboard

Progression events are used to track attempts at completing some part of a game (level, area). A defined area follow a 3 tier hierarchy structure (could be world:stage:level) to indicate what part of the game the player is trying to complete.

When a player is starting a progression attempt a start event should be added.
When the player then finishes the attempt a fail or complete event should be added along with a score if needed.

Add a progression start event.

GameAnalytics.addProgressionEventWithProgressionStatus(GAProgressionStatus.Start, "world01", "stage01", "level01");

It is not required to use all 3 if your game does not have them.

  • progression01
  • progression01 and progression02
  • progression01 and progression02 and progression03
Field Type Description Example
progressionStatus enum Status of added progression GAProgressionStatus.Start GAProgressionStatus.Fail GAProgressionStatus.Complete
progression01 string Required progression location. World01
progression02 string Not required. Use if needed. Stage01
progression03 string Not required. Use if needed. Level01
score integer An optional score when a user completes or fails a progression attempt. 1023

For more information on the progression event go here.



Copy link to clipboard

Used to track custom error events in the game. You can group the events by severity level and attach a message. By default the SDK will automatically send error events for uncaught exceptions for more information on this and how to disable it click here.

To add a custom error event call the following function:

GameAnalytics.addErrorEventWithSeverity(GAErrorSeverity.GAErrorSeverityDebug, "Something went bad in some of the smelly code!");
Field Type Description Example
severity enum Severity of error GAErrorSeverity.GAErrorSeverityDebug
message string Error message (can be null) “Error when entering level12”

For more information on the error event go here.



Copy link to clipboard

Every game is special. Therefore some needed events might not be covered by our other event types. The design event is available for you to add your own event-id hierarchy.

Please note that custom dimensions and progression filters will not be added on design and error events. Therefore you cannot (at the moment) filter by these when viewing design or error metrics.

To add a design event call the following method.


It is also possible to add a float value to the event. This will (in addition to count) make the mean and sum aggregation available in the tool.

GameAnalytics.addDesignEventWithEventId("BossFights:FireLord:KillTimeUsed", 234);
Field Type Description Example
eventId string The eventId is a hierarchy string that can consist of 1-5 segments separated by ‘:’. Each segment can have a max length of 32. The segments can be written only with a-zA-Z0-9 characters. “StartGame:ClassLevel1_5”, “StartGame:ClassLevel6_10”
value float A float event tied to the eventId. Will result in sum & mean values being available. 34.5

It is important to not generate an excessive amount of unique nodes possible in the event hierarchy tree.

A bad implementation example. [level_name]:[weapon_used]:[damage_done]

level_name could be 100 values, weapon_used could be 300 values and damage_done could be 1-5000 perhaps. This will generate an event hierarchy with:

100 * 300 * 5000 = 1.5M possible nodes. This is far too many. Also the damage should be put as a value and not in the event string. The processing will perhaps be blocked for a game doing this and cause other problems when browsing our tool.

The maximum amount of unique nodes generated should be around 10k.

Please read our event guide here. You will get the most benefit of GameAnalytics when understanding what and how to track.


command center

Copy link to clipboard



Copy link to clipboard

Product Update – Remote Configs

We are excited to announce the upcoming release of Remote Configs – our new tool that will replace Configs.

Remote Configs will be released in October 2019 with a new user interface and updated SDKs.

You can continue to use the current version of Configs. We will soon be sharing more information and our migration guide.

If you have any questions, please don’t hesitate to reach out.

Register to events for whenever the Config (CommandCenter) is updated with new values:

public class MainActivity extends Activity implements ICommandCenterListener
    public void onCommandCenterUpdated()
        // add your code here

    protected void onCreate(Bundle savedInstanceState)

To manual check if Configs is ready (has been populated with values) you can call this:

    // the command center is ready, add your code here

To get values out of a populated Config use the following methods:

// Without custom default value (using normal default value)
String value = GameAnalytics.getCommandCenterValueAsString("key");
// With custom default value
String valueWithCustomDefaultValue = GameAnalytics.getCommandCenterValueAsString("key", "myDefaultValue");

If the specified key is not found in the Config it will return the default value either “normal” or “custom” default value.

More info Configs please see here


additional calls

Copy link to clipboard


Custom Dimensions

Copy link to clipboard

GameAnalytics support the use of 3 custom dimensions.

  • Custom01
  • Custom02
  • Custom03

During the game it is possible to set the active value for each custom dimension dynamically. Once a dimension is set it will be persisted across sessions/game-start and automatically be added to all event categories. Remember you have to set the custom dimensions before initialzing the SDK (but after setting the available custom dimensions) to be able to add the dimensions to the first session start event.

Setting each custom dimension.


To reset a set custom dimension simply set it to empty string or null:

Field Type Description Example
customDimension string One of the available dimension values set in the configuration phase. Will persist cross session. Set to null to reset. ninja

Read more about custom dimensions here.


User Information

Copy link to clipboard
During the game it is possible to set information about your users that will then be annotated to all other events.

  • gender
  • Facebook ID
  • birthyear (age)

These user values will persist cross session/game-launch. Set them to nil to reset.

Set gender.


Set birthyear.


Set Facebook ID.

Field Type Description Example
gender string Gender of player. female, male
birthYear integer The year the player was born. 1980
facebookId string Facebook Id of the player. 123456789012345


Error Reporting

Copy link to clipboard

By default the SDK will automatically send error events for uncaught exceptions. This can be disabled by calling this before the SDK has been initialized:


If you are using other crash/error reporting services like for example Crashlytics together GameAnalytics’ automatic error reporting it can in some cases give problems but the SDK makes sure to call any error handlers set prior to GameAnalytics error handler.


debug & verify

Copy link to clipboard



Copy link to clipboard

The SDK is designed to be as silent as possible and use very few resources. You will therefore not get much information by default in your development console.

We have 2 different debug log types that can be enabled / disabled (at any time).

  • info log
  • verbose log

Info log

Short messages will be output when enabled explaining when some action is being performed by the SDK. Sometimes cropping text / values to make it more readable.

Enable info log when implementing the SDK – remember to turn it off in production!

 Info/GameAnalytics: Add DESIGN event: {eventId:someEvent, value:0}
 Info/GameAnalytics: Add DESIGN event: {eventId:someOtherEvent, value:100}
 Info/GameAnalytics: Add ERROR event: {severity:info, message:This is some in}

Verbose Log

Console output when each event is added (all fields) in JSON string format. This is the data being submitted to the GA servers for each event.

Enable verbose log when troubleshooting events.


This can result in a lot of text. When troubleshooting/debugging events it is therefore recommended to enable/disable when performing the action that need inspection.

Troubleshooting example.

 // enable verbose log
 // add event you need to troubleshoot / inspect
 GameAnalytics.addDesignEventWithEventId("Some:Event", 100);
 // disable verbose log 


Copy link to clipboard

Enable the Info Log to verify that events are being sent from your game project without any issues being reported.

Events submitted should register after a minor delay in our realtime dashboard in the GameAnalytics tool.

Read more about the realtime dashboard and our data processing.


how does it work?

Copy link to clipboard


Session Handling

Copy link to clipboard

By default the SDK will handle session start/end automatically, but it is also possible to manually control this yourself.

Be aware that the initialization will always automatically start the first session even with manual session handling.

If you are using ads in your game there is a big possibility that the onPause() and onStop() events will be triggered when the ads are showing which will interfere with the session length for information on how to fix this to look here

Automatic session handling

The automatic session handling will track the focused time the user is spending in your game – from game launch to the user leaving the game.

session start

On Android a new session will start once the game is launched or when the app is resuming if there is no current session.

session end

A session will end once the game is going to homescreen (or is not visible anymore).

It will end the session at once if the application received the onStop event from the game activity.

Manual session handling

If you just want to be in control when to start and end sessions) you can enable/disable manual session handling by calling this at any given time:


You will then need to call endSession and startSession at the appropriate times.

With manual session handling it is recommended to also call endSession when the game activity event onStop is fired. This will ensure a correct session close when users click the home or on/off button.



This will end a session if:

  • manual session handling is enabled
  • a session is active
  • SDK is initialized (initialize will start a session automatically)



This will start a new session if:

  • manual session handling is enabled
  • SDK is initialized (initialize will start a session automatically)

If a current session is active then it will end the current session and start a new one.

Handling ads and preserve correct session length

Ads will most likely trigger onPause() and onStop() which will interfere with the session length of the game. To prevent this you need to use manual session handling at least when you are about to show ads. Here is an example using AdColony but it should easily apply to ad SDKs with the own events surrounding the ad (on showing and on finished ad):

public void onAdColonyAdAttemptFinished(AdColonyAd ad)

public void onAdColonyAdAttemptFinished(AdColonyAd ad)

If you are already using manual session handling from the beginning of your game then you don’t need to worry about this.

Behind the scenes

This is what happens when the session is starting or ending.

Session start

  1. Generate new session.
  2. Add a session start event (a “user” event).
  3. Start the periodic activation of submitting queued events.
  4. Next event submit will fix potential missing session_end from earlier sessions.

Session end

  1. Stop the periodic activation of submitting queued events.
  2. Add a session_end event.
  3. Submit queued events.


Event Queue

Copy link to clipboard

Whenever an event is added (and validated) it will be added to a local database queue.


Every 8 seconds the SDK will start a task for submitting queued events since last submit. This processing is done in a separate low-priority thread that will have minimum impact on performance. The payload is gzipped and will therefore only consume a small amount of bandwidth.


When a device is offline the events are still added to the queue. When the device is online it will submit.


Thread Handling

Copy link to clipboard

For the Android platform almost every piece of this code is run using a dedicated low-priority serial thread queue to avoid UI lag or sudden performance spikes. The queue will execute each task sequentially. If the SDK add several tasks to the queue then each will be executed in turn. A task could be adding an event or submitting all queued events.

Consider this example with 3 calls.

// Configure build version
GameAnalytics.configureBuild("alpha 0.1.0");
// Initialize
GameAnalytics.initializeWithGameKey("12341234123412341234123412341234", "1234123412341234123412341234123412341234");
// Add Design event

The configureBuild is required to be called before initialize is completely finished. The design event call is required after initialize is finished. The queuing will make sure that each task is completely finished before proceeding to the next one.

Contact support

We’ll get back to you ASAP.

Report a bug

Let us know more details.