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.
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.
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.
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.
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:
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.
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.