Integrating the Tapstream Android SDK

First, get the latest Android SDK.

Get the latest Android SDK

Adding the SDK to your project

Google's Play Store approval process requires apps that track their users via hardware IDs to use the Google Advertising ID alone, and no other hardware identifiers. To facilitate this, your app must:

  • include the Google Play Services SDK

  • include a privacy policy disclosing your use of the Google Advertising ID

Submitting your app to the Google Play Store without the Google Play Services SDK, or without a privacy policy disclosing your use of the Google Advertising ID, may result in its rejection from the Play Store.

Adding the INTERNET permission

  • Add the following permissions to your AndroidManifest.xml, as children of the <manifest> element:

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

Configuring the Android broadcast receiver

Tapstream uses an Android broadcast receiver to perform accurate attribution. Configuring Tapstream's broadcast receiver is a requirement.

  • Add the following XML fragment to your AndroidManifest.xml, as a child of the <application> element:

<receiver android:name="com.tapstream.sdk.ReferrerReceiver" android:exported="true" >
    <intent-filter>
        <action android:name="com.android.vending.INSTALL_REFERRER" />
    </intent-filter>
</receiver>

Note: Only one declared BroadcastReceiver will receive the INSTALL_REFERRER intent. Ignore the following paragraph if you only have a single BroadcastReceiver for INSTALL_REFERRER.

If you want more than one receiver to get the INSTALL_REFERRER intent, you should remove their declarations from your AndroidManifest.xml file and replace them with your own custom BroadcastReceiver. The custom broadcast receiver should explicitly instantiate and call onRecieve() for each of the receivers that need the referrer data. Here's an example implementation of a custom broadcast receiver that captures and delivers the INSTALL_REFERRER event to both Tapstream and Google Analytics:

public class ReferrerReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        new com.tapstream.sdk.ReferrerReceiver().onReceive(context, intent);
        new com.google.analytics.tracking.android.CampaignTrackingReceiver().onReceive(context, intent);
    }
}

Configuring Proguard

If you are using Proguard, you will need to add the following line to your proguard.cfg:

-keep class com.google.android.gms.ads.identifier.** { *; }

Since Tapstream uses reflection to interact with the advertising identifier classes, Proguard will not be able to determine this dependency and may remove them from your build, preventing Tapstream's SDK from reporting the Google Advertising ID.

Importing and initializing the SDK

In your project's main activity file, import the Tapstream SDK:

import com.tapstream.sdk.*;

Then, in the onCreate method of your main activity, create the Tapstream singleton with your account name and SDK secret:

Config config = new Config("ACCOUNT_NAME", "SDK_SECRET");
Tapstream.create(getApplication(), config);

Collecting hardware identifiers

Tapstream will automatically collect the Google Advertising ID, but only if you have integrated the Google Play Services SDK into your app. See the Google Play Services integration instructions.

Firing SDK events

The SDK will fire two types of events automatically:

  • An install event, the first time the app runs
  • An open event, every time the app runs.

The install event is called [platform]-[appname]-install, and the open event is called [platform]-[appname]-open, where [platform] is the device's platform (iOS, Android, etc.) and [appname] is your app's shortname.

Additional SDK events

You may fire additional events from anywhere in your code. This is useful for tracking engagement events, user progress, and other LTV metrics.

Firing an event is simple and can be done like this:

Event e = new Event("created-account", false);
Tapstream.getInstance().fireEvent(e);

This example fires an event called created-account, but you may call your events anything you like. Event names are case insensitive.

The Tapstream SDK is threadsafe, so you may fire events from any thread you wish.

Firing events with custom parameters

Tapstream also allows you to attach key/value pairs to your events. The keys and values must be no more than 255 characters each (once in string form).

Custom event parameters and values are available via the Tapstream postback system, the Reporting tab of the Tapstream dashboard, and the Tapstream API suites.

In the following example, an event called level-complete with custom parameters for score and skill is fired.

Tapstream tracker = Tapstream.getInstance();

Event e = new Event("level-complete", false);
e.setCustomParameter("score", 15000);
e.setCustomParameter("skill", "easy");
tracker.fireEvent(e);

Global custom event parameters

You may find that you have some data that needs to be attached to every single event sent by the Tapstream SDK. Instead of writing the code to attach this data in each place that you send an event, add these data values to the global event parameters member of the config object. The parameters in this dictionary will automatically be attached to every event, including the automatic events fired by the SDK.

For example:

Config config = new Config();
config.setGlobalEventParameter("user_id", "92429d82a41e");

Tracking IAB events

If you wish to track in-app purchases made by your users, you will need to fire a special purchase event. To construct a purchase event, you will need two pieces of data: the JSON describing the purchase, and the JSON describing the properties of the SKU in question. How and where you acquire this JSON data will depend on how you have implemented in-app billing. The following abridged example assumes that you have used the classes provided in the "Trivial Drive" sample shipped with the Android SDK.

public class MainActivity extends Activity {

    ...

    private IabHelper mHelper;
    private IabHelper.QueryInventoryFinishedListener mGotInventoryListener;
    private IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener;

    // This is where we will store the inventory information
    // received by the QueryInventoryFinishedListener above.
    private Inventory mInventory;

    ...

    protected void onCreate(Bundle savedInstanceState) {

        // Init Tapstream, etc
        ...


        // Create the IAB helper, providing your public key, as in the Trivial Drive sample
        mHelper = new IabHelper(this, pubKey);

        mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
            public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
                if (result.isFailure()) {
                    Log.d(TAG, "QueryInventory failed: " + result);
                } else {

                    // Important:
                    // Store the inventory in a member variable so we will have access to this data
                    // later when a purchase succeeds.
                    mInventory = inventory;

                    ...
                }
            }
        };

        mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
            public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
                if (result.isFailure()) {
                    Log.d(TAG, "IabPurchase failed: " + result);
                } else {

                    ...

                    // Purchase success, fire a Tapstream purchase event.
                    // We need to provide the product details json that we got when we first queried our inventory.
                    // Fortunately, we stored the Inventory instance in a member variable so we can still access it.
                    SkuDetails skuDetails = mInventory.mSkuMap.get(purchase.getSku());
                    try {
                        Event event = new Event(purchase.mOriginalJson, skuDetails.mJson, purchase.getSignature());
                        Tapstream.getInstance().fireEvent(event);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        ...

    } // end of onCreate

    ...

} // end of MainActivity

Tracking other types of purchase events

If your app allows users to make purchases that are not processed by the standard Android in-app billing system, you may want to fire completely custom purchase events. For example:

// Arguments are: transactionId, productId, quantity, priceInCents, currencyCode
Event event = new Event("3da541559918a", "com.myapp.coinpack100", 1, 299, "USD");
Tapstream.getInstance().fireEvent(event);

If you don't know or cannot provide the price and currency of the transaction in your app, you can omit these details. The value of the purchase event will then be determined by the value that you set in your Tapstream dashboard.

For example:

// Arguments are: transactionId, productId, quantity
Event event = new Event("3da541559918a", "com.myapp.coinpack100", 1);
Tapstream.getInstance().fireEvent(event);

Verifying your SDK integration

Once you've completed the integration, you can log in to your Tapstream dashboard and verify that your integration is delivering events to Tapstream. Run your app and visit the Events section of the dashboard. You should now see at least one event, like platform-myapp-install.

The SDK status light in the header of the dashboard will now be green to indicate that Tapstream has received an event from your integration.

Controlling logging

The log output of Tapstream can be redirected (or quelled) by providing a handler to receive the messages.

Make sure to define the logging behavior before you initialize the SDK.

Here's how you might redirect Tapstream messages to a custom logging system:

Logging.setLogger(new Logger() {
    @Override
    public void log(int logLevel, String message) {
        MyCustomLoggingSystem(message);
    }
});

Changing hardware ID collection

If you prefer that Tapstream not collect the Google Advertising ID, you can opt-out by adding the following to your Tapstream configuration. (Note that this is not recommended.)

// These hardware identifiers will be automatically collected and sent
// unless you opt-out by setting them to false, as shown below. This is NOT recommended.

config.setCollectAdvertisingId(false);

If you need to collect deprecated hardware IDs, you can add them to your config as shown here:

// These hardware identifiers are optional and are not collected automatically.
// If you wish to send them, you must opt-in by providing values, as shown here:
config.setOdin1("<ODIN-1 value goes here>");
config.setOpenUdid("<OpenUDID value goes here>");
config.setWifiMac("<WiFi MAC value goes here>");
config.setDeviceId("<Device ID goes here>");
config.setAndroidId("<Android ID goes here>");

Changing the default events

Automatic install and open events can be renamed, and automatic install, open, and iOS purchase events may suppressed entirely by modifying the config object that you used to instantiate the SDK. For example, if you wanted to rename the install and open events, you would set the config object like this:

config.setInstallEventName("my-install-event");
config.setOpenEventName("my-open-event");

If you wanted to suppress the automatic install, open, and iOS purchase events, you would set the config object like this:

config.setFireAutomaticInstallEvent(false);
config.setFireAutomaticOpenEvent(false);