Handling deep links in Android (Kotlin) involves configuring your AndroidManifest.xml and then processing the incoming Intent in your designated Activity. There are two primary types of deep links:
- Deep Links (Custom Schemes): These use custom URI schemes (e.g.,
myapp://product/123). - Android App Links (HTTP/HTTPS URLs): These use standard web URLs (e.g.,
https://www.example.com/product/123) and offer automatic verification, allowing your app to open directly without a disambiguation dialog if verified.
Here's how to implement them:
1. Configure AndroidManifest.xml
You need to declare an <intent-filter> in the Activity that will handle the deep link.
For Custom Scheme Deep Links:
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Custom scheme deep link -->
<data android:scheme="myapp"
android:host="example.com"
android:pathPrefix="/product" />
</intent-filter>
</activity>
android:exported="true": This is crucial for any activity that can be launched by an external app or the system.android.intent.action.VIEW: This action indicates that the activity can display data to the user.android.intent.category.DEFAULT: Allows the activity to be the target of an implicit intent.android.intent.category.BROWSABLE: Allows the deep link to be opened from a web browser.<data>: Defines the URI scheme, host, and optional path. In this example,myapp://example.com/product/123would be handled.
For Android App Links (HTTP/HTTPS Deep Links):
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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" />
<!-- App Link (HTTP/HTTPS) -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/product" />
<data android:scheme="https"
android:host="www.example.com"
android:pathPrefix="/product" />
</intent-filter>
</activity>
android:autoVerify="true": This attribute tells Android to verify that your app is the default handler for the specified HTTP/HTTPS links. This verification requires setting up Digital Asset Links on your website.
2. Handle the Incoming Intent in Your Activity
In your Activity (e.g., MainActivity), you'll retrieve the Intent data and parse the URI.
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.util.Log
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) // Your layout
handleIntent(intent)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// If the activity is already running and a new deep link comes in
handleIntent(intent)
}
private fun handleIntent(intent: Intent?) {
val appLinkAction = intent?.action
val appLinkData: Uri? = intent?.data
if (Intent.ACTION_VIEW == appLinkAction && appLinkData != null) {
Log.d("DeepLink", "Deep link received: $appLinkData")
// Example: myapp://example.com/product/123 or https://www.example.com/product/123
val pathSegments = appLinkData.pathSegments
if (pathSegments.size >= 2 && pathSegments[0] == "product") {
val productId = pathSegments[1]
Log.d("DeepLink", "Product ID: $productId")
// Now you can navigate to the product details screen or load data
// For example: navigateToProductDetails(productId)
} else {
Log.d("DeepLink", "Unhandled deep link path: ${appLinkData.path}")
}
// You can also get query parameters
val param1 = appLinkData.getQueryParameter("param1")
if (param1 != null) {
Log.d("DeepLink", "Query parameter 'param1': $param1")
}
} else {
Log.d("DeepLink", "No deep link data found or action is not VIEW")
}
}
}
onCreate(): The first time the activity is launched via a deep link, theIntentwill be available here.onNewIntent(): If the activity is already running (e.g.,singleToplaunch mode) and a new deep link is triggered,onNewIntent()will be called with the newIntent. It's important to handle the intent in both places.intent?.data: ThisUriobject contains the full deep link URL.appLinkData.pathSegments: Provides a list of path segments from the URI (e.g., for/product/123, it would be["product", "123"]).appLinkData.getQueryParameter("paramName"): Allows you to extract specific query parameters from the URL.
3. Digital Asset Links (for Android App Links only)
For android:autoVerify="true" to work, you need to host a assetlinks.json file on your website at https://www.yourdomain.com/.well-known/assetlinks.json. This file proves that your app owns the domain.
A typical assetlinks.json looks like this:
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.your.package.name",
"sha256_cert_fingerprints": ["YOUR_APP_SHA256_FINGERPRINT"]
}
}]
You can find your app's SHA256 fingerprint using the following command (for your release keystore):
keytool -list -v -keystore your_release_key.keystore
Or for your debug keystore:
keytool -list -v -keystore ~/.android/debug.keystore
Testing Deep Links
You can test deep links using adb:
For Custom Scheme Deep Links:
adb shell am start -W -a android.intent.action.VIEW -d "myapp://example.com/product/456" com.your.package.name
For Android App Links:
adb shell am start -W -a android.intent.action.VIEW -d "https://www.example.com/product/456" com.your.package.name
Replace com.your.package.name with your actual application package name.