Skip to content
Tolinku
Tolinku
Sign In Start Free
Android Development · · 6 min read

Debugging Android Intent Resolution for Deep Links

By Tolinku Staff
|
Tolinku app links dashboard screenshot for android blog posts

Your App Link should open your app. Instead, it opens the browser. Or it shows a disambiguation dialog. Or it opens the wrong Activity. Or it works on your test device but fails on your colleague's phone.

Android intent resolution is the system that decides which component handles a given URL. When deep links break, the root cause is almost always an intent resolution issue: the system didn't match the URL to your app, or it matched multiple apps, or the verification failed silently. This guide covers the tools and techniques for diagnosing these problems.

For the App Links setup, see the Android App Links complete guide. For testing after debugging, see the testing Android App Links guide.

How Intent Resolution Works

When a user taps a URL on Android, the system:

  1. Checks for verified App Links. If the URL matches a <intent-filter> with android:autoVerify="true" and the app has been verified via Digital Asset Links, the system opens that app directly.
  2. Falls back to the disambiguation dialog. If the URL matches intent filters in multiple apps (or a single unverified app), the system shows a "Open with" dialog.
  3. Falls back to the browser. If no app matches, the URL opens in the default browser.

Problems occur at each step. The debugging tools below help you figure out which step failed and why. For background on the verification process itself, see Android App Link Verification Process.

Tool 1: ADB (Android Debug Bridge)

The most common issue. Your app claims to handle a domain, but the system hasn't verified it.

# Check verification status for your app
adb shell pm get-app-links --user cur com.example.yourapp

Output:

com.example.yourapp:
    ID: 12345678-1234-1234-1234-123456789012
    Signatures: [AB:CD:EF:...]
    Domains:
      links.yourapp.com:
        Status: verified
      yourapp.com:
        Status: legacy_failure

Status values:

  • verified: The domain's .well-known/assetlinks.json was fetched and validated. App Links work.
  • legacy_failure: Verification failed. The system couldn't fetch or validate the asset links file.
  • none: The app declares the domain but hasn't attempted verification (or the device hasn't re-verified).
  • restored: Verification was restored from a backup.

Force Re-Verification

If the status is wrong, force the system to re-verify:

# Reset and re-verify all App Links for your app
adb shell pm set-app-links --package com.example.yourapp 0 all

# Then trigger verification
adb shell pm verify-app-links --re-verify com.example.yourapp

Wait 10-30 seconds, then check the status again.

Test a URL via ADB

Simulate tapping a URL to see how the system resolves it:

# Open a URL as if the user tapped it
adb shell am start -a android.intent.action.VIEW \
  -d "https://links.yourapp.com/promo/summer" \
  -c android.intent.category.BROWSABLE

If the correct Activity opens, intent resolution is working. If the browser opens or a dialog appears, something is wrong.

Dump Intent Filters

See all intent filters registered by your app:

# List all intent filters for your package
adb shell dumpsys package com.example.yourapp | grep -A 20 "intent-filter"

This shows exactly what the system thinks your app handles. Compare it to your AndroidManifest.xml to spot mismatches.

Tool 2: Logcat

Filter for Intent Resolution

# Watch intent resolution in real time
adb logcat -s "IntentResolver" "PackageManager" "AppLinksService"

When you tap a URL, logcat shows:

  • Which apps matched the intent
  • Whether verification was checked
  • Which app was selected
# Watch for DAL verification events
adb logcat -s "SingleV" "IntentFilterVerification"

This shows the HTTP request to your .well-known/assetlinks.json and whether the response was valid.

Common Logcat Messages

# Successful verification
I/IntentFilterVerification: Verification success for links.yourapp.com

# Failed verification (common errors)
W/IntentFilterVerification: Verification failure for links.yourapp.com
E/SingleV: Error fetching https://links.yourapp.com/.well-known/assetlinks.json: 404

# Intent resolution chose browser over app
D/IntentResolver: Resolved to com.android.chrome for https://links.yourapp.com/path

Tool 3: Android Studio

Android Studio includes a built-in App Link Assistant (Tools > App Links Assistant) that:

  1. Scans your manifest for intent filters and flags issues (missing autoVerify, incorrect schemes, etc.)
  2. Generates your Digital Asset Links file with the correct SHA-256 fingerprints
  3. Tests URLs against your declared intent filters
  4. Validates the asset links file on your server

This is the fastest way to catch manifest configuration errors.

If the wrong Activity is opening, use the Layout Inspector to confirm which Activity is in the foreground. This helps distinguish between "the right Activity opened with the wrong data" and "the wrong Activity opened."

Common Problems and Solutions

Problem 1: Browser Opens Instead of App

Diagnosis checklist:

  1. Is the app installed? Obvious but worth checking on the test device.
  2. Is the domain verified? Run adb shell pm get-app-links --user cur <package> and check the status.
  3. Does the intent filter match? The scheme, host, and path must all match. Common mistakes:
    • Using http instead of https (or missing one)
    • Path prefix doesn't match the actual URL
    • Missing android.intent.category.BROWSABLE
    curl -I "https://links.yourapp.com/.well-known/assetlinks.json"
    # Must return 200 with Content-Type: application/json
    

    Problem 2: Disambiguation Dialog Appears

    This means the link matched multiple apps, or matched your app but isn't verified.

    # Check which apps handle the URL
    adb shell pm query-activities -a android.intent.action.VIEW \
      -d "https://links.yourapp.com/path" -c android.intent.category.BROWSABLE
    

    If multiple apps appear, either:

    • Another app on the device claims the same domain (unlikely but possible)
    • Your app's verification failed, so the system treats it as an unverified link

    Problem 3: Wrong Activity Opens

    Your app has multiple Activities with intent filters, and the wrong one catches the URL.

    <!-- Activity A: handles /products/* -->
    <intent-filter android:autoVerify="true">
        <data android:scheme="https" android:host="links.yourapp.com"
              android:pathPrefix="/products" />
        ...
    </intent-filter>
    
    <!-- Activity B: handles everything else -->
    <intent-filter android:autoVerify="true">
        <data android:scheme="https" android:host="links.yourapp.com" />
        ...
    </intent-filter>
    

    If Activity B is catching /products/123, the pathPrefix filter on Activity A might not be matching. Check:

    • Case sensitivity (paths are case-sensitive)
    • Trailing slashes
    • URL encoding in the path

    Fix: Use a single entry-point Activity that routes internally based on the URL path:

    class DeepLinkRouter : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            val uri = intent.data ?: run {
                finish()
                return
            }
    
            when {
                uri.path?.startsWith("/products") == true -> {
                    val productId = uri.lastPathSegment
                    startActivity(ProductActivity.intent(this, productId))
                }
                uri.path?.startsWith("/profile") == true -> {
                    startActivity(ProfileActivity.intent(this))
                }
                else -> {
                    startActivity(MainActivity.intent(this))
                }
            }
    
            finish()
        }
    }
    

    Verification behavior varies by Android version and device manufacturer:

    • Android 12+: Stricter verification. The asset links file must be fetchable at install time and periodically thereafter.
    • Samsung devices: Samsung Internet has its own deep link handling that can override Chrome's behavior.
    • Xiaomi/MIUI: Some MIUI versions have aggressive link interception that redirects URLs through their own browser.

    Test on at least 3-4 different device/OS combinations.

    If your signing key changes (e.g., switching from upload key to Play App Signing key), the SHA-256 fingerprint in your asset links file won't match.

    # Get the current signing fingerprint
    adb shell pm get-app-links --user cur com.example.yourapp
    # Compare the "Signatures" field with what's in assetlinks.json
    

    Fix: Include both the old and new fingerprints in your asset links file during the transition period. See the Android developer documentation for the correct format.

    Debugging Checklist

    When an App Link isn't working, go through this checklist in order:

    1. adb shell pm get-app-links --user cur <package> shows verified for the domain
    2. curl https://yourdomain/.well-known/assetlinks.json returns 200 with valid JSON
    3. SHA-256 fingerprint in asset links matches adb shell pm get-app-links output
    4. Intent filter in manifest has autoVerify="true", correct scheme/host/path, and BROWSABLE category
    5. adb shell am start -a android.intent.action.VIEW -d "<url>" opens the correct Activity
    6. No other app on the device claims the same domain

    If all 6 pass and it still doesn't work, the issue is likely browser-specific or manufacturer-specific. For a broader set of validation steps, see Testing Android App Links.

    For Tolinku App Links setup, the platform generates and hosts the asset links file automatically. Configure your Android package name and SHA-256 fingerprint in the Tolinku dashboard settings and the verification file is served at the correct path.

Get deep linking tips in your inbox

One email per week. No spam.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.