Android SDK: Advanced Options

Singular Android SDK
Download
Singular Android SDK version 12.1.1 (see Change Log)
Compatibility

Android 4.0.1 (Ice Cream Sandwich) and higher

  • The SDK uses the device's Android Advertising ID for devices that use Play Store version 4. For older devices, the SDK uses the Android ID.
  • The latest version of the SDK has not been tested with Android versions older than 4.0.1.
Sample App Review our sample app for an example of a complete SDK integration based on best practices.
Integration Guides
  1. Basic Integration
  2. Tracking Events and Revenue
  3. Implementing Deep Links
  4. Advanced Options

 

Creating Short Referrer Links

Note: This functionality is available in SDK version 12.1.1+. Once created, short links remain active for 30 days.

Use short links to transform long, parameter-filled Singular Links into shorter and more secure links that are convenient for sharing.

Typically, you will want to create short links dynamically so that your app's users can share them with friends to invite them to use the app.

To create a short link, you need:

  • A Singular Link that leads to your app download (see the Singular Links FAQ).
  • Any parameters you want to add to the link dynamically (see Tracking Link Parameters for the list of options).
  • The name and ID of the referring user, if you want to be able to track new app installs back to the user who shared the link.

Use the createReferrerShortLink method to create a short link as in the example below.

// Create a JSON object to add parameters to the Singular Link (if they don't exist in the link URL yet)
JSONObject params = new JSONObject();       
try {
      params.put("channel","sms");
      params.put("another parameter","parameter value");
} catch (JSONException e) {
      e.printStackTrace();
}

Singular.createReferrerShortLink (
  "https://sample.sng.link/D52wc/cuvk?pcn=test", // The original Singular Link URL
  "Referrer Name",
  "Referrer ID",
  params,
  new ShortLinkHandler() { 
    @Override
      public void onSuccess(final String shortLinkURL) {
        view.post(new Runnable() {
          @Override
          public void run() {
            // Add your share logic here
          }   
        });
      }

@Override public void onError(final String error) { view.post(new Runnable() { @Override public void run() { // Logic to retry/abort/modify the params passed to
// the function, based on the cause of the error } }); } });

Adding Ad Revenue Attribution Support

Note: Starting in version 11.0.0, Singular added the option to set up ad revenue attribution through the Singular SDK.

Ad revenue attribution can still be set up the old way, using API calls, without updating the Singular SDK in your apps.

To add ad revenue attribution support in the Singular SDK:

  1. If you haven't done so yet, contact your Singular Customer Success Manager to enable ad revenue attribution for your account.
  2. Update to the latest version of the Singular SDK.
  3. Add the appropriate code snippet to your Singular SDK integration, depending on the mediation platform you use for ad revenue data.
AdMob AppLovin MAX IronSource Other (Generic)
// Note: This is a beta feature. Contact Admob to have it enabled.

RewardedAd mRewardedAd;

@Override
public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
mRewardedAd = rewardedAd;

// Set paid event listener
mRewardedAd.setOnPaidEventListener(new OnPaidEventListener() {

@Override
public void onPaidEvent(AdValue adValue) {
AdValue impressionData = adValue;

SingularAdData data = new SingularAdData("AdMob", impressionData.getCurrencyCode(),
impressionData.getValueMicros()/1000000.0);

data.withAdUnitId(mRewardedAd.getAdUnitId()).
withNetworkName(mRewardedAd.getResponseInfo().getMediationAdapterClassName());

Singular.adRevenue(data);
}
});
}

Note: Pass currency as a three-letter ISO 4217 currency code, e.g., "USD," "EUR", "INR".

Uninstall Tracking

To enable uninstall tracking for your Android app, first configure the app in the Singular platform as detailed in Setting Up Uninstall Tracking. Then follow the instructions below.

Note: Google deprecated the GCM APIs in April 2018. Use FCM for uninstall tracking.

Enabling Uninstall Tracking Using Firebase Cloud Messaging (FCM)

1. Integrate with FCM:

To track uninstalls, you can use the services of the Firebase Cloud Messaging (FCM) platform. If you are not already using FCM follow Google's instructions on how to Set up a Firebase Cloud Messaging client app on Android.

FCM Requirements ( source )

FCM clients require devices running Android 4.1 or higher that also have the Google Play Store app installed, or an emulator running Android 4.1 with Google APIs. Note that you are not limited to deploying your Android apps through the Google Play Store.

Users/devices who are not running on supported versions of Android will not be available for Singular uninstall tracking.

2. Update the AndroidManifest.xml File:

Update your AndroidManifest.xml file to add the necessary intent filter for your app (replace MyFirebaseMessagingService with your class that implements the Firebase Service):

<service android:name=".java.MyFirebaseMessagingService"
android:exported="false">
    <intent-filter>
        action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

3. Register and Send the FCM Device Token:

Finally, set the FCM device token after your SingularConfig is initialized in OnCreate(), as follows:

Singular.setFCMDeviceToken(String fcmDeviceToken);

Adding Global Properties

The Singular SDK lets you define custom additional properties that you want to send to the Singular servers with every session and event sent from the app. These properties can represent any information you want about the user, the app mode or status, or anything else. Once you set these properties, they are available as dimensions in your reports and you can use them to break down your data.

For example, if you have a gaming app, you can define a property called "Level" and set it initially to "0". Any session and event sent from the app will be sent with "Level": "0". Once the user levels up you reset the property to "1" and so on. You can then get your reports, including sessions, event counts, and revenue data, broken down by user level.

  • You can define up to 5 global properties.
  • They persist between app runs (with the latest value you gave them) until you unset them or the user uninstalls the app.
  • Each property name and value can be up to 200 characters long. If you pass a longer property name or value, it will be truncated to 200 characters.
  • Global properties are accessible and available in user-level exports and postbacks. In the future, aggregate reporting support will be added. Let your Singular customer success manager know if you have any questions, or are interested in updates to global properties support!

Setting Global Properties through SingularConfig

You can use the withGlobalProperty method to set global properties through SingularConfig before initializing the SDK.

Note that since global properties and their values persist between app runs, the property that you are setting may already be set to a different value. Use the overrideExisting parameter to tell the SDK whether to override an existing property with the new value or not.

withGlobalProperty Method 
Description Set a global property.
Signature withGlobalProperty(String key, String value, boolean overrideExisting)
Usage Example
// Set two global properties and override any existing values
SingularConfig config = new SingularConfig("SDK KEY", "SDK SECRET")
  .withGlobalProperty(“MyProperty”, “MyValue”, true)
  .withGlobalProperty(“AnotherProperty”, “AnotherValue”, true);

Setting Global Properties After Initialization

Use the following methods to set, unset, and retrieve global properties at any time in the app's run.

Singular.setGlobalProperty Method
Description

Set a global property to a given value.

Notes:

  • If the property does not exist yet, and there are already 5 other global properties, the property will not be added.
  • If the property has already been set, the overrideExisting parameter determines whether the existing value will be overridden.
  • The method returns true if the property was set successfully or false otherwise.
Signature public static bool setGlobalProperty(String key, String value, boolean overrideExisting)
Usage Example
boolean result = Singular.setGlobalProperty(“MyProperty”, “MyValue”, true);
Singular.getGlobalProperties Method
Description Retrieve all the global properties and their current values as a Map.
Signature public static Map<String, String> getGlobalProperties()
Usage Example
Map<String, String> map = Singular.getGlobalProperties();
Singular.unsetGlobalProperty Method
Description Remove a global property.
Signature public static void unsetGlobalProperty(String key)
Usage Example
Singular.unsetGlobalProperty(“MyProperty”);
Singular.clearGlobalProperties Method
Description Remove all global properties.
Signature public static void clearGlobalProperties()
Usage Example
Singular.clearGlobalProperties();

Collecting the Install Referrer on Older Devices

Note: Google is deprecating the install_referrer intent broadcast. See: Still Using InstallBroadcast? Switch to the Play Referrer API by March 1, 2020

The install referrer is Singular's most accurate tool to determine attribution, in addition to helping Singular detect and analyze fraud attempts. It is an identifier provided by the Google Play Store that points to the ad that the user clicked on before installing the app.

On devices that have the latest version of the Google Play Store, the Singular SDK collects the install referrer value automatically (since Singular is integrated with the latest Google Play Referrer API).

To collect the install referrer on older devices:

If you have an existing install referrer receiver:

Chances are your app already has a BroadcastReceiver that receives the INSTALL_REFERRER from Android.

If so, just go into the BroadcastReceiver's onReceive method and add the following line:

new SingularInstallReceiver().onReceive(context, intent);

For example, if your existing receiver is called MyCustomInstallReceiver, it should look as follows:

public class MyCustomInstallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Pass install referrer information on to Singular
        new SingularInstallReceiver().onReceive(context, intent);
        // ...
    }
}

If there is no other install referrer receiver:

If you don't have any install referrer receiver in your app, you can let the Singular SDK register the only receiver simply by adding the following to your <application> tag in your manifest file:

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

Managing Sessions

For Android API 14 (Ice Cream Sandwich) and above, the Singular SDK can handle session management automatically. If your app's minSdkVersion is 14 or higher, no additional configuration is required for session management.

Modifying the Session Timeout

By default, if the app runs in the background for 60 seconds or more before returning to the foreground, the SDK registers a new session.

To change the timeout value, use withSessionTimeoutInSec(<timeout in seconds>) in SingularConfig before initializing the SDK.

For example:

// Set the session timeout to 120 seconds
SingularConfig config = new SingularConfig("SDK KEY", "SDK SECRET")
.withSessionTimeoutInSec(120); 

Manual Session Management

If your app's minSdkVersion is below 14, you need to manage sessions manually by calling the Singular's SDK two session-handling methods, onActivityPaused and onActivityResumed, from each of your activities.

Note: If you have a custom common base activity class from which all other activities are derived, you can place these calls to onActivityResumed and onActivityPaused in the common activity's "onResume and onPause methods.
Singular.onActivityResumed Method
Description Call this method inside the activity's onResume method to manage the Singular session.
Signature public static void onActivityResumed()
Usage Example
@Override
protected void onResume() {
    super.onResume();
    Singular.onActivityResumed();
    .... //other code if any
}
Singular.onActivityPaused Method
Description Call this method inside the activity's onPause method to manage the Singular session.
Signature public static void onActivityPaused()
Usage Example
@Override
protected void onPause() {
    super.onPause();
    Singular.onActivityPaused();
    .... //other code if any
}

Using the JavaScript Interface

Singular provides a JavaScript interface that you can use in order to call Singular from within javaScript code in your app.

For example, if you set up the JavaScript interface, you can send events to Singular from JavaScript code as follows:

SingularInterface.event('event');
SingularInterface.event('test',
JSON.stringify({"a1":"bar", "a2":"boo", "a3":"baz"}));

The interface supports the following SDK methods:

  • setCustomUserID
  • unsetCustomUserID
  • event
  • revenue

Enabling the JavaScript Interface

To enable the JavaScript interface, add the following lines of code to your main activity, where "myWebView" is the name of your webview.

SingularJSInterface singularJSInterfaceInstance = new SingularJSInterface(this);
singularJSInterfaceInstance.setWebViewId(R.id.webview);
myWebView.addjavascriptInterface(singularJSInterfaceInstance, "SingularInterface");
Notes:
  • If you have more than one webview, do this for each one.
  • We recommend placing the code in the onCreate method of your application.

Your onCreate method may look like this:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    WebView myWebView = (WebView) this.findViewById(R.id.webview);
    WebSettings webSettings = myWebView.getSettings();
    webSettings.setjavaScriptEnabled(true);
    myWebView.loadUrl("file:///android_asset/index.html");

    SingularConfig config = new SingularConfig("SDK KEY", "SDK SECRET");
    Singular.init(this, config);
    SingularJSInterface singularJSInterfaceInstance = 
        new SingularJSInterface(this);
    singularJSInterfaceInstance.setWebViewId(R.id.webview);
    myWebView.addjavascriptInterface(singularJSInterfaceInstance,
        "SingularInterface");
}

Collecting the OAID (Open Advertising ID)

In countries that do not use Google Play, Android devices do not have a Google Advertising ID (GAID, also called AIFA in Singular). Instead, the devices may offer an identifier called OAID (Open Advertising Identifier) that can be used to track sessions and events coming from the device.

OAID is currently offered on devices by Huawei and by brands that belong to the Mobile Security Alliance (MSA).

For your app to collect the OAID, you first have to integrate the MSA SDK and Huawei OAID SDK. You need to integrate both SDKs to be able to collect the OAID on all the platforms that offer it.

Then, to tell the Singular SDK to use OAID for tracking, add a call to withOAIDCollection in the config object before initializing Singular.

SingularConfig config = new SingularConfig("SDK KEY","SDK SECRET")
    .withOAIDCollection();
Singular.init(context, config);

The Singular SDK will automatically detect if the device has an OAID as well as which OAID SDK should be used to collect the identifier.

Collecting the IMEI Number

If your app is offered in countries that do not use Google Play, devices do not have a Google Advertising ID. In this case, you may want to collect the device IMEI (International Mobile Equipment Identity) instead.

Note: If you use Google Play Services, you should not collect the IMEI number because it's a violation of the Google Play service agreement.

To collect the IMEI number:

  1. Add the android.permission.READ_PHONE_STATE permission to the app's AndroidManifest.xml file:

    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
  2. Add code like the following to fetch the device's IMEI number:

    TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
    
    String imei = null;
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        imei = telephonyManager.getImei();
    } else {
        imei = telephonyManager.getDeviceId();
    }

To send the IMEI number to Singular, use one of the following methods:

  • Recommended: Set the IMEI number in SingularConfig using withIMEI before you initialize the Singular SDK, as in the following example. This makes the IMEI number available to Singular from the very first session.

    SingularConfig config = new SingularConfig("SDK KEY","SDK SECRET")
    .withIMEI("537769845792516"); Singular.init(context, config);
  • To set the IMEI number at any point in the code after the SDK initialization, call setIMEI.
Singular.setIMEI Method
Description Send the device's IMEI number to Singular.
Signature public void setIMEI(string IMEIString)
Usage Example
Singular.setIMEI(IMEIString);

Complying with Data Privacy Laws

Singular provides privacy-safeguarding functionality to help you cooperate with any partners who may be complying with consumer privacy laws such as GDPR and CCPA (California Consumer Privacy Act). These partners want to be notified if the end-user has consented to share their private information.

If you have implemented a way to ask users for consent to share their information, use the limitDataSharing method to notify Singular of the user's choice:

  • Use Singular.limitDataSharing(false) to indicate that the user consented (opted in) to share their information.
  • Use Singular.limitDataSharing(true) if the user did not consent.

Singular will pass this information on to partners who require it in order to comply with relevant regulations.

Note: The use of the method is optional, but there may be attribution information that the partner will share with Singular only if specifically notified that the user has opted in.

Singular.limitDataSharing Method
Signature Singular.limitDataSharing(boolean shouldLimitDataSharing)
Description Notify Singular of user consent (opt-in) for sharing private data.
Usage Example
// User has opted into sharing data
Singular.limitDataSharing(false);

Additional Methods for GDPR Compliance

The Singular SDK provides several methods to help you comply with GDPR policies and let Singular know about user consent or non-consent for tracking.

Singular.trackingOptIn Method
Description Notify Singular of user consent (opt-in) for tracking.
Usage Example
Singular.trackingOptIn();
Singular.stopAllTracking Method
Description

Stop all tracking activities for this user on this app.

Note: Calling this method effectively disables the SDK, even after the app restarts (the state is persistent)! The only way to re-enable tracking is by calling resumeAllTracking().
Usage Example
Singular.stopAllTracking();
Singular.resumeAllTracking Method
Description Resume tracking for this user on this app.
Usage Example
Singular.resumeAllTracking();
Singular.isAllTrackingStopped Method
Description Check the tracking status for this user on this app. Returns true if tracking has been stopped using StopAllTracking() and not resumed.
Usage Example
Singular.isAllTrackingStopped();