Android SDK

Install and integrate the LinkTrail Android SDK — package io.linktrail, minSdk 26.

Binary AAR · package io.linktrail · entry point LinkTrail · minSdk 26 · artifact io.linktrail:sdk:0.0.3 on Maven Central.

Install

The SDK is published to Maven Central, so no custom repository is needed — just add the dependency:

app/build.gradle.ktskotlin
dependencies {
    implementation("io.linktrail:sdk:0.0.3")
}

mavenCentral() is already in the default repositories of every Android project, which also resolves the SDK's transitive dependencies (coroutines, Play Install Referrer, App Set ID). Keep google() alongside it.

Nothing else to configure: the INTERNET permission merges in from the SDK's manifest, and consumer ProGuard/R8 rules are bundled in the AAR — no app-side keep rules needed.

Integrate

import io.linktrail.LinkTrail

// In Application.onCreate(). The API key is required — a blank key throws.
// The install is tracked automatically.
LinkTrail.configure(context = this, apiKey = "lt_live_...")

// One hook — fires for deferred (first-launch) AND re-engagement links:
LinkTrail.shared?.onLink { link, source ->
    router.route(link.path, link.customData)
}

LinkTrail.shared?.onError { error -> /* e.g. LinkTrailError.InvalidApiKey */ }

Forward incoming links from your Activity — both entry points:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    LinkTrail.shared?.handleDeepLink(intent?.data)
}
override fun onNewIntent(intent: Intent) {          // app already running
    super.onNewIntent(intent)
    setIntent(intent)                               // keep getIntent() current
    LinkTrail.shared?.handleDeepLink(intent.data)
}

Every callback API also has a coroutine suspend twin (trackInstallAsync, handleDeepLinkAsync, trackEventAsync). Callbacks are delivered on the main thread.

More

// Custom + revenue events:
LinkTrail.shared?.trackEvent("purchase", value = 59.99, currency = "USD")

// Cached results:
val attribution = LinkTrail.shared?.lastAttribution
val lastLink = LinkTrail.shared?.lastDeepLink

// Attribution hook (fires when an install is attributed):
LinkTrail.shared?.onAttribution { attribution -> /* … */ }

// Consent-gated install (defer configure's auto-track, then call manually):
LinkTrail.configure(context = this, apiKey = "lt_live_...",
    options = LinkTrailOptions(autoTrackInstall = false))
LinkTrail.shared?.trackInstall()

Options & defaults

LinkTrailOptions fieldDefaultNotes
logEnabledfalseMaster switch for SDK logging (tag: LinkTrail)
logLevelINFODEBUG · INFO · WARNING · ERROR · NONE
requestTimeoutMillis15 000Per-request network timeout
retryPolicyDEFAULT3 attempts, 500 ms base / 8 s max backoff; DISABLED turns retries off
linkDomainsempty (all hosts)Exact host or subdomain match; see warning under Deep-link setup
autoTrackInstalltruefalse = consent-gated; call trackInstall() yourself

Errors are a sealed LinkTrailError: MissingApiKey (thrown synchronously by configure), InvalidApiKey (the backend rejected the key — arrives via onError, not from configure), NotALinkTrailUrl, InvalidUrl, Server, Transport, Decoding, EmptyResponse. Under the hood the SDK also queues failed events offline and retries them after the next successful install call, and handles the Play Install Referrer and App Set ID automatically — there's no API to call. (App Tracking Transparency / SKAdNetwork are iOS-only and have no Android equivalent.)

API surface

APIPurpose
configure(context, apiKey, options)Initialize; auto-tracks the install
onLink { link, source }Deep link delivered (deferred + re-engagement)
onAttribution { attribution }Install attribution result
onError { error }Failures (invalid key, network…)
handleDeepLink(uri)Forward App Links / custom schemes
trackEvent(name, value, currency)Custom + revenue events
trackInstall(force)Manual install track (with autoTrackInstall = false)
lastAttribution / lastDeepLinkCached last results
trackInstallAsync / handleDeepLinkAsync / trackEventAsyncCoroutine suspend twins

Declare your App Links host (plus an optional custom scheme) in the manifest:

AndroidManifest.xmlxml
<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" android:host="yourapp.linktrail.io" />
</intent-filter>
The assetlinks.json file is generated and hosted by LinkTrail — it's built from the package name + SHA-256 fingerprints you registered in the dashboard (to change fingerprints, edit the app in the dashboard, not a file). Links opening the browser or Play Store instead of your app? That's almost always App Links verification — see Troubleshooting. And if you set linkDomains, list every link host: re-engagement opens only route for listed hosts, while deferred install links still route — so the bug hides on fresh installs.
Example app: KickFlip — a Jetpack Compose storefront in example/ wired end to end. cd example && ./gradlew :app:installDebug, with your API key in example/local.properties as linktrail.apiKey=lt_live_… (without a key, the built-in deep-link simulator still works offline).