The Definitive Guide to App Links

Currently I’m working on an ecommerce app that also has a website. We found out that apparently users that use the app are more loyal, convert more and are happier with the company as a whole. Therefore it made sense for us to try to get more people that normally use the website to use the app. One way to do that is to use App Links.

App links will, once successfully setup, automatically redirect users to the app for the configured pages. An example would be that if you would go to a product page on the website it would open that product page within the app automatically without the user seeing the disambiguation dialog

Here I will explain how I went about setting those up and a few gotcha’s I found along the way.

In essence setting up App Links is about two parts, both equally important.

  • An assetlinks.json file at the root of the website in a folder called .well-known.
  • Defining an intent filter that has the android:autoVerify attribute set to true.

Setting up the assetlinks file

The format of the assetlinks file is the following:

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.ecommerce",
      "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"
      ]
    }
  }
]

The only thing that you would have to adjust here is the package_name and the fingerprint. One thing to note is that if you use Google App Signing the signature that you should put in the sha256certfingerprints can be found under the section Release Management > App signing > App signing certificate > SHA-256 certificate fingerprint. This certificate is the one that Google uses to distribute your app to devices so that is the one that should be used, otherwise the validation will fail.

Things to be aware of

Make sure that this file is served at the root of the website that you want to link in the .well-known folder without any redirects.

A common situation might be that the website redirects non-www links to the www variant of the website. If the intent filter links to the non-www variant of the website, it will not work since there is a redirect in between.

Another thing to consider is that the website should not be behind a VPN. Even if the Android phone is also connected to the VPN, it will not verify the website.

That part out of the way, lets take a look at how defining the intent filter works.

Defining the intent filter

As previously mentioned, for App Linking to work, the app has to define an intent filter in the AndroidManifest that includes the android:autoVerify attribute. This attribute tells Android that it should automatically verify this intent filter with the corresponding URL that is defined within the intent filter. Lets take a look at an example.

<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:host="example.com" />
    <data android:scheme="https" />
</intent-filter>

This intent filter will, once the app is installed, verify that there is a file called assetlinks.json at https://example.com/.well-known. If the correct signature is used this will setup the linking and App Linking will have been enabled!

A good thing to be aware of is something that is not in the documentation anywhere but I found out while testing is that every host that is in the AndroidManifest should have the assetlinks.json file. For example if you have a host like https://example.com that has the file and a host like https://example-bad.com that does not have the file it will not verify the website.

Debugging App links

Hopefully you will never have to read this section but if you do, here are some things that helped me while debugging what was going wrong.

First thing to start with is to verify if the website and app were successfully linked:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "https://example.com"

If the App linking was successful, this should open the app instead of the website.

If this is not setup correctly then there are a few things that could be wrong:

  • The assetlinks file is being served with a redirect, this is easy to verify using a browser and looking at the Network tab in the DevTools.
  • The signature does not match. This is a bit more tricky to verify but doable.

Verifying the signature of the APK you can do by first downloading the APK. Since the APK format is basically a ZIP file, you can change the extension to a ZIP and unpack it. In that folder should be a file called ANDROID.RSA or CERT.RSA. If you run this command:

keytool -printcert -file $rsa_file where $rsa_file is the path to the RSA file you should see the SHA256 hash. This you can easily check with the hash that was defined in the assetlinks.json file.

iOS & Android difference

One last thing to be aware of is that the linking for iOS & Android behave differently. On iOS if you have setup the linking (Universal Linking), if you are browsing a website in Safari and you are navigating to URLs that have the same hosts, you will not be redirected to the app, even though you have setup the linking. In Android it does work like that.

Let me give you an example:

This will open the Android app since it registered itself to match on that URL. On iOS you will not be redirected.

Published 30 Jul 2019

I blog about Android.
Joey Kaan on Twitter