Quizzr Logo

Deep Linking

Implementing Android App Links with Digital Asset Links

How to verify domain ownership via the assetlinks.json file to ensure Android automatically opens your app instead of the browser.

Mobile DevelopmentIntermediate18 min read

The Evolution of Mobile Navigation and the Trust Problem

In the early days of mobile development, bridging the gap between a web browser and a native application was a disjointed experience. Developers relied on custom URI schemes like myapp://profile to trigger app launches, but these schemes lacked a central authority. If two different applications claimed the same custom scheme, the operating system had no way to determine which one was the legitimate owner.

This ambiguity led to the infamous disambiguation dialog, which forces users to choose an application manually every time they click a link. This friction point often results in significant user drop-off during critical workflows like password resets or email verifications. For a modern software engineer, the goal is to remove these barriers and provide a seamless transition from a URL to a specific screen within the app.

Android App Links were introduced to solve this exact problem by establishing a cryptographically backed relationship between a web domain and a mobile application. By proving that you own both the website and the app, you grant the Android operating system permission to bypass the selection dialog entirely. This process ensures that your app is the exclusive handler for your specific domain, creating a secure and reliable deep linking infrastructure.

The primary objective of Android App Links is not just to open the app, but to verify that the app has the legal right to represent the content hosted on a specific web domain.

Understanding this underlying trust model is essential before diving into the configuration files. Without verification, your deep links are merely suggestions to the operating system rather than definitive instructions. By implementing the Digital Asset Links protocol, you transform these suggestions into a hardened, predictable navigation system for your users.

Why Manual Selection Dialogs Kill Conversion

Every extra tap required to reach a destination in a mobile app decreases the likelihood of a successful conversion. When a user clicks a promotional link in an email, they expect to land on the product page, not to be asked which browser or app they want to use. This decision point creates cognitive load and can confuse less tech-savvy users who may not understand why they are being asked.

Furthermore, if a malicious app claims your custom URI scheme, it could potentially intercept sensitive data by tricking users into opening the wrong application. App Links mitigate this security risk by requiring a digital signature check that a malicious actor cannot forge without access to your web server. This makes the verification process a security requirement as much as a user experience improvement.

Configuring the Android Manifest for Auto-Verification

Once your server-side configuration is in place, you must instruct the Android operating system to attempt the verification process. This is done within the AndroidManifest.xml file by adding a specific attribute to your intent filters. The autoVerify attribute is a boolean flag that tells the system to validate the relationship between the app and the domains listed in the filter.

It is important to understand that the verification process is an all-or-nothing operation for each intent filter. If your intent filter contains multiple host entries, Android will attempt to verify every single one of them. If even one domain fails to host the assetlinks.json file correctly, the entire intent filter will fail verification, and the app will revert to showing the disambiguation dialog.

xmlManifest Intent Filter Configuration
1<activity android:name=".ui.DeepLinkActivity">
2    <!-- The autoVerify attribute is crucial for App Links -->
3    <intent-filter android:autoVerify="true">
4        <action android:name="android.intent.action.VIEW" />
5        <category android:name="android.intent.category.DEFAULT" />
6        <category android:name="android.intent.category.BROWSABLE" />
7
8        <!-- Define the web domains to be handled -->
9        <data android:scheme="https" />
10        <data android:host="www.example-fintech.com" />
11        <data android:host="api.example-fintech.com" />
12        <data android:pathPrefix="/transfer" />
13    </intent-filter>
14</activity>

By setting the scheme to https, you ensure that the app only intercepts secure links. While you can technically include the http scheme, Android's verification logic primarily focuses on secure connections. Modern best practices suggest moving all web traffic to HTTPS, which aligns perfectly with the security requirements of the Digital Asset Links protocol.

Handling Multiple Hostnames and Subdomains

Many large-scale applications operate across various subdomains, such as shop.example.com and blog.example.com. Each of these subdomains must be explicitly listed in the intent filter if you want the app to handle their specific paths. Remember that the Android system treats each unique host as a separate verification target that requires its own assetlinks.json file.

If you have a large number of subdomains, managing the verification files can become a logistical challenge. You should consider using a wildcard or a centralized redirection strategy on the web side, but ensure that the final destination of the .well-known path always returns the correct JSON. Consistency across all entry points is the key to maintaining a reliable deep linking experience for the user base.

Mapping URLs to Internal App Logic

Once the system verifies the link and opens your app, your activity must be prepared to parse the incoming URI and navigate to the correct screen. This usually involves extracting path segments or query parameters from the intent data. In the provided example, any URL starting with /transfer would be directed to the DeepLinkActivity, which would then extract the transaction ID.

A common pitfall is failing to handle scenarios where the app is already running in the background. You should ensure that your activity handles new intents properly by overriding the onNewIntent method. This prevents the system from creating multiple instances of the same activity and ensures a smooth transition within the app's internal navigation stack.

Deployment, Testing, and Troubleshooting

Verifying App Links can be a frustrating process because the verification happens silently in the background during app installation. There is no immediate visual feedback in the UI to tell you if the process succeeded or failed. Developers must rely on command-line tools and system logs to diagnose issues with the verification handshake.

The Android Debug Bridge provides a powerful set of commands to inspect the state of package verification on a connected device. By querying the package manager, you can see the status of every domain your app has attempted to verify. This is the only way to confirm that the system has successfully processed your assetlinks.json file and granted the app default handler status.

bashVerifying App Link Status via ADB
1# Check the verification status for a specific package
2adb shell dumpsys package d | grep -A 10 "com.production.fintech.app"
3
4# Force the system to run verification immediately
5adb shell pm set-app-links --state verified com.production.fintech.app all

If you see a status of ask or undefined, it means the verification failed or has not yet been attempted. Common causes include network timeouts, invalid JSON syntax, or a mismatch between the certificate fingerprint in the file and the one used to sign the APK. You should also check the logcat output during installation for any entries from the IntentFilterVerifier department.

The Impact of Android Versioning on Verification

It is important to note that the behavior of App Links has evolved significantly across different Android versions. Starting with Android 12, the system has become much stricter about verification requirements. If verification fails for a domain on Android 12 or higher, the system will never show the disambiguation dialog; it will simply open the link in the browser by default.

This change makes successful verification even more critical for maintaining a high-quality user experience. Developers targeting modern Android versions must ensure that their server infrastructure is robust enough to handle the verification requests. Relying on legacy deep linking behavior is no longer a viable strategy for apps that require seamless web-to-app transitions.

Common Pitfalls and Performance Considerations

A frequent mistake is hosting the assetlinks.json file on a server that requires a specific User-Agent or blocks automated requests. The Android system's verification agent may not identify itself like a standard browser, which can trigger security filters or firewalls. You should white-list the verification path to ensure it is globally accessible to all requests.

Performance is another factor to consider, as a slow server response can cause the verification process to time out. Since verification happens at install time, a slow response won't impact the user's immediate experience, but it will prevent the App Link from working until the next time the system attempts a check. Regularly monitor your server logs to ensure that the .well-known path is being served quickly and reliably.

We use cookies

Necessary cookies keep the site working. Analytics and ads help us improve and fund Quizzr. You can manage your preferences.