5 Steps for Universal Pattern Links in AndroidManifest 2025
Master Android App Links in 2025! Follow these 5 essential steps to configure universal pattern links in your AndroidManifest and create seamless user experiences.
Alex Ivanov
Senior Android Engineer specializing in app architecture, performance, and seamless user experiences.
Tired of users getting stuck in their mobile browser when they should be landing directly in your app? Seamlessly bridging the gap between your website and your Android application isn't just a nice-to-have anymore; it's a core part of a modern, polished user experience. As we head into 2025, Google's requirements for link verification are only getting smarter and stricter.
This guide will walk you through the five essential steps to master universal pattern links, ensuring your users always get to the right place with a single tap. Let's ditch the disambiguation dialogs and create a truly integrated experience.
Step 1: Build the Foundation with a Verified Intent Filter
Everything starts in your AndroidManifest.xml
. While you might be familiar with basic intent filters for deep linking, Android App Links (the official term for these universal links) require a specific configuration to trigger the automatic verification process.
The key is adding android:autoVerify="true"
to your intent filter. This single attribute tells the Android system to attempt to verify that your app has the authority to handle links from the specified domain. If verification succeeds, your app becomes the default handler for those URLs, opening them instantly without showing the user a choice.
Here’s what a modern, robust intent filter looks like for an activity that handles product links:
<activity
android:name=".ui.ProductActivity"
android:exported="true">
<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="https"
android:host="www.your-awesome-brand.com" />
<!-- More specific path patterns will go here in the next step -->
</intent-filter>
</activity>
Notice a few crucial elements:
android:autoVerify="true"
: The magic switch. Without this, you're just creating a standard deep link.ACTION_VIEW
: This is the standard action for viewing content.CATEGORY_BROWSABLE
: This is essential for the link to be openable from a web browser.https
scheme: App Link verification only works with secure HTTPS URLs. Don't usehttp
.
Step 2: Master Universal Path Patterns
Just matching the host isn't enough. You need to tell the system exactly which URL paths your app can handle. This is where "universal patterns" come into play, giving you incredible flexibility. The <data>
tag supports three attributes for path matching: path
, pathPrefix
, and pathPattern
.
Choosing the right one is critical for creating maintainable and scalable link handling. Let's break them down.
Attribute | Matching Logic | Example | Best For |
---|---|---|---|
android:path |
Exact match | /products |
Specific, static pages like a "/cart" or "/profile" page. |
android:pathPrefix |
Prefix match | /products/ |
Handling entire sections of your site, like all product detail pages (e.g., matches /products/widget-a and /products/widget-b). |
android:pathPattern |
Wildcard pattern | /user/.* |
Complex routing, such as matching user profiles with numerical or string-based IDs. It uses a simplified wildcard syntax. |
A Deeper Dive into pathPattern
The pathPattern
attribute is your most powerful tool. It’s not full RegEx, but it provides two essential wildcards:
*
(asterisk): Matches a sequence of zero or more occurrences of the immediately preceding character. For example,/item/123*
would match/item/12
,/item/123
, and/item/12333
..*
(dot-asterisk): Matches any sequence of zero or more characters. This is the most common and useful pattern. For example,/products/.*
will match any URL that starts with/products/
, like/products/a-cool-gadget
or/products/another/nested/item
.
Here’s how you’d update your manifest to handle specific product and user profile pages:
<!-- Inside your intent-filter -->
<!-- Handles URLs like https://www.your-awesome-brand.com/products/super-widget-123 -->
<data android:scheme="https" android:host="www.your-awesome-brand.com" android:pathPattern="/products/.*" />
<!-- Handles URLs like https://www.your-awesome-brand.com/user/alex-ivanov -->
<data android:scheme="https" android:host="www.your-awesome-brand.com" android:pathPattern="/user/.*" />
Step 3: Host and Validate Your Digital Asset Links JSON
This is the server-side half of the verification equation and a common stumbling block. You must prove you own the domain you listed in your manifest. You do this by hosting a special JSON file at a specific location on your server.
This file is called assetlinks.json
and it must be accessible at:
https://www.your-awesome-brand.com/.well-known/assetlinks.json
The contents of this file create a relationship between your website and your app. The structure is an array of objects, where each object defines a trusted "target" (your app).
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.your.package.name",
"sha256_cert_fingerprints": [
"AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90"
]
}
}
]
Getting the SHA256 Fingerprint
The sha256_cert_fingerprints
value is a unique signature of the certificate you use to sign your app. Crucially, you must use the fingerprint for your production signing key.
- For Google Play App Signing: The easiest and recommended way is to go to your Google Play Console. Navigate to Setup > App integrity. Under the "App signing key certificate" tab, you'll find the SHA-256 certificate fingerprint.
- For local keystores: You can use the
keytool
command-line utility.
Pro Tip: Ensure your server serves theassetlinks.json
file with aContent-Type
ofapplication/json
and that it's accessible without any redirects. A 404 error or a redirect will cause verification to fail silently. You can test this by simply trying to open the URL in your browser.
Step 4: Debug and Verify Like a Pro in 2025
Hoping for the best isn't a strategy. With Android Studio's evolving tools and powerful adb
commands, you can and should test your App Links thoroughly.
Android Studio App Links Assistant
The built-in App Links Assistant (Tools > App Links Assistant) is your best friend. In its 2025 iteration, it's more powerful than ever:
- URL Mapping Editor: Visually add and edit your intent filters.
- Asset File Generation: It can generate the
assetlinks.json
content for you, including pulling the correct SHA-256 fingerprint. - Live Validation: It will test your live
assetlinks.json
file, checking for common errors like incorrect content type, redirects, or HTTPS issues.
Manual Verification with ADB
Sometimes you need to force the system to re-evaluate your links, especially after making a change. You can do this directly from your terminal:
# For Android 12 and higher
adb shell pm verify-app-links --re-verify com.your.package.name
# Check the verification status for your app
adb shell pm get-app-links com.your.package.name
After running the re-verify command, check Logcat for messages from IntentFilterIntentSvc
. You'll see logs indicating whether the verification for each host succeeded or failed, often with a reason for the failure.
Step 5: Gracefully Handle Incoming Links in Your App
Once verification is successful and a user clicks a link, your designated Activity
will launch. The final step is to parse the incoming URL and direct the user to the correct content.
In your Activity
's onCreate
or onNewIntent
method, you can retrieve the data from the intent:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ... your regular setup
handleIntent(intent)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// Handle new link when activity is already open
if (intent != null) {
handleIntent(intent)
}
}
private fun handleIntent(intent: Intent) {
if (intent.action == Intent.ACTION_VIEW) {
val appLinkData: Uri? = intent.data
if (appLinkData != null) {
// Example: for a URL like /products/super-widget-123
val pathSegments = appLinkData.pathSegments
if (pathSegments.size == 2 && pathSegments[0] == "products") {
val productId = pathSegments[1] // "super-widget-123"
// Now navigate to your product screen with this ID
navigateToProduct(productId)
}
}
}
}
Using uri.pathSegments
is a clean way to break the URL path into a list of its components, making it easy to build routing logic. This completes the journey, taking the user from a web link to specific, relevant content within your app.
Key Takeaways for 2025
Implementing universal pattern links is a powerful way to enhance user engagement. Remember these key principles:
autoVerify
is Mandatory: Always useandroid:autoVerify="true"
for a true App Link experience.- Leverage
pathPattern
: UsepathPattern
with.*
for maximum flexibility in handling dynamic URL structures.- Perfect Your
assetlinks.json
: Double-check your package name, SHA-256 fingerprint, and ensure the file is hosted correctly at the/.well-known/
path. This is the #1 source of failure.- Test, Test, Test: Use the App Links Assistant and
adb
commands to validate your setup before releasing to production.