Android App Linking

The ultimate developer guide to Android application linking methods

The main objectives of this guide are to explore the most common deeplinking methods available on Android and evaluate their pros and cons.
The source code of the AppLinks Android app is available on the corresponding GitHub repository.


Method Link App not installed Offline Referrer Deeplink Deferred deeplink
Web url Test ✔️ ✔️
App Links Test ✔️ ✔️
Custom scheme Test ✔️ ✔️
Intent scheme Test ✔️ ✔️ ✔️ ✔️
App scheme Test ✔️ ✔️ ✔️ ✔️
Firebase Dynamic Links Test ✔️ ✔️ ✔️
Play Store url Test ✔️ ✔️ ✔️ ✔️
Market scheme Test ✔️ ✔️ ✔️ ✔️ ✔️


Web url

Documentation:
https://developer.android.com/training/app-links/deep-linking.html

http://smarquis.fr/action?key=value#data

Android

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data
            android:scheme="http"
            android:host="smarquis.fr"
            android:pathPattern="/action" />
    </intent-filter>
</activity>

Data

Uri Value
scheme http
host smarquis.fr
path /action
query ?key=value
fragment data

Features

Feature ✔️/
App not installed
Offline ✔️
Referrer
Deeplink ✔️
Deferred deeplink

Pros and Cons

Cons:

Documentation:
https://developer.android.com/training/app-links/verify-site-associations.html

https://smarquis.fr/action?key=value#data

A JSON verification file needs to be available at https://smarquis.fr/.well-known/assetlinks.json containing the application's package name and keystore fingerprint

[
    {
        "relation": [
            "delegate_permission/common.handle_all_urls"
        ],
        "target": {
            "namespace": "android_app",
            "package_name": "fr.smarquis.applinks",
            "sha256_cert_fingerprints": [
                "6B:41:26:A6:1E:D8:BD:91:D3:8B:57:10:5F:07:5C:2D:AB:3E:26:A4:D1:3C:9C:97:15:78:9E:0D:56:0A:CE:DC"
            ]
        }
    }
]

To test an existing statement file, you can use the official Statement List Generator and Tester tool.

During app install/update, an Android service will verify if the App Links configuration complies with the server side assetlinks.json file.
The results will be sent to logcat, with these tags: IntentFilterIntentSvc and SingleHostAsyncVerifier

Click to see logcat content

Android

Same as Web url but with https only and android:autoVerify="true" attribute.

<activity android:name=".MainActivity">
    <intent-filter
        android:autoVerify="true"
        tools:targetApi="m">
        <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="smarquis.fr"
            android:pathPattern="/action" />
    </intent-filter>
</activity>

Data

Uri Value
scheme https
host smarquis.fr
path /action
query ?key=value
fragment data

Features

Feature ✔️/
App not installed
Offline ✔️
Referrer
Deeplink ✔️
Deferred deeplink

Pros and Cons

Pros:

Cons:

Custom scheme

Documentation:
https://developer.android.com/training/app-links/deep-linking.html

link://smarquis.fr/action?key=value#data

Android

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="link" />
    </intent-filter>
</activity>

Data

Uri Value
scheme link
host smarquis.fr
path /action
query ?key=value
fragment data

Features

Feature ✔️/
App not installed
Offline ✔️
Referrer
Deeplink ✔️
Deferred deeplink

Pros and Cons

Cons:

Intent scheme

Documentation:
https://developer.chrome.com/multidevice/android/intents

intent://smarquis.fr/action?key=value#data#Intent;scheme=link;package=fr.smarquis.applinks;S.key=value;S.market_referrer=my%20referrer%20data;end

Web

Extra parameters can be added to the link and will be transfered as extras Bundle in the Intent:

More:

Android

The url will be rewritten by the parseUri() method from the Android source code.
The new url will be link://smarquis.fr/action?key=value#data

And will contain additional parameters in the Intent.

Data

Uri Value
scheme link
host smarquis.fr
path /action
query ?key=value
fragment data
Extra Value
key value
market_referrer my referrer data
Referrer
my referrer data

Features

Feature ✔️/
App not installed ✔️
Offline ✔️
Referrer ✔️
Deeplink ✔️
Deferred deeplink

Pros and Cons

Cons:

App scheme

Documentation:
https://developer.android.com/reference/android/content/Intent.html#URI_ANDROID_APP_SCHEME

android-app://fr.smarquis.applinks/https/smarquis.fr/action?key=value#data#Intent;S.key=value;S.market_referrer=my%20referrer%20data;end

Very similar to Intent scheme.

Web

Extra parameters can be added to the link and will be transfered as extras Bundle in the Intent:

More:

Android

The url will be rewritten by the parseUri() method from the Android source code.
The new url will be https://smarquis.fr/action?key=value#data

And will contain additional parameters in the Intent.

Data

Uri Value
scheme https
host smarquis.fr
path /action
query ?key=value
fragment data
Extra Value
key value
market_referrer my referrer data
Referrer
my referrer data

Features

Feature ✔️/
App not installed ✔️
Offline ✔️
Referrer ✔️
Deeplink ✔️
Deferred deeplink

Pros and Cons

Cons:

Documentation:
https://firebase.google.com/docs/dynamic-links

https://mr7f2.app.goo.gl/Tbeh

Web

Create the link from the Firebase console.

Android

Same requirements as App Links.
And add the Firebase Dynamic Links dependency in the app-level build.gradle file:

compile 'com.google.firebase:firebase-invites:11.2.0'

Then in your Activity's onCreate method, use this code to get the link if the user came from a Firebase Dynamic Link:

FirebaseDynamicLinks.getInstance()
        .getDynamicLink(getIntent())
        .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
            @Override
            public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
                if (pendingDynamicLinkData != null) {
                    Uri link = pendingDynamicLinkData.getLink();
                }
            }
        });

Data

Uri Value
scheme https
host smarquis.fr
path /action
query ?key=value
fragment data

Features

Feature ✔️/
App not installed ✔️
Offline
Referrer
Deeplink ✔️
Deferred deeplink ✔️

Pros and Cons

Pros:

Cons:

Play Store url

Documentation:
https://developer.android.com/distribute/marketing-tools/linking-to-google-play.html#UriSummary

https://play.google.com/store/apps/details?id=fr.smarquis.applinks&url=link%3A%2F%2Fsmarquis.fr%2Faction%3Fkey%3Dvalue%23data&referrer=my%20referrer%20data

Very similar to the Market scheme.

Web

This url contains additional query parameters that will be handled by the Play Store app:

Android

The url will be rewritten by the Play Store to link://smarquis.fr/action?key=value#data

Data

Uri available in deferred deeplink only

Uri Value
scheme link
host smarquis.fr
path /action
query ?key=value
fragment data
Referrer
my referrer data

Features

Feature ✔️/
App not installed ✔️
Offline ✔️
Referrer ✔️
Deeplink
Deferred deeplink ✔️

Pros and Cons

Cons:

Pros:

Market scheme

Documentation:
https://developer.android.com/distribute/marketing-tools/linking-to-google-play.html#UriSummary

market://details?id=fr.smarquis.applinks&url=link%3A%2F%2Fsmarquis.fr%2Faction%3Fkey%3Dvalue%23data&referrer=my%20referrer%20data

Web

This url contains additional query parameters that will be handled by the Play Store app:

Android

The url will be rewritten by the Play Store to link://smarquis.fr/action?key=value#data

Data

Uri Value
scheme link
host smarquis.fr
path /action
query ?key=value
fragment data
Referrer
my referrer data

Features

Feature ✔️/
App not installed ✔️
Offline ✔️
Referrer ✔️
Deeplink ✔️
Deferred deeplink ✔️

Pros and Cons

Pros:

Misc

Referrer Receiver

Add the Broadcast Receiver in AndroidManifest.xml

<receiver
    android:name=".ReferrerReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="com.android.vending.INSTALL_REFERRER" />
    </intent-filter>
</receiver>

And in the Receiver's onReceive() method, you can get the referrer value

@Override
public void onReceive(Context context, Intent intent) {
    String referrer = intent.getExtras().getString("referrer");
}

Deeplinking

You can get the deeplink Uri in your Activity's onCreate() method as well as the corresponding properties:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Uri deeplink = getIntent().getData();
    if (deeplink != null) {
        String host = deeplink.getHost();
        String path = deeplink.getPath();
        String query = deeplink.getQuery();
        String fragment = deeplink.getFragment();
    }
}

When using Play Store url or Market scheme or Firebase Dynamic Links methods, the regular Play Store Open button will be replaced by a Continue button.
Furthermore, a notification will be displayed with Tap to continue content.
These two actions are essential to the Deferred deeplink method as they provide the initial data to the app.

Regular Deeplink Deferred Deeplink

Url redirections

Adb Activity Manager

To try links with adb, use the Activity Manager (am) command:

$ adb shell 'am start "link://smarquis.fr/action?key=value#data"'

Alternatives



© Simon Marquis