# Testing & Troubleshooting

Testing deferred linking on Android has platform constraints, mainly around install referrer availability and app-link verification state.

## Deferred flow constraints

- Deferred matching is intended for first-launch flow after install.
- Deterministic matching uses Play Install Referrer `click_id` when available.
- If install referrer is unavailable, SDK falls back to probabilistic matching.
- Repeated deferred attempts in same install/session return `NotFirstLaunch`.

## Recommended deferred test flow

1. Uninstall the app from the device or emulator.
2. Open a Detour link in a browser.
3. Install and launch the app.
4. Verify `LinkResult.Success` with `type = DEFERRED`, or expected fallback (`NoLink` / `Error`).
5. Relaunch the app and confirm the deferred link is not consumed again, that is `LinkResult.NotFirstLaunch`.

:::note[Missing `click_id`]
If you encounter click_id missing in your build see limitations section [Play Store referrer missing](https://detour.swmansion.com/docs/platform/architecture/architecture-limitations#play-store-referrer-missing)
:::

## Testing app links and scheme links

For app-link/scheme integration (`LinkProcessingMode.ALL`), verify both cold and warm starts.

### App Link via ADB

```bash
adb shell am start -a android.intent.action.VIEW \
  -d "https://<your-link-domain>/products/42" \
  <your.package.name>
```

Expected: `LinkResult.Success` with `type = VERIFIED`.

### Custom scheme via ADB

```bash
adb shell am start -a android.intent.action.VIEW \
  -d "myapp://products/42" \
  <your.package.name>
```

Expected: `LinkResult.Success` with `type = SCHEME` (only when `LinkProcessingMode.ALL`).

### App Link verification and the SHA-256 fingerprint

An `autoVerify` App Link opens your app only if the Dashboard SHA-256 matches the key that signed **the installed APK**:

| How the app is installed                          | Signed with                  | Where to read the SHA-256                                    |
| :---------------------------------------------------- | :------------------------------- | :---------------------------------------------------------------- |
| Google Play, any track                            | Play App Signing key         | Play Console → **Protected with Play** → **Manage Play app signing** → *App signing key certificate* |
| Android Studio run / `./gradlew assembleDebug`    | AGP default debug keystore   | `keytool -list -v -keystore ~/.android/debug.keystore -storepass android`, or `./gradlew signingReport` |
| `./gradlew assembleRelease` with your own config  | Your release keystore        | `keytool -list -v -keystore <path-to-your.keystore>`, or `./gradlew signingReport` |

`./gradlew signingReport` prints the `Store:` path each variant really uses, so it stays correct when a project overrides `signingConfigs.debug`. To check a binary directly: `apksigner verify --print-certs app-debug.apk`.

Then check what the device made of it:

```bash
adb shell pm verify-app-links --re-verify <your.package.name>
adb shell pm get-app-links <your.package.name>   # expect: verified
```

The complete procedure is described in [Finding your Android SHA-256 fingerprint](https://detour.swmansion.com/docs/platform/fundamentals/universal-app-links#finding-your-android-sha-256-fingerprint).

## Common issues

<details id="detour-sdk-not-initialized">
<summary>`Detour SDK not initialized`</summary>

`Detour.initialize(...)` was not called before `processLink()` / `getDeferredLink()`.

</details>

<details id="immediate-nolink">
<summary>Immediate `NoLink`</summary>

No matching click was found. Verify the link click happened before the install.

</details>

<details id="click-limit-error">
<summary>App/Universal link returns `NoLink` despite a valid click</summary>

Your plan's click limit may be exceeded. Look for `[Detour:CLICK_LIMIT_ERROR]` in logcat. See [Click limits](https://detour.swmansion.com/docs/sdk/android/sdk-usage#click-limits).

</details>

<details id="always-notfirstlaunch">
<summary>Always `NotFirstLaunch`</summary>

The first-launch flag is already stored. Reinstall the app to test the deferred flow again.

</details>

<details id="app-links-open-browser">
<summary>App links open the browser instead of the app</summary>

- Check the Dashboard app-link domain config and the manifest intent-filter alignment.
- Confirm the Dashboard SHA-256 matches the key that signed the installed APK. See [App Link verification and the SHA-256 fingerprint](#app-link-verification-and-the-sha-256-fingerprint).

</details>

<details id="custom-scheme-not-handled">
<summary>Custom scheme not handled</summary>

Verify the manifest `<data android:scheme="..." />` entry and that `linkProcessingMode` is `LinkProcessingMode.ALL`.

</details>

<details id="analytics-events-not-visible">
<summary>Analytics events not visible</summary>

Ensure `apiKey` and `appId` are valid, and call `DetourAnalytics` only after SDK initialization.

</details>

## Debugging

Use logcat while testing:

```bash
adb logcat | grep -i detour
```

Useful tags from SDK internals:

- `Detour`
- `DetourApiClient`
- `InstallReferrerHelper`
- `DetourAnalytics`

For complete end-to-end sample flows, use [Examples](https://detour.swmansion.com/docs/sdk/android/examples).