Deep Linking

You may set up a deep link for your preferred URL so that when users taps the defined URL from anywhere outside your app in their Android device, they will be redirected to your app for a smoother experience.

In this example, we will explain how to set up deep linking to open TapTalk.io's room list or a specific chat room page when user taps a specific link from their device.

Step 1: Define a URL to open your app

To start, choose a URL from your domain that will be used to open your app. In this example, we will try using https://web.taptalk.io/chat.

You should use your own specified URL, the URL above is only meant as an example to make it easier to follow the guide.

To be able to open your app from a URL, you will need to add an intent filter to your specified activity's tag inside the AndroidManifest.xml file. In this example, a new activity named TapDeepLinkActivity will be created specifically to handle deep links. You may also use an existing activity, such as your app's main activity, if you wish.

After you locate your chosen activity tag in the Manifest, add the following intent filter inside the <activity> tag. The previously defined URL as will be added as data for the intent filter.

AndroidManifest.xml
<application
    android:name=".YourApplication"
    ...
    
    <activity
        android:name="com.example.app.activity.TapDeepLinkActivity"
        android:exported="true"
        android:launchMode="singleTask">
        <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" />
            <data android:host="web.taptalk.io" />
            <data android:pathPrefix="/chat" />
        </intent-filter>
    </activity>

</application>

From Android Developer:

To create a link to your app content, add an intent filter that contains these elements and attribute values in your manifest:

<action>

Specify the ACTION_VIEW intent action so that the intent filter can be reached from Google Search.

<data>

Add one or more <data> tags, each of which represents a URI format that resolves to the activity. At minimum, the <data> tag must include the android:scheme attribute.

You can add more attributes to further refine the type of URI that the activity accepts. For example, you might have multiple activities that accept similar URIs, but which differ simply based on the path name. In this case, use the android:path attribute or its pathPattern or pathPrefix variants to differentiate which activity the system should open for different URI paths.

<category>

Include the BROWSABLE category. It is required in order for the intent filter to be accessible from a web browser. Without it, clicking a link in a browser cannot resolve to your app.

Also include the DEFAULT category. This allows your app to respond to implicit intents. Without this, the activity can be started only if the intent specifies your app component name.

The TapDeepLinkActivity from this example will act as a bridge to open TapTalk.io's room list page, or a specified chat room.

When the activity is launched from an intent filter, you can obtain the required data from the incoming Intent from the Activity.

The example snippet below will show how to open a chat room from the specified roomID from the URL (i.e. https://web.taptalk.io/chat/roomID), or open the room list page when no roomID is specified

TapDeepLinkActivity.java
package com.example.app.activity;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;

import java.util.List;

import io.taptalk.TapTalk.Helper.TapTalk;
import io.taptalk.TapTalk.Listener.TapCommonListener;
import io.taptalk.TapTalk.Manager.TapUI;

public class TapDeepLinkActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        handleIntent();
        finish();
    }

    private void handleIntent() {
        Intent intent = getIntent();
        if (intent != null && intent.getData() != null) {
            Uri data = intent.getData();
            if (data.getHost().equals("web.taptalk.io")) {
                if (TapTalk.isAuthenticated()) {
                    List<String> pathSegments = data.getPathSegments();

                    if (pathSegments != null && !pathSegments.isEmpty()) {
                        // Get room ID from last path segment
                        String roomID = pathSegments.get(pathSegments.size() - 1);
                        openRoomList(roomID);
                    }
                    else {
                        // Fallback if room ID is not found
                        openRoomList("");
                    }
                }
                else {
                    // TapTalk not authenticated
                    // You may authenticate or open fallback activity
                    TapTalk.authenticateWithAuthTicket(AUTH_TICKET, true, new TapCommonListener() {
                        @Override
                        public void onSuccess(String successMessage) {
                            // Authentication success
                            handleIntent();
                        }

                        @Override
                        public void onError(String errorCode, String errorMessage) {
                            // Authentication success
                            openFallbackActivity();
                        }
                    });
                }
            }
            else {
                // Fallback if tapped url is not chat
                openFallbackActivity();
            }
        }
        else {
            // Fallback if data is null
            openFallbackActivity();
        }
    }

    private void openRoomList(String roomID) {
        // openRoomList with roomID parameter will open selected chat room after room list
        TapUI.getInstance().openRoomList(this, roomID);
    }

    private void openFallbackActivity() {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
    }
}

You can also try using the above snippet for your own preferred Activity.

Starting in Android 12 (API level 31), a generic web intent resolves to an activity in your app only if your app is approved for the specific domain contained in that web intent. If your app isn't approved for the domain, the web intent resolves to the user's default browser app instead.

To handle this change, we will need to create an assetlinks.json file and place it under the .well-known/ directory of your host.

Creating the assetlinks.json file

You may create the file manually, create an empty file and name it assetlinks.json. The file should contain the following:

assetlinks.json
[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.yourapppackagename",
      "sha256_cert_fingerprints":
      ["<Your App’s SHA256 fingerprint>"]
    }
  },
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.yourapppackagename.debug",
      "sha256_cert_fingerprints":
      ["<Your App’s SHA256 fingerprint>"]
    }
  }
]

The above example shows the contents of assetlinks.json file addressing your application for both debug and release build. Change the package_name and sha256_cert_fingerprints value respectively according to your application.

package_name can be obtained from the applicationId in your build.grade (:app) file.

One way to obtain SHA-256 fingerprint for your app is through running gradle signingReport from Android Studio.

Click on the gear icon on the top right of Android Studio, then select Run Anything, and type gradle signingReport, then press Enter. (menu location may vary according to version)

Android Studio will then execute a signingReport task. When it is finished, you can see all your app variants' fingerprints in the Debug tab at the bottom of the Android Studio window. Paste the SHA-256 value of your selected app variant to the assetlinks.json file.

Deploying the assetlinks.json file

After generating the file, deploy it to the host under a .well_known directory. For this specific example, the file will be located at https://web.taptalk.io/.well-known/assetlinks.json

Google provides some useful information to watch out for when hosting this file:

  • The assetlinks.json file must be accessible without any redirects (no 301 or 302 redirects) and must be accessible by bots (your robots.txt must allow crawling /.well-known/assetlinks.json).

  • The assetlinks.json file must be served with content-type application/json.

  • The assetlinks.json file must be accessible over an HTTPS connection, regardless of whether the app's intent filters declare HTTPS as the data scheme.

Once all the steps above are successfully done, your app should be approved for your domain, and should be able to handle deep linking. You can try tapping the specified url from a test device to open your app.

Last updated

#621:

Change request updated