{"id":1261,"date":"2026-05-30T13:00:00","date_gmt":"2026-05-30T18:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1261"},"modified":"2026-03-07T03:49:02","modified_gmt":"2026-03-07T08:49:02","slug":"android-13-14-deep-link-updates","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/android-13-14-deep-link-updates\/","title":{"rendered":"Android 13 and 14 Deep Link Updates"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Each Android version adjusts how deep links and App Links behave. Android 12 made the biggest changes in recent years (mandatory verification, web intent changes). Android 13 and 14 continued that trajectory with more refinements to intent handling, verification behavior, and user-facing link controls.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide covers the deep linking changes in Android 13 (API 33) and Android 14 (API 34) that affect how your app handles and receives links. For the Android 12 changes, see <a href=\"https:\/\/tolinku.com\/blog\/android-12-app-links-changes\/\">Android 12+ App Links changes<\/a>. For the full App Links setup, see the <a href=\"https:\/\/tolinku.com\/blog\/android-app-links-complete-guide\/\">Android App Links complete guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Android 13 (API 33) Changes<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Intent Filter Matching Changes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 13 made intent filter matching stricter for intents that target specific components.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What changed:<\/strong> When an intent explicitly targets a component (via <code>setComponent()<\/code> or <code>setClassName()<\/code>), the system now validates that the component&#39;s intent filter actually matches the intent&#39;s action, data, and categories. Previously, explicit intents bypassed filter matching entirely.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Impact on deep linking:<\/strong> If your app sends explicit intents to internal Activities for deep link routing, those Activities must now have matching intent filters. This catches a common mistake where developers add explicit intents to Activities that don&#39;t declare the correct filters.<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;!-- This Activity MUST have an intent filter that matches the intent --&gt;\n&lt;activity\n    android:name=&quot;.ProductDetailActivity&quot;\n    android:exported=&quot;true&quot;&gt;\n    &lt;intent-filter&gt;\n        &lt;action android:name=&quot;android.intent.action.VIEW&quot; \/&gt;\n        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; \/&gt;\n        &lt;data android:scheme=&quot;https&quot;\n              android:host=&quot;yourapp.com&quot;\n              android:pathPrefix=&quot;\/products&quot; \/&gt;\n    &lt;\/intent-filter&gt;\n&lt;\/activity&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Photo Picker Impact on Share Links<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 13 introduced the <a href=\"https:\/\/developer.android.com\/training\/data-storage\/shared\/photopicker\" rel=\"nofollow noopener\" target=\"_blank\">Photo Picker<\/a>, which changes how apps share images. While not directly a deep linking change, it affects apps that generate shareable content with deep link overlays (like achievement cards or promotional images with embedded links).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Photo Picker doesn&#39;t pass along custom metadata from shared images, so if your app relies on image metadata for deep link attribution, you need an alternative approach (like embedding the link in the share text alongside the image).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Per-App Language Preferences<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 13 added <a href=\"https:\/\/developer.android.com\/guide\/topics\/resources\/app-languages\" rel=\"nofollow noopener\" target=\"_blank\">per-app language preferences<\/a>. This affects deep link landing screens: when a user opens a deep link, the app should respect their per-app language preference, not the system locale.<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">\/\/ Get the user&#39;s per-app language preference\nval appLocale = AppCompatDelegate.getApplicationLocales()\n\n\/\/ Apply it when rendering deep link content\nfun onDeepLinkReceived(uri: Uri) {\n    val locale = appLocale.toLanguageTags()\n    loadContent(uri.path, locale)\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Notification Permission (POST_NOTIFICATIONS)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 13 requires the <a href=\"https:\/\/developer.android.com\/develop\/ui\/views\/notifications\/notification-permission\" rel=\"nofollow noopener\" target=\"_blank\">POST_NOTIFICATIONS<\/a> runtime permission. This affects deep linking workflows that send notifications as part of the referral or engagement flow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your app sends push notifications when a referral is completed or when a deep link campaign triggers a follow-up, request the notification permission before attempting to send:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">\/\/ Check and request notification permission (Android 13+)\nif (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.TIRAMISU) {\n    if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)\n        != PackageManager.PERMISSION_GRANTED) {\n        requestPermissions(\n            arrayOf(Manifest.permission.POST_NOTIFICATIONS),\n            REQUEST_NOTIFICATION_PERMISSION\n        )\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Without this permission, notifications fail silently. Users who arrived via deep links and expected a notification (e.g., &quot;We&#39;ll notify you when your referral reward is ready&quot;) won&#39;t receive it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Android 14 (API 34) Changes<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Stricter Intent Handling<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 14 further tightened intent handling with several changes that affect deep linking:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Implicit intent restrictions:<\/strong> Apps targeting API 34 cannot send implicit intents to internal components. If your app routes deep links by broadcasting implicit intents between Activities or Services, you must switch to explicit intents.<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">\/\/ BROKEN on Android 14 (targeting API 34): implicit intent to internal component\nval intent = Intent(&quot;com.example.app.DEEP_LINK&quot;)\nintent.putExtra(&quot;url&quot;, deepLinkUrl)\nsendBroadcast(intent) \/\/ Fails silently\n\n\/\/ FIX: use explicit intent\nval intent = Intent(this, DeepLinkReceiver::class.java)\nintent.putExtra(&quot;url&quot;, deepLinkUrl)\nsendBroadcast(intent) \/\/ Works\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Exported receivers require filters:<\/strong> Any receiver that&#39;s exported must have an intent filter. This was a best practice before; now it&#39;s enforced. If your app has a broadcast receiver for deep link events without an intent filter, it will crash on Android 14.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Link Verification Improvements<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 14 improved the Digital Asset Links verification process:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Faster re-verification.<\/strong> The system re-verifies App Links more frequently and handles server errors more gracefully. On Android 12-13, a single verification failure could leave your app in an unverified state until the user cleared data or reinstalled. Android 14 retries more aggressively.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Better error reporting.<\/strong> The <code>adb shell pm get-app-links<\/code> command provides more detailed status information on Android 14, making it easier to diagnose verification failures.<\/p>\n\n\n\n<pre><code class=\"language-bash\"># Android 14 provides more detail\nadb shell pm get-app-links --user cur com.example.app\n# Now shows verification timestamp, failure reason, and retry status\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Credential Manager Integration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 14 introduced the <a href=\"https:\/\/developer.android.com\/identity\/sign-in\/credential-manager\" rel=\"nofollow noopener\" target=\"_blank\">Credential Manager<\/a> API, which unifies passkeys, passwords, and federated sign-in. This intersects with deep linking when:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A deep link triggers a sign-in flow (e.g., a magic link email).<\/li>\n<li>The app needs to authenticate the user before showing deep-linked content.<\/li>\n<li>A referral deep link requires account creation.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The Credential Manager simplifies the sign-in step, reducing friction in deep link flows that require authentication:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">\/\/ Use Credential Manager for deep link sign-in flows\nsuspend fun handleDeepLinkWithAuth(uri: Uri) {\n    val credentialManager = CredentialManager.create(context)\n\n    try {\n        val result = credentialManager.getCredential(\n            context,\n            GetCredentialRequest(listOf(GetPasswordOption()))\n        )\n        \/\/ User authenticated; proceed with deep link content\n        navigateToContent(uri)\n    } catch (e: NoCredentialException) {\n        \/\/ No saved credentials; show sign-up flow\n        navigateToSignUp(uri)\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Predictive Back Gesture<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 14 expanded the <a href=\"https:\/\/developer.android.com\/guide\/navigation\/custom-back\/predictive-back-gesture\" rel=\"nofollow noopener\" target=\"_blank\">predictive back gesture<\/a> API. When a user opens your app via a deep link and then swipes back, the predictive back animation should show where they&#39;ll go (the previous app, not a blank screen).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For deep link Activities, handle the back gesture correctly:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">class DeepLinkActivity : AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        \/\/ Enable predictive back\n        onBackPressedDispatcher.addCallback(this) {\n            \/\/ If this was opened from another app via deep link,\n            \/\/ finish() returns to the calling app\n            finish()\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Partial Screen Sharing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android 14 allows <a href=\"https:\/\/developer.android.com\/about\/versions\/14\/features#partial-screen-sharing\" rel=\"nofollow noopener\" target=\"_blank\">partial screen sharing<\/a>. Users can share a single app window instead of the entire screen. This doesn&#39;t directly change deep link behavior, but it&#39;s worth noting: if your app generates shareable content with deep links embedded (QR codes, share cards), the content should be within the app window, not in system overlays.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Migration Checklist<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Targeting API 33 (Android 13)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><input disabled=\"\" type=\"checkbox\"> All Activities that receive deep links have matching intent filters<\/li>\n<li><input disabled=\"\" type=\"checkbox\"> Notification permission requested before sending referral\/deep link notifications<\/li>\n<li><input disabled=\"\" type=\"checkbox\"> Per-app language preferences respected in deep link content screens<\/li>\n<li><input disabled=\"\" type=\"checkbox\"> Share flows work correctly with Photo Picker (no reliance on image metadata for attribution)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Targeting API 34 (Android 14)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><input disabled=\"\" type=\"checkbox\"> No implicit intents sent to internal components for deep link routing<\/li>\n<li><input disabled=\"\" type=\"checkbox\"> All exported receivers have intent filters<\/li>\n<li><input disabled=\"\" type=\"checkbox\"> Back gesture handling works correctly for deep link Activities<\/li>\n<li><input disabled=\"\" type=\"checkbox\"> Credential Manager integrated for deep link sign-in flows (if applicable)<\/li>\n<li><input disabled=\"\" type=\"checkbox\"> Test App Links verification on Android 14 devices<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Testing Across Android Versions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Deep link behavior varies enough across Android versions that you should test on at least:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Android Version<\/th>\n<th>Key Behavior to Test<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>Android 11 (API 30)<\/td>\n<td>Package visibility restrictions<\/td>\n<\/tr>\n<tr>\n<td>Android 12 (API 31)<\/td>\n<td>Mandatory App Link verification, web intent changes<\/td>\n<\/tr>\n<tr>\n<td>Android 13 (API 33)<\/td>\n<td>Stricter intent filter matching, notification permissions<\/td>\n<\/tr>\n<tr>\n<td>Android 14 (API 34)<\/td>\n<td>Implicit intent restrictions, improved verification<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Use the <a href=\"https:\/\/developer.android.com\/studio\/run\/emulator\" rel=\"nofollow noopener\" target=\"_blank\">Android Emulator<\/a> to test across versions without physical devices. For App Links verification testing, use a physical device or an emulator with Google Play services.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For <a href=\"https:\/\/tolinku.com\/features\/deep-linking\">Tolinku deep links<\/a>, the platform&#39;s redirect chain is compatible with all Android versions. The App Links verification file is served at the correct path with the right content type, which resolves many of the verification issues that the newer Android versions are stricter about. Configure your Android settings in the <a href=\"https:\/\/tolinku.com\/docs\/developer\/app-links\/\">Tolinku dashboard<\/a> to get started.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For the complete intent filter configuration guide, see the <a href=\"https:\/\/tolinku.com\/blog\/android-intent-filters-deep-links\/\">Android intent filters guide<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Stay current with Android 13 and 14 deep linking changes. Updated intent handling, per-app language, notification permissions, and link verification behavior.<\/p>\n","protected":false},"author":2,"featured_media":1260,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Android 13 and 14 Deep Link Updates You Need to Know","rank_math_description":"Stay current with Android 13 and 14 deep linking changes. Updated intent handling, notification permissions, and link verification behavior.","rank_math_focus_keyword":"android 13 14 deep links","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-android-13-14-deep-link-updates.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-android-13-14-deep-link-updates.png","footnotes":""},"categories":[10],"tags":[25,321,322,23,20,184,69],"class_list":["post-1261","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","tag-android","tag-android-13","tag-android-14","tag-app-links","tag-deep-linking","tag-intent-filters","tag-mobile-development"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1261","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=1261"}],"version-history":[{"count":4,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1261\/revisions"}],"predecessor-version":[{"id":2572,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1261\/revisions\/2572"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1260"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}