Why Android 12 Broke Your Deep Links (and How to Fix Verification for Good)

Why Android 12 Broke Your Deep Links (and How to Fix Verification for Good)

By Reggi, 29 Dec 2022

If your users upgraded to Android 12 and suddenly found your shared web links dumping them into Chrome instead of your native views, your deep link architecture just hit Google's strict verification boundary. Prior to API level 31, the operating system relied on a clumsy disambiguation dialog, letting users decide which app handled a given web scheme. Android 12 eliminated that safety net. Unless your domain explicitly validates ownership via cryptographic signatures, the OS defaults straight to the browser.

To bypass that fallback and guarantee seamless navigation directly into your app without user friction, you must implement verified Android App Links.

The Architectural Shift: Deep Links vs. App Links

A standard deep link is simply a URI mechanism connecting a web resource to an internal destination inside an application. However, legacy deep links allow multiple installed applications to claim the same URL pattern, causing the OS to display an "Open with" chooser popup.

Android App Links represent a verified subset of deep links tied directly to an HTTP or HTTPS domain that you own. Once the Android subsystem confirms the domain association, it registers your application as the default handler for those specific URLs, bypassing the chooser dialog entirely.

AttributeStandard Deep LinksAndroid App Links
Target OSAndroid 11 and lower (default behavior)Android 12+ (API 31+) required for direct launch
User PromptDisplays disambiguation dialogLaunches app immediately with zero dialogs
Domain VerificationNone requiredRequires .well-known/assetlinks.json verification
Fallback PathPrompts user or defaults to browserGracefully opens in browser if verification fails

Step 1: Enforce Auto-Verification in the Manifest

Your entry point starts in AndroidManifest.xml. You need to flag your intent filter with android:autoVerify="true". This attribute signals the package manager to initiate domain verification for all hosts listed across your intent filters when the app is installed.

xml
<activity ...> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="http" android:host="www.example.com" /> <data android:scheme="https" /> </intent-filter> </activity>

Including both http and https schemes within the filter ensures that any incoming web URL routing to www.example.com triggers the verified routing mechanism.


Step 2: Extract Your Signing Fingerprint and Build the Statement

Verification relies on the Digital Asset Links protocol. The host domain must publish a JSON payload proving that the application holding your exact package name and release signing key is authorized to handle its traffic.

First, extract the SHA256 fingerprint from your release keystore using the standard keytool utility:

bash
keytool -list -v -keystore my-release-key.keystore

Locate the SHA256 string in the output, along with your applicationId (declared in your build.gradle file).

Next, construct the assetlinks.json file. It must define the relation delegate_permission/common.handle_all_urls targeting your application ID and signing certificate:

json
[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "com.example", "sha256_cert_fingerprints": ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"] } }]

Step 3: Deploy the Digital Asset Links File

Publish the generated payload to your web server inside the .well-known directory at the root level of your domain (alongside your main entry scripts such as index.php):

text
https://example.com/.well-known/assetlinks.json

The endpoint must be publicly accessible, served over HTTPS, and return a clean 200 OK status without any redirects.


Step 4: Verification and Diagnostics

Do not wait for production rollouts to discover broken associations. Verify your live configuration using official debugging tools before distributing your build:

  1. Digital Asset Links Tool: Validate your hosted statement using the web-based Statement List Generator and Tester.
  2. Android Studio Profiling: Test domain declarations and intent handling directly within your IDE workflow. For step-by-step IDE instructions, reference the guide on Verifying Deep Links on Android Using Android Studio.
  3. Official Documentation: Review manual verification diagnostics outlined in the Android Developers Guide.

Once your manifest carries android:autoVerify="true" and your web server delivers a valid assetlinks.json, Android 12+ devices will automatically route incoming traffic directly into your activity lifecycle, eliminating the disambiguation modal entirely.


Popular Reads