Deep linking is a crucial feature for modern Android applications, allowing users to navigate directly to specific content within an app from outside sources like web pages, emails, or social media links. With Jetpack Compose, implementing deep linking involves using Navigation Compose, the recommended navigation library for Compose-based apps.
What is Deep Linking?
Deep linking is a technique that enables users to navigate directly to a specific location or screen within a mobile app. Instead of simply opening the app’s main screen, a deep link can take the user to a particular piece of content, profile, or feature. This provides a seamless and contextual user experience.
Why Use Deep Linking?
- Enhanced User Experience: Direct users to specific content.
- Marketing Campaigns: Track conversions from specific campaigns by directing users to dedicated landing pages within the app.
- Seamless Sharing: Share links that open content directly within the app from web pages or social media.
How to Implement Deep Linking in Jetpack Compose Apps
To implement deep linking, we’ll primarily use the Navigation Compose library along with custom URI schemes or Android App Links.
Step 1: Add Dependencies
Ensure you have the necessary dependencies in your build.gradle file:
dependencies {
implementation("androidx.navigation:navigation-compose:2.7.0")
}
Step 2: Define Navigation Graph with Deep Links
Create a Navigation Graph to define your app’s navigation structure. Within the graph, specify which composables should be associated with particular deep link URIs.
import androidx.compose.runtime.Composable
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
@Composable
fun NavigationGraph() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") {
HomeScreen(navController = navController)
}
composable(
"details/{itemId}",
arguments = listOf(navArgument("itemId") { type = NavType.IntType }),
deepLinks = listOf(navDeepLink { uriPattern = "example://app/details/{itemId}" })
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt("itemId")
DetailsScreen(itemId = itemId)
}
}
}
In this example:
"details/{itemId}"defines a route with a parameteritemId.navArgument("itemId") { type = NavType.IntType }specifies the argument as an integer.navDeepLink { uriPattern = "example://app/details/{itemId}" }associates a deep link with the route using a custom URI schemeexample://app/details/{itemId}.
Step 3: Define UI Components
Implement the UI components for the Home screen and Details screen:
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
@Composable
fun HomeScreen(navController: NavController) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Go to Details for Item 1",
modifier = Modifier.clickable {
navController.navigate("details/1")
}
)
}
}
@Composable
fun DetailsScreen(itemId: Int?) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "Details for Item: $itemId")
}
}
Here, the HomeScreen navigates to the DetailsScreen using navController.navigate("details/1").
Step 4: Configure AndroidManifest.xml
To handle deep links, you need to configure the AndroidManifest.xml file. Add an intent filter to the Activity that handles the deep link.
<activity
android:name=".MainActivity"
android:exported="true">
<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="example"
android:host="app"
android:pathPrefix="/details" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Key points in the AndroidManifest.xml:
<action android:name="android.intent.action.VIEW" />specifies that this intent filter handles the action of viewing data.<category android:name="android.intent.category.DEFAULT" />and<category android:name="android.intent.category.BROWSABLE" />ensure the app can be launched via the deep link from external sources.<data android:scheme="example" android:host="app" android:pathPrefix="/details" />configures the URI scheme (example), host (app), and path prefix (/details).
Step 5: Using adb to Test Deep Links
You can use adb to test the deep link from the command line:
adb shell am start -W -a android.intent.action.VIEW -d "example://app/details/123" your.package.name
Replace your.package.name with your app’s package name.
Android App Links vs. Custom URI Schemes
- Android App Links: Use HTTPS URLs and require verification via Digital Asset Links. This is the recommended approach for linking to web content and ensures that only your app can handle those links.
- Custom URI Schemes: Use a custom scheme (e.g.,
example://). While easier to implement, they are less secure and other apps can register for the same scheme.
Implementing Android App Links
To implement Android App Links:
- Configure your app to handle HTTPS URLs.
- Create a Digital Asset Links file (
assetlinks.json) and host it on your website. - Add an intent filter in your
AndroidManifest.xmlto handle the HTTPS URLs.
Step 1: Update AndroidManifest.xml
<activity
android:name=".MainActivity"
android:exported="true">
<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"
android:host="www.example.com"
android:pathPrefix="/details" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Step 2: Create assetlinks.json
Create an assetlinks.json file:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "your.package.name",
"sha256_cert_fingerprints": [
"YOUR_SHA256_CERTIFICATE_FINGERPRINT"
]
}
}
]
Host this file at https://www.example.com/.well-known/assetlinks.json. Make sure your server serves this file with the correct MIME type (application/json).
Conclusion
Deep linking in Jetpack Compose apps is facilitated by Navigation Compose, enabling navigation to specific destinations within your app via URI schemes or, preferably, Android App Links. Custom URI schemes are simpler but less secure, whereas Android App Links with HTTPS URLs provide better security and user experience by verifying app ownership through Digital Asset Links. Using Navigation Compose and proper AndroidManifest.xml configuration will enable you to leverage deep linking effectively, providing seamless access to specific content within your application.