{"id":1249,"date":"2026-05-29T13:00:00","date_gmt":"2026-05-29T18:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1249"},"modified":"2026-03-07T04:45:44","modified_gmt":"2026-03-07T09:45:44","slug":"debugging-android-intent-resolution","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/debugging-android-intent-resolution\/","title":{"rendered":"Debugging Android Intent Resolution for Deep Links"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">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&#39;s phone.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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&#39;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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For the App Links setup, see the <a href=\"https:\/\/tolinku.com\/blog\/android-app-links-complete-guide\/\">Android App Links complete guide<\/a>. For testing after debugging, see the <a href=\"https:\/\/tolinku.com\/blog\/testing-android-app-links\/\">testing Android App Links guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Intent Resolution Works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a user taps a URL on Android, the system:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Checks for verified App Links.<\/strong> If the URL matches a <code>&lt;intent-filter&gt;<\/code> with <code>android:autoVerify=&quot;true&quot;<\/code> and the app has been verified via Digital Asset Links, the system opens that app directly.<\/li>\n<li><strong>Falls back to the disambiguation dialog.<\/strong> If the URL matches intent filters in multiple apps (or a single unverified app), the system shows a &quot;Open with&quot; dialog.<\/li>\n<li><strong>Falls back to the browser.<\/strong> If no app matches, the URL opens in the default browser.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">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 <a href=\"https:\/\/tolinku.com\/blog\/android-app-link-verification-process\/\">Android App Link Verification Process<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tool 1: ADB (Android Debug Bridge)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Check App Link Verification Status<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The most common issue. Your app claims to handle a domain, but the system hasn&#39;t verified it.<\/p>\n\n\n\n<pre><code class=\"language-bash\"># Check verification status for your app\nadb shell pm get-app-links --user cur com.example.yourapp\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Output:<\/p>\n\n\n\n<pre><code>com.example.yourapp:\n    ID: 12345678-1234-1234-1234-123456789012\n    Signatures: [AB:CD:EF:...]\n    Domains:\n      links.yourapp.com:\n        Status: verified\n      yourapp.com:\n        Status: legacy_failure\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Status values:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>verified<\/code>: The domain&#39;s <code>.well-known\/assetlinks.json<\/code> was fetched and validated. App Links work.<\/li>\n<li><code>legacy_failure<\/code>: Verification failed. The system couldn&#39;t fetch or validate the asset links file.<\/li>\n<li><code>none<\/code>: The app declares the domain but hasn&#39;t attempted verification (or the device hasn&#39;t re-verified).<\/li>\n<li><code>restored<\/code>: Verification was restored from a backup.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Force Re-Verification<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If the status is wrong, force the system to re-verify:<\/p>\n\n\n\n<pre><code class=\"language-bash\"># Reset and re-verify all App Links for your app\nadb shell pm set-app-links --package com.example.yourapp 0 all\n\n# Then trigger verification\nadb shell pm verify-app-links --re-verify com.example.yourapp\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Wait 10-30 seconds, then check the status again.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Test a URL via ADB<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Simulate tapping a URL to see how the system resolves it:<\/p>\n\n\n\n<pre><code class=\"language-bash\"># Open a URL as if the user tapped it\nadb shell am start -a android.intent.action.VIEW \\\n  -d &quot;https:\/\/links.yourapp.com\/promo\/summer&quot; \\\n  -c android.intent.category.BROWSABLE\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the correct Activity opens, intent resolution is working. If the browser opens or a dialog appears, something is wrong.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dump Intent Filters<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">See all intent filters registered by your app:<\/p>\n\n\n\n<pre><code class=\"language-bash\"># List all intent filters for your package\nadb shell dumpsys package com.example.yourapp | grep -A 20 &quot;intent-filter&quot;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This shows exactly what the system thinks your app handles. Compare it to your <code>AndroidManifest.xml<\/code> to spot mismatches.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tool 2: Logcat<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Filter for Intent Resolution<\/h3>\n\n\n\n<pre><code class=\"language-bash\"># Watch intent resolution in real time\nadb logcat -s &quot;IntentResolver&quot; &quot;PackageManager&quot; &quot;AppLinksService&quot;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When you tap a URL, logcat shows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Which apps matched the intent<\/li>\n<li>Whether verification was checked<\/li>\n<li>Which app was selected<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Filter for Digital Asset Links<\/h3>\n\n\n\n<pre><code class=\"language-bash\"># Watch for DAL verification events\nadb logcat -s &quot;SingleV&quot; &quot;IntentFilterVerification&quot;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This shows the HTTP request to your <code>.well-known\/assetlinks.json<\/code> and whether the response was valid.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Common Logcat Messages<\/h3>\n\n\n\n<pre><code># Successful verification\nI\/IntentFilterVerification: Verification success for links.yourapp.com\n\n# Failed verification (common errors)\nW\/IntentFilterVerification: Verification failure for links.yourapp.com\nE\/SingleV: Error fetching https:\/\/links.yourapp.com\/.well-known\/assetlinks.json: 404\n\n# Intent resolution chose browser over app\nD\/IntentResolver: Resolved to com.android.chrome for https:\/\/links.yourapp.com\/path\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Tool 3: Android Studio<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">App Link Assistant<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android Studio includes a built-in <a href=\"https:\/\/developer.android.com\/studio\/write\/app-link-indexing\" rel=\"nofollow noopener\" target=\"_blank\">App Link Assistant<\/a> (Tools &gt; App Links Assistant) that:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Scans your manifest<\/strong> for intent filters and flags issues (missing <code>autoVerify<\/code>, incorrect schemes, etc.)<\/li>\n<li><strong>Generates your Digital Asset Links file<\/strong> with the correct SHA-256 fingerprints<\/li>\n<li><strong>Tests URLs<\/strong> against your declared intent filters<\/li>\n<li><strong>Validates the asset links file<\/strong> on your server<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This is the fastest way to catch manifest configuration errors.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Layout Inspector for Deep Link Targets<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If the wrong Activity is opening, use the Layout Inspector to confirm which Activity is in the foreground. This helps distinguish between &quot;the right Activity opened with the wrong data&quot; and &quot;the wrong Activity opened.&quot;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Problems and Solutions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 1: Browser Opens Instead of App<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Diagnosis checklist:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Is the app installed?<\/strong> Obvious but worth checking on the test device.<\/li>\n<li><strong>Is the domain verified?<\/strong> Run <code>adb shell pm get-app-links --user cur &lt;package&gt;<\/code> and check the status.<\/li>\n<li><strong>Does the intent filter match?<\/strong> The scheme, host, and path must all match. Common mistakes:<ul>\n<li>Using <code>http<\/code> instead of <code>https<\/code> (or missing one)<\/li>\n<li>Path prefix doesn&#39;t match the actual URL<\/li>\n<li>Missing <code>android.intent.category.BROWSABLE<\/code><\/li>\n<\/ul>\n\n\n\n<pre><code class=\"language-bash\">curl -I &quot;https:\/\/links.yourapp.com\/.well-known\/assetlinks.json&quot;\n# Must return 200 with Content-Type: application\/json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 2: Disambiguation Dialog Appears<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This means the link matched multiple apps, or matched your app but isn&#39;t verified.<\/p>\n\n\n\n<pre><code class=\"language-bash\"># Check which apps handle the URL\nadb shell pm query-activities -a android.intent.action.VIEW \\\n  -d &quot;https:\/\/links.yourapp.com\/path&quot; -c android.intent.category.BROWSABLE\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If multiple apps appear, either:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Another app on the device claims the same domain (unlikely but possible)<\/li>\n<li>Your app&#39;s verification failed, so the system treats it as an unverified link<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 3: Wrong Activity Opens<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Your app has multiple Activities with intent filters, and the wrong one catches the URL.<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;!-- Activity A: handles \/products\/* --&gt;\n&lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n    &lt;data android:scheme=&quot;https&quot; android:host=&quot;links.yourapp.com&quot;\n          android:pathPrefix=&quot;\/products&quot; \/&gt;\n    ...\n&lt;\/intent-filter&gt;\n\n&lt;!-- Activity B: handles everything else --&gt;\n&lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n    &lt;data android:scheme=&quot;https&quot; android:host=&quot;links.yourapp.com&quot; \/&gt;\n    ...\n&lt;\/intent-filter&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If Activity B is catching <code>\/products\/123<\/code>, the <code>pathPrefix<\/code> filter on Activity A might not be matching. Check:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Case sensitivity (paths are case-sensitive)<\/li>\n<li>Trailing slashes<\/li>\n<li>URL encoding in the path<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fix<\/strong>: Use a single entry-point Activity that routes internally based on the URL path:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">class DeepLinkRouter : AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        val uri = intent.data ?: run {\n            finish()\n            return\n        }\n\n        when {\n            uri.path?.startsWith(&quot;\/products&quot;) == true -&gt; {\n                val productId = uri.lastPathSegment\n                startActivity(ProductActivity.intent(this, productId))\n            }\n            uri.path?.startsWith(&quot;\/profile&quot;) == true -&gt; {\n                startActivity(ProfileActivity.intent(this))\n            }\n            else -&gt; {\n                startActivity(MainActivity.intent(this))\n            }\n        }\n\n        finish()\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 4: Links Work on Some Devices but Not Others<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Verification behavior varies by Android version and device manufacturer:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Android 12+<\/strong>: Stricter verification. The asset links file must be fetchable at install time and periodically thereafter.<\/li>\n<li><strong>Samsung devices<\/strong>: Samsung Internet has its own deep link handling that can override Chrome&#39;s behavior.<\/li>\n<li><strong>Xiaomi\/MIUI<\/strong>: Some MIUI versions have aggressive link interception that redirects URLs through their own browser.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Test on at least 3-4 different device\/OS combinations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 5: Links Stop Working After App Update<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">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&#39;t match.<\/p>\n\n\n\n<pre><code class=\"language-bash\"># Get the current signing fingerprint\nadb shell pm get-app-links --user cur com.example.yourapp\n# Compare the &quot;Signatures&quot; field with what&#39;s in assetlinks.json\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fix<\/strong>: Include both the old and new fingerprints in your asset links file during the transition period. See the <a href=\"https:\/\/developer.android.com\/training\/app-links\/verify-android-applinks\" rel=\"nofollow noopener\" target=\"_blank\">Android developer documentation<\/a> for the correct format.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Debugging Checklist<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When an App Link isn&#39;t working, go through this checklist in order:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>adb shell pm get-app-links --user cur &lt;package&gt;<\/code> shows <code>verified<\/code> for the domain<\/li>\n<li><code>curl https:\/\/yourdomain\/.well-known\/assetlinks.json<\/code> returns 200 with valid JSON<\/li>\n<li>SHA-256 fingerprint in asset links matches <code>adb shell pm get-app-links<\/code> output<\/li>\n<li>Intent filter in manifest has <code>autoVerify=&quot;true&quot;<\/code>, correct scheme\/host\/path, and <code>BROWSABLE<\/code> category<\/li>\n<li><code>adb shell am start -a android.intent.action.VIEW -d &quot;&lt;url&gt;&quot;<\/code> opens the correct Activity<\/li>\n<li>No other app on the device claims the same domain<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">If all 6 pass and it still doesn&#39;t work, the issue is likely browser-specific or manufacturer-specific. For a broader set of validation steps, see <a href=\"https:\/\/tolinku.com\/blog\/testing-android-app-links\/\">Testing Android App Links<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For <a href=\"https:\/\/tolinku.com\/docs\/developer\/app-links\/\">Tolinku App Links setup<\/a>, the platform generates and hosts the asset links file automatically. Configure your Android package name and SHA-256 fingerprint in the <a href=\"https:\/\/tolinku.com\/features\/deep-linking\">Tolinku dashboard settings<\/a> and the verification file is served at the correct path.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Debug deep link intent resolution issues on Android. Use logcat, ADB, and Android Studio to trace link handling, diagnose routing problems, and fix intent filter conflicts.<\/p>\n","protected":false},"author":2,"featured_media":1248,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Debugging Android Intent Resolution for Deep Links on Android","rank_math_description":"Debug deep link intent resolution issues on Android. Use logcat, ADB, and Android Studio to trace link handling and fix routing problems.","rank_math_focus_keyword":"debug android intent resolution","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-debugging-android-intent-resolution.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-debugging-android-intent-resolution.png","footnotes":""},"categories":[10],"tags":[317,25,23,74,20,184,69],"class_list":["post-1249","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","tag-adb","tag-android","tag-app-links","tag-debugging","tag-deep-linking","tag-intent-filters","tag-mobile-development"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1249","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=1249"}],"version-history":[{"count":4,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1249\/revisions"}],"predecessor-version":[{"id":2812,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1249\/revisions\/2812"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1248"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1249"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}