If you need more information around specifically why verification may have failed, here’s a few bonus tips on debugging.

Check out Google’s Digital Asset Link API. You can call this endpoint to check if your domain verifies properly and returns the right payload.

Try looking at the logs from SingleHostAsyncVerifier . This class is the one responsible for querying your domains for your assetlinks.json file, and matching up signatures. This may give you more insight in to why certain hosts are failing.

Tip 3. Use android:priority to favour the more relevant app

Alright, you’ve structured your app’s intent filters nicely, and have your app links verifying correctly. Cool. But what if you have a main application — one used for most functionality, as well as a couple of other, more specialised apps? This probably isn’t a common use case, but it’s something which may be useful.

Picture this. Your main app catches a URL and provides the user with a pretty alright experience, but your more specialised app has a much more detailed and better user experience on offer. You want to handle the URL in both places, as it’s more likely users have the main app installed. You also want App Links to keep doing their thing, as that’s a much better user experience too.

P roblem: How do you get the system to favour your more specialised app?

Solution: Say hello to the lesser-known intent filter property: android:priority . This is a property on the intent-filter element that allows you to change the order in which Android considers your intent filters. The documentation warns to use it sparingly:

Use this attribute only if you really need to impose a specific order in which the broadcasts are received, or want to force Android to prefer one activity over others.

Turns out, we can use this to hint to Android that we want to prefer our more specialised apps! Set the priority in your main app to be the minimum value, meaning your more specific apps will be chosen above it without any change to them.

Do: Define app priority using priority.

Tip 4. (Optional) Use Plunge to match patterns up to incoming URLs and test your intent-filters

Plunge is a library we wrote at Trade Me to help with how we create and test deep links in our apps. We found that there were two different parts to deep linking:

The intent-filter side of things, where we need to use basic glob matching to catching things.

side of things, where we need to use basic glob matching to catching things. The code side of things where we handle these and extract the information we need to know about to take the user to where they’re going.

These things are quite different — one’s an Android thing we’re stuck with and the other is something we have a lot of control over. The thing is, they both do the same things. They catch URLs, and do things.

Plunge tries to unify both components of deep linking by doing two key things:

It allows you to write simple matching patterns for catching URLs in your code which are very similar to your intent filter patterns.

It allows you to write tests once and use them to test both implementations.

Here’s an example of how you’d catch a simple URL with a bit of information:

Define your pathPattern in your manifest

<data android:pathPattern="/item/..*" />

2. Catch the pattern in your code

pattern("/item/{itemId}") { launchItem(it.params["itemId"]) }

3. Write a test case

{

"url": "https://plunge.example.com/item/12345",

"description": "The page for buying a submarine",

"params": [

{

"name": "itemId",

"value": "12345"

}

]

}

Those three simple things are all it takes to handle a new URL. With those additions you can catch a URL, pull out some relevant information, and test both the catching, and the information extracting.

There’s a bit more setup as detailed in the repo, and it has a lot more about how you can use it for testing both positive and negative scenarios. We’ve found it’s simplified our deep linking logic considerably, and gives developers much more confidence in adding new links. Want to know more about the library without leaving Medium? Check out our intro post!