Skip to content
Dashboard

Usage

Detour delivers links to your app through the launching intent. DetourDelegate attaches to the Activity lifecycle, resolves the incoming link, whether deferred, App Link, or custom scheme, and returns a LinkResult to navigate with. Apps that only need deferred links can skip the delegate and call Detour.getDeferredLink() directly.

DetourDelegate is the recommended integration for classic Android apps. It wraps the coroutine calls to Detour.processLink(...) and returns LinkResult in a callback.

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.swmansion.detour.Detour
import com.swmansion.detour.DetourConfig
import com.swmansion.detour.DetourDelegate
import com.swmansion.detour.models.LinkProcessingMode
import com.swmansion.detour.models.LinkResult
class MainActivity : AppCompatActivity() {
private val detourDelegate = DetourDelegate(
lifecycleOwner = this,
config = DetourConfig(
apiKey = BuildConfig.DETOUR_API_KEY,
appId = BuildConfig.DETOUR_APP_ID,
linkProcessingMode = LinkProcessingMode.ALL,
),
onLinkResult = { result -> handleLinkResult(result) }
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Detour.initialize(this, detourDelegate.config)
detourDelegate.onCreate(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
detourDelegate.onNewIntent(intent)
}
private fun handleLinkResult(result: LinkResult) {
// handle result and navigate
}
}

onCreate(intent) processes the intent that created a new activity instance. onNewIntent(intent) processes a link delivered to an existing instance, for example when the activity uses singleTop or singleTask. Keep the setIntent(intent) call so the activity’s current intent stays in sync.

For complete, runnable integrations, see Examples.

processLink() and getDeferredLink() return one of four results:

  • LinkResult.Success — carries url, route, pathname, params, and type
  • LinkResult.NotFirstLaunch — the deferred flow was already consumed in this install or session
  • LinkResult.NoLink — no matching link
  • LinkResult.Error — a runtime or integration error

Typical routing pattern:

when (result) {
is LinkResult.Success -> navigateToRoute(result.route, result.params)
is LinkResult.NotFirstLaunch -> Unit
is LinkResult.NoLink -> Unit
is LinkResult.Error -> Log.e("Detour", "Link error", result.exception)
}

DetourConfig.linkProcessingMode controls which link sources the SDK handles:

ValueDeferredApp Links (http/https)Custom scheme
ALL (default)YesYesYes
WEB_ONLYYesYesNo
DEFERRED_ONLYYesNoNo

Use DEFERRED_ONLY when your navigation stack already handles App Link and scheme intents, and Detour should only resolve first-install deferred links.

Before it delivers an App Link or Universal Link, the SDK checks the click against your plan’s limit. Within the limit, links resolve normally.

The link is not delivered. processLink() returns LinkResult.NoLink, and so does the DetourDelegate callback.

The SDK logs [Detour:CLICK_LIMIT_ERROR] in logcat with clicksInPeriod and effectiveLimit.

This flow applies only to App Links and Universal Links.

  • Deferred and short links — the same plan limits apply on the backend, but the SDK raises no click-limit error. An over-limit link fails to resolve: getDeferredLink() returns LinkResult.NoLink and resolveShortLink() returns null.
  • Custom scheme links — resolved on device, never limit-checked.

For per-plan limits, pay-as-you-go overage, and how to raise them, see Billing & Payments.

In DEFERRED_ONLY mode you can skip DetourDelegate and call Detour.getDeferredLink() directly:

Detour.initialize(
this,
DetourConfig(
apiKey = BuildConfig.DETOUR_API_KEY,
appId = BuildConfig.DETOUR_APP_ID,
linkProcessingMode = LinkProcessingMode.DEFERRED_ONLY,
)
)
lifecycleScope.launch {
when (val result = Detour.getDeferredLink()) {
is LinkResult.Success -> navigateToRoute(result.route, result.params)
else -> Unit
}
}

See the example-deferred-only app in Examples.

Detour.initialize(...) turns analytics on. With the SDK initialized, it logs one event by itself: app_open, a retention event sent once per session on cold start. App Link and Universal Link opens are not client events. The backend records them through the click endpoint (see Click limits).

Everything else you log yourself, through DetourAnalytics.

import com.swmansion.detour.analytics.DetourAnalytics
import com.swmansion.detour.analytics.DetourEventNames
DetourAnalytics.logEvent(
DetourEventNames.Purchase,
mapOf("item" to "subscription_premium", "currency" to "USD"),
)
DetourAnalytics.logRetention("home_screen_opened")