Android

Integrate SDK into your Android project. As an example, use a ready-made demo app in Java and Kotlin.

Basic requirements

  • Oldest Android version supported — 4.0 (API Level 14).

  • For Google Play apps, the project must have  Google Play Services (com.google.android.gms:play-services-ads-identifier module) and Google Play Install Referrer (com.android.installreferrer:installreferrer module) enabled.

  • For Huawei AppGallery apps, the project must have Huawei Media Services enabled (com.huawei.hms:hms-ads-identifier and com.huawei.hms:ads-installreferrer modules), so MyTracker can obtain OAID and Install Referrer.

Integration

Using Gradle

Add build.gradle file to your project dependencies section:

dependencies {
//... other dependencies
implementation 'com.my.tracker:mytracker-sdk:3.0.+'
}

Manually

  • Download the latest version of MyTracker.aar.

  • Add MyTracker.aar to your project as a dependency.

  • Add next dependencies to your application build.gradle file:

    dependencies {
        ...
        implementation 'com.android.installreferrer:installreferrer:2.2'
        implementation 'com.google.android.gms:play-services-ads-identifier:18.0.0'
        implementation 'com.google.android.gms:play-services-appset:16.0.1'
    }
  • (Optionally or when using jar) If using Proguard make sure to add an exception:

    -keep class com.my.tracker.** { *; }
    -dontwarn com.my.tracker.**
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
        com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);
    }
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
        java.lang.String getId();
        boolean isLimitAdTrackingEnabled();
    }
    -keep class com.android.installreferrer.** { *; }
    -keep class com.android.vending.billing.** { *; }
    -keep class com.android.billingclient.api.** { *; }

Required permissions

(Optionally or when using jar) Add required permissions to your app’s AndroidManifest.xml at "manifest" section:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
     >
    ...
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
    ...
</manifest>

Initialization

For correct MyTracker SDK operation, set it up and initialize inside of your app the onCreate method of the Application class. To initialize SDK, you have to enter your SDK_KEY. And before that, you may set different settings for the tracker (configurations, parameters, deep links, etc.).

SDK_KEY is generated automatically after you added your application to MyTracker. To get the key, go to the Application list page, select the required application, and copy the key from the Overview tab.

public class YourApplicationClass extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        // Setting up the configuration if needed
        MyTrackerParams trackerParams = MyTracker.getTrackerParams();
        MyTrackerConfig trackerConfig = MyTracker.getTrackerConfig();
        // …
        // Setting up params
        // …
        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this);
    }
}
class YourApplicationClass : Application()
{
    override fun onCreate()
    {
        super.onCreate()

        // Setting up the configuration if needed
        val trackerParams = MyTracker.getTrackerParams()
        val trackerConfig = MyTracker.getTrackerConfig()
        // ...
        // Setting up params
        // ...

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this)
    }
}

If you cannot initialize MyTracker inside the Application class, you could do that in the first starting activity of your application. However, in this case you must call the trackLaunchManually method of MyTracker after initialization.

public class YourActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);


        // Setting up the configuration if needed
        MyTrackerParams trackerParams = MyTracker.getTrackerParams();
        MyTrackerConfig trackerConfig = MyTracker.getTrackerConfig();
        // ...
        // Setting up params
        // ...

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, getApplication());

        //Enable activity tracking
        MyTracker.trackLaunchManually(this);
    }
}
class YourActivity : Activity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        // Setting up the configuration if needed
        val trackerParams = MyTracker.getTrackerParams()
        val trackerConfig = MyTracker.getTrackerConfig()
        // ...
        // Setting up params
        // ...

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, getApplication())
        MyTracker.trackLaunchManually(this)
    }
}

Collect device IDs

Starting version 3.0.10 of MyTracker SDK, MyTracker automatically collects only resettable device IDs:

  • GAID (for apps published on Google Play);
  • App Set ID (for apps published on Google Play);
  • OIAD (for apps published on Huawei App Gallery).

MyTracker uses this information for advertising by attributing installs to traffic sources and uniqueizing the device within the project. When publishing your app on Google Play, complete the Google Play Data Safety section according to our guidelines.

If your app is not published on Google Play or the project requires additional IDs, you can send them to MyTracker using the appropriate SDK method:

MyTrackerParams trackerParams = MyTracker.getTrackerParams();
trackerParams.setCustomParam("custom_param_key", "custom_param_value");
val trackerParams = MyTracker.getTrackerParams()
trackerParams.setCustomParam("custom_param_key", "custom_param_value");

This method supports the following custom_param_key values:

  • android_id — a unique, non-resettable mobile device ID used by the third-party app stores. The SDK does not automatically collect android_id.

    According to the Google Play Privacy Policy, android_id cannot be used with GAID. However, it can be sent if the app is published in alternative app stores.

  • imei — a unique, non-resettable mobile device ID used in app stores other than Google Play. The SDK does not collect imei automatically.

    According to the Google Play Privacy Policy, imei cannot be used with GAID. However, it can be sent if the app is published in alternative app stores.

  • mac — an identifier of the mobile device's network equipment used in some types of attribution in MyTracker. The SDK does not collect mac automatically.

The sending of the listed identifiers is optional.

An example of initializing MyTracker with additional identifiers:

public class YourApplicationClass extends Application
{
    // Method of receiving Android ID
    static @Nullable String getAndroidId(Context context)
    {
        try
        {
            ContentResolver cr = context.getContentResolver();
            if (cr != null)
            {
                return Settings.Secure.getString(cr, Settings.Secure.ANDROID_ID);
            }
        }
        catch (Throwable e) {}

        return null;
    }

    // Method of receiving MAC
    static @Nullable String getMac()
    {
        try
        {
            List all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all)
            {
                if (!nif.getName().equalsIgnoreCase("wlan0"))
                {
                    continue;
                }

                try
                {
                    byte[] macBytes = nif.getHardwareAddress();
                    if (macBytes == null)
                    {
                        return null;
                    }

                    StringBuilder result = new StringBuilder();
                    for (byte b : macBytes)
                    {
                        result.append(String.format("%02X:", b));
                    }

                    int length = result.length();
                    if (length > 0)
                    {
                        result.deleteCharAt(length - 1);
                    }

                    return result.toString();
                }
                catch (Throwable e) {}
            }
        }
        catch (Throwable e) {}

        return null;
    }

    @Override
    public void onCreate()
    {
        super.onCreate();

        // Set up tracker configuration
        MyTrackerParams trackerParams = MyTracker.getTrackerParams();

        // Set up additional IDs sending
        trackerParams.setCustomParam("android_id", getAndroidId(getApplicationContext()));
        trackerParams.setCustomParam("mac", getMac());

        MyTrackerConfig trackerConfig = MyTracker.getTrackerConfig();
        // …
        // Set up tracker parameters
        // …

        // Initialize tracker
        MyTracker.initTracker(SDK_KEY, this);
    }
}
class YourApplicationClass : Application()
{
    override fun onCreate()
    {
        super.onCreate()

        // Set up tracker configuration
        val trackerParams = MyTracker.getTrackerParams()

        // Set up additional IDs sending
        trackerParams.setCustomParam("android_id", getAndroidId(applicationContext))
        trackerParams.setCustomParam("mac", getMac())

        val trackerConfig = MyTracker.getTrackerConfig()
        // …
        // Set up tracker parameters
        // …

        // Initialize tracker
        MyTracker.initTracker(SDK_KEY, this)
    }

    // Method of receiving Android ID
    fun getAndroidId(context: Context): String?
    {
        try
        {
            val cr = context.contentResolver
            if (cr != null)
            {
                return Settings.Secure.getString(cr, Settings.Secure.ANDROID_ID)
            }
        } catch (e: Throwable)
        {
        }
        return null
    }

    // Method of receiving MAC
    fun getMac(): String?
    {
        try
        {
            val all: List = Collections.list(NetworkInterface.getNetworkInterfaces())
            for (nif in all)
            {
                if (!nif.name.equals("wlan0", ignoreCase = true))
                {
                    continue
                }
                try
                {
                    val macBytes = nif.hardwareAddress ?: return null
                    val result = StringBuilder()
                    for (b in macBytes)
                    {
                        result.append(String.format("%02X:", b))
                    }
                    val length = result.length
                    if (length > 0)
                    {
                        result.deleteCharAt(length - 1)
                    }
                    return result.toString()
                }
                catch (e: Throwable)
                {
                }
            }
        }
        catch (e: Throwable)
        {
        }
        return null
    }
}

API

Tracker configuration

Configuration can be set up in the MyTrackerConfig class instance available through the MyTracker.getTrackerConfig() method. All parameters can be set up in the MyTrackerParams class instance available through the MyTracker.getTrackerParams() method. Currently available:

TrackingLaunchEnabled: app launch tracking. True by default.

@NonNull MyTrackerConfig setTrackingLaunchEnabled(boolean trackingLaunchEnabled)
fun setTrackingLaunchEnabled(trackingLaunchEnabled: Boolean): MyTrackerConfig

LaunchTimeout: an interval (in seconds) during which a new launch is not tracked and a session is not interrupted while app is in background. 30 seconds by default. Possible value range: 30-7200 seconds.

@NonNull MyTrackerConfig setLaunchTimeout(int seconds)
fun setLaunchTimeout(seconds: Int): MyTrackerConfig

BufferingPeriod: the time during which events are accumulated locally on the device before being sent to the MyTracker server. The default value is 900 seconds, allowed values are: 1-86400 seconds (1 day).

@NonNull MyTrackerConfig setBufferingPeriod(int seconds)
fun setBufferingPeriod(seconds: Int): MyTrackerConfig

ForcingPeriod: an interval (in seconds) starting from application install/update during which any new event will be send to the server immediately, without local buffering. Default value is set to 0 (immediate sending is disabled), allowed values are 0-432000 seconds (5 days).

@NonNull MyTrackerConfig setForcingPeriod(int seconds)
fun setForcingPeriod(seconds: Int): MyTrackerConfig

AutotrackingPurchaseEnabled: if inApp purchase events should be tracked automatically. True by default.

@NonNull MyTrackerConfig setAutotrackingPurchaseEnabled(boolean autotrackingPurchaseEnabled)
fun setAutotrackingPurchaseEnabled(autotrackingPurchaseEnabled: Boolean): MyTrackerConfig

TrackingLocationEnabled: geolocation tracking. False by default.

If your application requests location access, you can enable this parameter to improve the accuracy of statistics related to the user geography. In some cases, location tracking also improves attribution and predictive models (Fraud Scanner, Personalize, LTV Predictions, etc.).

The parameter is disabled by default since SDK version 3.0.9

@NonNull MyTrackerConfig setTrackingLocationEnabled(boolean trackingLocationEnabled)
fun setTrackingLocationEnabled(trackingLocationEnabled: Boolean): MyTrackerConfig

TrackingPreinstallEnabled: pre-installs tracking. True by default. MyTracker will catch pre-installs if you share an application and a special JSON-file with the device manufacturer.

@NonNull MyTrackerConfig setTrackingPreinstallEnabled(boolean trackingPreinstallEnabled)
fun setTrackingPreinstallEnabled(trackingPreinstallEnabled: Boolean): MyTrackerConfig

Region, where the data collection server is located. Choose a region based, for example, on current legislation. Available values:

  • Region.RU — server on the territory of Russian Federation

  • Region.EU — server on the territory of Europe

@NonNull MyTrackerConfig setRegion(int region)
fun setRegion(region: Int): MyTrackerConfig

Enable/disable debug mode

Enabling and disabling debug mode can be done via MyTracker class static methods. False by default.

@AnyThread
void setDebugMode(boolean debugMode)
@AnyThread
            fun setDebugMode(debugMode: Boolean)

Track users

Set the customUserId parameter to track user stats, not only device. It's a unique user identifier in the project, that you specify at the time of registration. The identifier should remain unchanged even when user switch devices. The parameter allows you to estimate the size and activity of user base, regardless of the number of user devices. Also, you can keep your customer data consistent if a user changes a device. For details, see the User tracking section.

It's essential to set the parameter before tracking events to pass user identifier with every event.

public void setUserInfo()
{
    MyTrackerParams trackerParams = MyTracker.getTrackerParams();

    // Set user id
    trackerParams.setCustomUserId("user_id");

}
fun setUserInfo()
{
    val trackerParams = MyTracker.getTrackerParams()

    // Set user id
    trackerParams.setCustomUserId("user_id")

}

If customUserId was set to the application with an existing registered users, MyTracker cannot calculate exact Lifetime metrics without registration time. For pre-registered users, Lifetime statistic will be count on the date of the first tracked event with customUserId.

To turn off user tracking, pass an empty value in the customUserId parameter.

Track events

Events can be sent via MyTracker class static methods. Before you call methods, set the customUserId parameter to pass user identifier with every tracked event.

The following methods for event tracking are available:

Registration event. You should call the method right after user registered in the app. Pass the user identifier in the parameter userId.

userId is a required parameter since SDK version 2.0.8

@AnyThread
void trackRegistrationEvent(@NonNull String userId)
@AnyThread
fun trackRegistrationEvent(userId: String)

Login event. You should call the method right after user successfully authorized in the app. Pass the user identifier in the parameter userId.

userId is a required parameter since SDK version 2.0.8

@AnyThread
void trackLoginEvent(@NonNull String userId)
@AnyThread
fun trackLoginEvent(userId: String)

Invite event. Any optional parameters can be passed with event as "key-value" by the optional eventParams parameter. Max key or value length — 255 chars.

@AnyThread
void trackInviteEvent()
@AnyThread
void trackInviteEvent(@Nullable Map<String, String> eventParams)
@AnyThread
fun trackInviteEvent()

@AnyThread
fun trackInviteEvent(eventParams: Map<String, String>?)

Level up event. The level parameter is optional. Any optional parameters can be passed with event as "key-value" by the optional eventParams parameter. Max key or value length — 255 chars.

@AnyThread
void trackLevelEvent()
@AnyThread
void trackLevelEvent(@Nullable Map<String, String> eventParams)
@AnyThread
void trackLevelEvent(int level, @Nullable Map<String,  String> eventParams)
@AnyThread
fun trackEvent(name: String)

@AnyThread
fun trackEvent(name: String, eventParams: Map<String, String>?)

Any user defined event with a custom name. Any optional parameters can be passed with event as "key-value" by the optional eventParams parameter. Max name, key or value length — 255 chars.

@AnyThread
void trackEvent(@Nullable String name)
@AnyThread
void trackEvent(@Nullable String name, @Nullable Map<String, String> eventParams)
@AnyThread
fun trackEvent(name: String)

@AnyThread
fun trackEvent(name: String, eventParams: Map<String, String>?)

Example:

Map<String, String> eventParams = new HashMap<>();
eventParams.put("someParamKey1", "someParamValue1");
eventParams.put("someParamKey2", "someParamValue2");
MyTracker.trackEvent("eventName", eventParams);
val eventParams = HashMap<String, String>()
eventParams["someParamKey1"] = "someParamValue1";
eventParams["someParamKey2"] = "someParamValue2";
MyTracker.trackEvent("eventName", eventParams);

Force sending events from local buffer to server and reset buffering timers.

The SDK, which reduces channel load and lowers impact on app performance, collects all data on the device before sending it off to the server and regularly does so in a compressed format. By default, data is sent every 15 minutes. The interval can be changed to anywhere from 1 second to 1 day through the bufferingPeriod property. If the user has quit the app, the events will be sent during next launch. It's extremely important to analyse certain events as soon as possible, especially in the first sessions since installing the app. The flush() method will help.

@AnyThread
void flush()
@AnyThread
fun flush()

Track in-app purchases

Play Billing Library

If you use the Play Billing Library, for automatic purchase events tracking you must call the corresponding MyTracker method from onPurchasesUpdated method of BillingClient listener.

private BillingClient client;
...
client = BillingClient.newBuilder(context)
                 .setListener(new PurchasesUpdatedListener()
                 {
                    @Override
                    public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases)
                    {
                        MyTracker.onPurchasesUpdated(responseCode, (List) purchases);


                        // Your code for in-app purchase handling
                        // ...
                    }
                 })
                 .build();
...
private var client: BillingClient? = null
// ...
client = BillingClient.newBuilder(this)
                .setListener { billingResult, purchases ->
                    MyTracker.onPurchasesUpdated(billingResult.responseCode, purchases as List<Any>?)
                    // ...
                    // Your code for in-app purchase handling
                    // ...
                }
                .build()
// ...

In-app Billing API

If you use you own In-App Billing API implementation, for automatic purchase events tracking you must call the corresponding MyTracker method from onActivityResult method of activity that started the purchase process.

public static final int PURCHASE_REQUEST_CODE = 1001;
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
   super.onActivityResult(requestCode, resultCode, data);
   if (requestCode == PURCHASE_REQUEST_CODE)
   {
        MyTracker.onActivityResult(resultCode, data);
        // Your code for in-app purchase handling
        // ...
   }
}
...
// ...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
{
    super.onActivityResult(requestCode, resultCode, data)
    if (PURCHASE_REQUEST_CODE == requestCode)
    {
        MyTracker.onActivityResult(resultCode, data)
        // ...
        // Your code for in-app purchase handling
        // ...
    }
}
// ...
companion object
{
    const val PURCHASE_REQUEST_CODE = 1001
}

Manual in-app purchases tracking

If you would like to track in-app purchase events manually, you shoud disable auto tracking by setting autotrackingPurchaseEnabled = false and use MyTracker methods:

@AnyThread
void trackPurchaseEvent(@NonNull JSONObject skuDetails,
       @NonNull JSONObject purchaseData,
       @NonNull String dataSignature)
@AnyThread
void trackPurchaseEvent(@NonNull JSONObject skuDetails,
       @NonNull JSONObject purchaseData,
       @NonNull String dataSignature,
       @Nullable Map<String, String> eventParams)
@AnyThread
fun trackPurchaseEvent(skuDetails: JSONObject,
                       purchaseData: JSONObject,
                       dataSignature: String)

@AnyThread
fun trackPurchaseEvent(skuDetails: JSONObject,
                       purchaseData: JSONObject,
                       dataSignature: String,
                       eventParams: Map<String, String>?)

If auto tracking is enabled, this methods calls will be ignored. Required parameters:

  • skuDetails — return value of the getSkuDetails() method call according to documentation
  • purchaseData — JSON object in INAPP_PURCHASE_DATA field of the getBuyIntent() method return value, according to documentation
  • dataSignature — string from INAPP_DATA_SIGNATURE field of the getBuyIntent() method return value

Since data returned by the getSkuDetails() and getBuyIntent() methods comes as Bundle with String type fields in it, transformation to JSONObject before send is required.

Any optional parameters can be passed with event as "key-value" by the optional eventParams parameter. Max key or value length — 255 chars.

public static final int PURCHASE_REQUEST_CODE = 1001;
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
   super.onActivityResult(requestCode, resultCode, data);
   if (requestCode == PURCHASE_REQUEST_CODE && resultCode == RESULT_OK)
   {
      try
      {
         final String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
         final String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");

         final JSONObject purchaseDataJson = new JSONObject(purchaseData);

         // Receive skuDetails response
         final JSONObject skuDetailsJson = obtainSkuDetailJson(purchaseData);

         MyTracker.trackPurchaseEvent(skuDetailsJson, purchaseDataJson, dataSignature);


        // Your code for in-app purchase handling
        // ...
      }
      catch (Exception ignored)
      {
      }
   }
}
...
// ...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
{
    super.onActivityResult(requestCode, resultCode, data)
    // Checking if the request code is PURCHASE_REQUEST_CODE
    if (PURCHASE_REQUEST_CODE == requestCode && RESULT_OK == resultCode && data != null)
    {
        try
        {
            val dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE") ?: return
            val purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA") ?: return

            //  Receive skuDetails response
            val skuDetailsJson = obtainSkuDetailJson(purchaseData)

            val purchaseDataJson = JSONObject(purchaseData)

            MyTracker.trackPurchaseEvent(skuDetailsJson, purchaseDataJson, dataSignature)
        }
        catch (_: Exception)
        {
        }
    }
}
// ...
companion object
{
    const val PURCHASE_REQUEST_CODE = 1001
}
// ...

S2S tracking

To send data from your server to MyTracker (for example, untracked data, offline events, etc.), you may need a special device identifier — instanceId. The instanceId is a device identifier (UUID v4), that generated at the first app launch and unchanged until a user delete the app (or app data) from device.

The instanceId can get via MyTracker class static method (you should not use it in the main thread).

@WorkerThread
@NonNull String getInstanceId(@NonNull Context context)
@WorkerThread
fun getInstanceId(context: Context): String

It's essential to collect instanceId as soon as possible and send the identifier to your server if you use this ID to work with S2S API.
Making API requests instead of instanceId, you can use customUserID or any device ID (gaid, androidId, appSetId).

Deep links allow sending additional parameters to the app. So a user can go to a specific app screen. There are two types of deep links: regular when parameters to be sent on a launch of the app and deferred when parameters to be sent on a launch of the app after the install. For more details, see the Deep Links section.

Regular deep links

To allow MyTracker to handle regular deep links, in each application activity which support deep links in the onCreate and onNewIntent methods you must call the handleDeeplink method of MyTracker.

public class SomeActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate();
        // ...
        String deeplink = MyTracker.handleDeeplink(getIntent());
        if(deeplink != null)
        {
            // Handle deep link
        }
    }


    @Override
    protected void onNewIntent(Intent intent)
    {
        super.onNewIntent(intent);
        // ...
        String deeplink = MyTracker.handleDeeplink(intent);
        if(deeplink != null)
        {
            // Handle deep link
        }
    }
}
class SomeActivity : Activity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        // ...
        val deeplink = MyTracker.handleDeeplink(intent)
        if (deeplink != null)
        {
            // ...
            // Handle deep link
            // ...
        }
    }

    override fun onNewIntent(intent: Intent?)
    {
        super.onNewIntent(intent)
        // ...
        val deeplink = MyTracker.handleDeeplink(intent)
        if (deeplink != null)
        {
            // ...
            // Handle deep link
            // ...
        }
    }
}

Deferred deep links

To support deferred deep links in your app you need to add a listener which implement the MyTracker.AttributionListener interface. The listener would be called out just once, at first launch of the app if a deferred deep link is found.

As a parameter to the onReceiveAttribution method, the MyTrackerAttribution attribution object containing the deep link property would be passed. Check that the property value belongs to your app otherwise a third-party app might open when using Intent transition.

public class YourApplicationClass extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        // Setting up the configuration if needed
        MyTrackerParams trackerParams = MyTracker.getTrackerParams();
        MyTrackerConfig trackerConfig = MyTracker.getTrackerConfig();
        // ...
        // Setting up params
        // ...


        // Set listener to receive the deferred deep link
        MyTracker.setAttributionListener(new MyTracker.AttributionListener()
        {

            @Override
            public void onReceiveAttribution(MyTrackerAttribution attribution)
            {
                String deeplink = attribution.deeplink;
                // Processing the deferred deep link
                // ...
            }
        });

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this);
    }
}
class YourApplicationClass : Application
{
    override fun onCreate()
    {
        super.onCreate()

        // Setting up the configuration if needed
        val trackerParams = MyTracker.getTrackerParams();
        val trackerConfig = MyTracker.getTrackerConfig();
        // ...
        // Setting up params
        // ...

        // Set listener to receive the deferred deep link
        MyTracker.setAttributionListener { myTrackerAttribution ->
            val deeplink = myTrackerAttribution.deeplink
            // ...
            //  Handle the deferred deep link
            // ...
        }

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this)
    }
}

You may set up a Handler for listener method execution when setting the listener with the setAttributionListener(AttributionListener attributionListener, Handler handler) method. If no Handler is set up when installing the listener then the onReceiveAttribution method would be called in the main application flow.