App Links & Universal Links — Testing & Troubleshooting

A focused checklist to prove your deep links work end-to-end. Run deterministic tests on real devices, verify AASA/assetlinks, read the right logs, and restore deferred context on first launch.

Sanity checks (both platforms)

  • Correct domain: use {YOUR_ID}.sddl.me or your verified custom domain.
  • No redirects for metadata: AASA/assetlinks must respond with HTTP 200 (no 3xx) over HTTPS.
  • Content-Type: serve JSON (e.g., application/json).
  • Reinstall after changes: after editing entitlements (iOS) or fingerprints (Android), delete & reinstall.
  • Cold-start restore: on app launch call SDDL resolve to fetch deferred payload (no link needed at launch).
# iOS — AASA direct
curl -i https://YOUR_DOMAIN/.well-known/apple-app-site-association
# Apple CDN check (replace domain)
# https://app-site-association.cdn-apple.com/a/v1/YOUR_DOMAIN
# Android — Digital Asset Links
curl -i https://YOUR_DOMAIN/.well-known/assetlinks.json

iOS — Universal Links

  1. Associated Domains entitlement: present & installed on device. Reinstall after changes.
  2. AASA availability: reachable at /.well-known/apple-app-site-association (no redirects).
  3. Trigger from trusted surfaces: Notes, Mail, Safari (some in-app browsers rewrite links).
  4. Simulator/Device open:
    xcrun simctl openurl booted "https://YOUR_DOMAIN/path"
  5. Logs to watch: device Console in Xcode → filter swcd / associateddomain for entitlement & AASA parsing messages.

Common iOS symptoms → fixes

  • Opens in Safari, not the app: reinstall app; ensure path matches AASA; open from Safari/Notes.
  • AASA “not found” in logs: serve from /.well-known/, HTTPS only, 200 OK, no auth/redirects.
  • Works once then stops: other apps claimed the domain (“Open in…” choice). Long-press link → “Open in App”.

Android — App Links

  1. Manifest intent-filter: includes android:autoVerify="true" for your host.
  2. assetlinks.json: SDDL publishes based on package + SHA256 fingerprints (add Debug & Release).
  3. Verification status:
    adb shell pm verify-app-links your.package.name
    # Optional reset
    adb shell pm reset-app-links your.package.name
  4. Fire a test intent:
    adb shell am start -W \
     -a android.intent.action.VIEW \
     -d "https://YOUR_DOMAIN/path" your.package.name
  5. Inspect mapping: adb shell dumpsys package your.package.name | grep -i intent-filter -n

Common Android symptoms → fixes

  • Chooser dialog appears: fix assetlinks.json (host, fingerprints), re-run verify, uninstall conflicting apps.
  • Opens browser, not app: missing/incorrect autoVerify, path mismatch, CDN returns 3xx/4xx for assetlinks.json.
  • Debug works, release fails: release SHA256 not added; ProGuard strips intent filter (check manifest merge).

Network/CDN pitfalls (both)

  • Redirect chains: AASA/assetlinks must be direct 200 (avoid http → https or path rewrites).
  • Headers: send JSON; disable auth & cookies; no HTML error pages for 404/403.
  • Edge cache: metadata can be cached; after updates purge CDN or change URL host to {YOUR_ID}.sddl.me temporarily for tests.
  • Firewall/AdBlock: can block first redirect; test on clean network and real device.

First-launch (deferred) context

To restore intent after install, the app should request resolution on cold start. With SDDL this is a single helper call (no need to pass the store URL back into the app).

  • iOS: call resolve on first launch even if onOpenURL/NSUserActivity didn’t fire.
  • Android: call resolve in onCreate and onNewIntent.
  • Verify payload: log payload keys (campaign, ref, product) and assert routing.

Edge cases by surface

Social / Messengers

  • In-app browsers (FB/IG/TG) may rewrite links. Long-press → “Open in Safari/Browser”.
  • Query params may be stripped by shorteners — prefer full SDDL link or your verified domain.

Email / SMS

  • iOS Mail/Notes are reliable to trigger Universal Links.
  • Some enterprise gateways add tracking params; verify final URL equals your link.

QA test matrix (copy-paste)

# Devices
- iPhone (latest iOS), iPad (optional), Android 12/13/14

# iOS
- Fresh install → tap link from Notes → app opens, routes correctly
- Reinstall after entitlement change → link works again
- AASA reachable (200, JSON, no redirects)
- From Messenger/Social → open in Safari → app opens

# Android
- Debug & Release fingerprints present
- adb verify-app-links → hosts verified
- Intent test opens app without chooser
- assetlinks.json returns 200 JSON

# Deferred
- Uninstall app → tap SDDL link → install → first launch → payload restored & routed

FAQ

Do I need to host AASA/assetlinks myself?

No. SDDL publishes both automatically from your app configuration.

Why does iOS cache old AASA?

iOS caches association data. In practice, deleting & reinstalling refreshes it fastest.

Chooser dialog on Android?

Fix assetlinks.json and verification status; remove conflicting apps during tests.

Related guides

Continue exploring