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.
Delegate setup
Section titled “Delegate setup”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.Intentimport android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport com.swmansion.detour.Detourimport com.swmansion.detour.DetourConfigimport com.swmansion.detour.DetourDelegateimport com.swmansion.detour.models.LinkProcessingModeimport 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.
Handle resolved links
Section titled “Handle resolved links”processLink() and getDeferredLink() return one of four results:
LinkResult.Success— carriesurl,route,pathname,params, andtypeLinkResult.NotFirstLaunch— the deferred flow was already consumed in this install or sessionLinkResult.NoLink— no matching linkLinkResult.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)}Link processing modes
Section titled “Link processing modes”DetourConfig.linkProcessingMode controls which link sources the SDK handles:
| Value | Deferred | App Links (http/https) | Custom scheme |
|---|---|---|---|
ALL (default) | Yes | Yes | Yes |
WEB_ONLY | Yes | Yes | No |
DEFERRED_ONLY | Yes | No | No |
Use DEFERRED_ONLY when your navigation stack already handles App Link and scheme intents, and Detour should only resolve first-install deferred links.
Click limits
Section titled “Click limits”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.
Over the limit
Section titled “Over the limit”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.
Other link types
Section titled “Other link types”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()returnsLinkResult.NoLinkandresolveShortLink()returnsnull. - 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.
Deferred-only flow
Section titled “Deferred-only flow”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.
Analytics
Section titled “Analytics”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.DetourAnalyticsimport com.swmansion.detour.analytics.DetourEventNames
DetourAnalytics.logEvent( DetourEventNames.Purchase, mapOf("item" to "subscription_premium", "currency" to "USD"),)
DetourAnalytics.logRetention("home_screen_opened")