Android SDK - Advanced Options

Advanced Options

Configure advanced SDK features including install referrer collection, session management, JavaScript integration, and alternative device identifiers for specialized use cases.

Install Referrer Collection (Legacy Devices)

Overview

The install referrer provides accurate attribution by identifying which ad the user clicked before installing your app from Google Play Store.

Deprecated: Google deprecated the INSTALL_REFERRER intent broadcast. See Still Using InstallBroadcast? Switch to the Play Referrer API by March 1, 2020. Modern Singular SDK versions automatically use the Google Play Referrer API.

Automatic Collection:

On devices with the latest Google Play Store, the Singular SDK collects the install referrer automatically using the Google Play Referrer API. Manual configuration is only needed for legacy device support.


Integrate with Existing Receiver

Forward install referrer data to Singular when your app already has a BroadcastReceiver for INSTALL_REFERRER.

Implementation:

Add a call to SingularInstallReceiver within your existing receiver's onReceive method.

KotlinJava
class MyCustomInstallReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // Forward install referrer to Singular
        SingularInstallReceiver().onReceive(context, intent)
        
        // Your existing logic
        // ...
    }
}

Register Singular Receiver

Configure the Singular install referrer receiver when your app doesn't have an existing INSTALL_REFERRER handler.

AndroidManifest.xml Configuration:

AndroidManifest.xml
<application>
    <!-- Other application components -->
    
    <receiver 
        android:name="com.singular.sdk.SingularInstallReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="com.android.vending.INSTALL_REFERRER" />
        </intent-filter>
    </receiver>
</application>

Recommendation: This configuration is only necessary for apps supporting very old devices. Modern implementations should rely on the automatic Google Play Referrer API integration.


Session Management

Automatic Session Management

The Singular SDK automatically handles session management for Android API 14 (Ice Cream Sandwich) and above without additional configuration.

Default Behavior:

When the app moves to the background for 60 seconds or more, the SDK registers a new session upon returning to the foreground.


Configure Session Timeout

Customize the session timeout duration to match your app's usage patterns.

Method Signature:

SingularConfig.withSessionTimeoutInSec(int timeoutInSeconds)
KotlinJava
// Set session timeout to 120 seconds (2 minutes)
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
    .withSessionTimeoutInSec(120)

Singular.init(applicationContext, config)

Timeout Values:

  • Default: 60 seconds
  • Minimum: 0 seconds (every background/foreground transition creates a new session)
  • Recommended: 30-180 seconds depending on app usage patterns

Manual Session Management (API < 14)

For apps with minSdkVersion below 14, manually manage sessions by calling lifecycle methods in each activity.

Important: Manual session management is only required for apps targeting Android API levels below 14 (Ice Cream Sandwich). Modern apps can skip this section.

Implementation

Call onActivityResumed() and onActivityPaused() in each activity's lifecycle methods, or implement in a base activity class.

KotlinJava
class MainActivity : AppCompatActivity() {
    
    override fun onResume() {
        super.onResume()
        Singular.onActivityResumed()
        // Your other code
    }
    
    override fun onPause() {
        super.onPause()
        Singular.onActivityPaused()
        // Your other code
    }
}

Best Practice: If you have a common base activity class, implement these calls in the base class's onResume() and onPause() methods instead of duplicating code across all activities.


JavaScript Interface for Hybrid Apps

Overview

Enable Singular SDK functionality from JavaScript code in WebView-based hybrid apps using the SingularJSInterface.

Supported Methods:

  • setCustomUserId: Set custom user identifier
  • unsetCustomUserId: Remove custom user identifier
  • event: Track events with or without attributes
  • revenue: Track revenue

Setup WebView Integration

Configure the JavaScript interface in your activity's onCreate() method for each WebView that needs Singular functionality.

KotlinJava
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    // Initialize Singular SDK
    val config = SingularConfig("SDK_KEY", "SDK_SECRET")
    Singular.init(this, config)
    
    // Configure WebView
    val myWebView = findViewById<WebView>(R.id.webview)
    myWebView.settings.javaScriptEnabled = true
    myWebView.loadUrl("file:///android_asset/index.html")
    
    // Add Singular JavaScript interface
    val singularJSInterface = SingularJSInterface(this)
    singularJSInterface.setWebViewId(R.id.webview)
    myWebView.addJavascriptInterface(singularJSInterface, "SingularInterface")
}

Multiple WebViews:

  • Configure the JavaScript interface for each WebView in your app
  • Use the same interface name ("SingularInterface") for consistency
  • Set unique WebView IDs for each instance

JavaScript Usage

Call Singular methods from JavaScript code running in your WebView.

Track Events

JavaScript
// Simple event without attributes
SingularInterface.event('level_completed');

// Event with attributes (pass as JSON string)
SingularInterface.event('purchase_attempt', 
    JSON.stringify({
        "item_name": "sword",
        "item_category": "weapons",
        "item_price": 9.99
    })
);

Track Revenue

JavaScript
// Track revenue in USD
SingularInterface.revenue('USD', 9.99);

// Track revenue in other currencies
SingularInterface.revenue('EUR', 8.50);

Manage Custom User ID

JavaScript
// Set custom user ID
SingularInterface.setCustomUserId('user_12345');

// Remove custom user ID
SingularInterface.unsetCustomUserId();

Alternative Device Identifiers

OAID (Open Advertising ID)

Enable tracking on Android devices in regions without Google Play using the Open Advertising Identifier (OAID).

OAID Support:

  • Huawei Devices: Huawei's proprietary OAID implementation
  • MSA Devices: Mobile Security Alliance member brands (OPPO, Vivo, Xiaomi, etc.)

Prerequisites

Integrate both the MSA SDK and Huawei OAID SDK to collect OAID on all supported platforms.

Enable OAID Collection

Configure the Singular SDK to collect and use OAID for tracking.

KotlinJava
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
    .withOAIDCollection()

Singular.init(applicationContext, config)

Automatic Detection:

  • The SDK automatically detects if the device has an OAID
  • The SDK selects the appropriate OAID SDK (MSA or Huawei) based on device
  • Amazon Advertising ID (AMID) is collected automatically without additional dependencies

IMEI (International Mobile Equipment Identity)

Collect the device IMEI number for tracking on devices in regions without Google Play Services.

Critical Warning: Collecting IMEI violates Google Play Services agreement. Only use IMEI collection for apps distributed outside Google Play Store in regions without Google services.

Add Required Permission

Add the READ_PHONE_STATE permission to your AndroidManifest.xml.

AndroidManifest.xml
<manifest>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
    <application>
        <!-- Your application components -->
    </application>
</manifest>

Retrieve IMEI Number

Obtain the device IMEI using TelephonyManager with proper API level handling.

KotlinJava
val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager

val imei: String? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    telephonyManager.imei
} else {
    @Suppress("DEPRECATION")
    telephonyManager.deviceId
}

// Validate IMEI before use
if (imei != null && imei.isNotEmpty()) {
    // Send to Singular
    Log.d("IMEI", "Retrieved: $imei")
} else {
    Log.w("IMEI", "Failed to retrieve IMEI")
}

Send IMEI to Singular

Configure IMEI during SDK initialization (recommended) or set it dynamically after initialization.

Option 1: Configuration Method (Recommended)

KotlinJava
// Set IMEI during initialization
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
    .withIMEI(imei)

Singular.init(applicationContext, config)

Option 2: Runtime Method

KotlinJava
// Set IMEI after initialization
Singular.setIMEI(imei)

Best Practice: Set IMEI in SingularConfig before SDK initialization to ensure it's available from the first session. Use setIMEI() only when the IMEI becomes available after initialization.