Testing & Troubleshooting
Deferred flow testing has platform constraints: full attribution path depends on store redirect chain.
Deferred flow constraints
Section titled “Deferred flow constraints”- Deferred matching is first-launch oriented.
- Runtime callbacks do not re-trigger deferred matching logic.
- Flutter bridge does not expose session reset API in
1.1.1.
Recommended deferred test flow
Section titled “Recommended deferred test flow”- Uninstall the app from the device or simulator.
- Open a Detour link.
- Install and launch the app.
- Verify the initial intent and the resolved route in your UI logs.
- Relaunch the app and confirm the deferred behavior is not repeated.
Runtime link tests
Section titled “Runtime link tests”Android App Link
Section titled “Android App Link”adb shell am start -a android.intent.action.VIEW \ -d "https://<your-link-domain>/<link-token>" \ com.example.appAndroid custom scheme
Section titled “Android custom scheme”adb shell am start -a android.intent.action.VIEW \ -d "myapp://product/42" \ com.example.appiOS custom scheme (simulator)
Section titled “iOS custom scheme (simulator)”xcrun simctl openurl booted "myapp://product/42"iOS Universal Link (simulator)
Section titled “iOS Universal Link (simulator)”xcrun simctl openurl booted "https://<your-link-domain>/<link-token>"Platform-specific notes
Section titled “Platform-specific notes”Android
Section titled “Android”Install referrer click_id is often unavailable in local/dev-store scenarios. In that case matching falls back to probabilistic flow.
For local install referrer testing workarounds, see
How to test the Play Store Install Referrer API.
Testing Android App Links
Section titled “Testing Android App Links”If an installed app does not open Detour links, the Dashboard SHA-256 probably does not match the key that signed the build on your device:
| How you install the app | SHA-256 to use | Where to find it |
|---|---|---|
| Google Play, any track | Play App Signing key | Play Console → Protected with Play → Manage Play app signing → App signing key certificate |
flutter run / flutter build apk --debug | AGP default debug keystore | keytool -list -v -keystore ~/.android/debug.keystore -storepass android, or ./gradlew signingReport |
| Release build with your own keystore | Your release keystore | keytool -list -v -keystore <path-to-your.keystore> |
The Flutter template signs release with the debug config until you add your own release keystore, so a fresh flutter build apk --release is still debug-signed.
To check any build directly: apksigner verify --print-certs build/app/outputs/flutter-apk/app-debug.apk. The complete procedure is described in Finding your Android SHA-256 fingerprint.
Common issues
Section titled “Common issues”-
No match found (404)
- Check timestamps. The click may be older than the match window (15 minutes).
- Confirm the click was recorded in your Detour Dashboard.
- On Android deterministic flow: confirm
click_idis present in the install referrer.
-
429 Too Many Requests
- Detour limits deferred link matching per device and IP address, and per app. Wait between reinstall tests on one device. For tests on many devices at once, create a separate app for testing in the Dashboard, because each app has its own credentials and its own limit.
-
NOT_CONFIGUREDplatform errorresolveInitialLink()andprocessLink()raise it on both platforms. On Android,logEvent()andlogRetention()raise it too.- Await
DetourService.start(...)orDetourFlutterPlugin.configure(...)before you call these methods. Ifconfigure(...)failed, fix that error first.
-
INVALID_ARGSplatform error- Android only.
configure(...)raises it whenapiKeyorappIDis empty,processLink(...)whenurlis empty, andlogRetention(...)wheneventNameis empty. A value that contains only whitespace counts as empty. - Pass non-empty values.
- Android only.
-
NO_ACTIVITYplatform error- On Android,
configure(...)ran in a Flutter engine that has no attached activity, such as a separate engine started for background work. - Call
DetourService.start(...)orDetourFlutterPlugin.configure(...)from your app’s UI code, not from a background handler.
- On Android,
-
NATIVE_ERRORplatform error- Android only.
resolveInitialLink()andprocessLink()raise it, andlinkStreamemits it as an error event, when the native SDK fails to process a link.DetourService.start()throws the same error and leavesisInitialLinkProcessedatfalse, so catch it if your startup flow waits for that flag. - A failed deferred match request on first launch raises it. When the server
responded, the message starts with the HTTP status code:
[401]for a wrongapiKeyorappID,[402]when your organization is over its plan’s click limit, and[429]for too many match requests. Without a status code, the request did not complete.
- Android only.
-
iOS clipboard not read
- Ensure
shouldUseClipboard: trueis set inDetourConfig. - Ensure the copy-link feature is enabled in the Detour Dashboard for your iOS app configuration.
- The link must be copied to the clipboard before the app is opened, because the clipboard is only read during
resolveInitialLink().
- Ensure
-
Deferred link not returned on subsequent test runs
- Deferred matching is first-launch based. Reinstall the app for a clean re-test.
-
Android release build fails with
Type com.swmansion.detour.BuildConfig is defined multiple times- Debug builds of the same project succeed.
detour_flutter_plugin1.1.1uses the Android namespacecom.swmansion.detour, which the native Detour SDK also uses. The release build then contains two classes namedcom.swmansion.detour.BuildConfig.- No
1.1.xrelease fixes this. Upgrade todetour_flutter_plugin: ^1.2.1and runflutter pub get.
Debugging
Section titled “Debugging”- Android:
adb logcat | grep -i detour
- iOS simulator:
xcrun simctl spawn booted log stream --predicate 'subsystem == "com.swmansion.detour"'
For full runnable setup and commands, use Examples.