Deep linking is a powerful mechanism in Android that allows users to navigate directly to a specific location within an application from an external source, such as a web link, push notification, or another app. In Jetpack Compose, implementing deep links requires integrating navigation components and setting up the necessary intent filters. This comprehensive guide will walk you through implementing deep links in a Jetpack Compose application.
What are Deep Links?
Deep links are URIs (Uniform Resource Identifiers) that direct users to a specific location within an application. Unlike regular app links, deep links require the user to select the application to handle the intent, which offers flexibility but may involve an extra step for the user.
Why Implement Deep Links?
- Enhanced User Experience: Provides a direct route to relevant content within your app.
- Improved Engagement: Increases user engagement by guiding users from external sources directly to specific features.
- Marketing and Promotion: Supports marketing campaigns by directing users to particular promotions or content.
Prerequisites
- Android Studio installed.
- Basic understanding of Jetpack Compose.
- Familiarity with Android Navigation Component.
How to Implement Deep Links in Jetpack Compose
Follow these steps to implement deep links in your Jetpack Compose application:
Step 1: Add Navigation Dependencies
Ensure that you have the necessary navigation dependencies in your build.gradle file:
dependencies {
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.1")
implementation("androidx.activity:activity-compose:1.7.2")
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
// Navigation dependencies
implementation("androidx.navigation:navigation-compose:2.6.0")
}
Step 2: Define Navigation Graph
Create a navigation graph using the NavController to define the app’s navigation structure. This graph will include destinations that can be reached via deep links.
import androidx.compose.runtime.Composable
import androidx.navigation.NavType
import androidx.navigation.compose.rememberNavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import androidx.compose.material3.Text
import androidx.compose.ui.tooling.preview.Preview
@Composable
fun NavigationGraph() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") {
HomeScreen(navController = navController)
}
composable(
route = "details/{itemId}",
arguments = listOf(navArgument("itemId") { type = NavType.IntType }),
deepLinks = listOf(navDeepLink { uriPattern = "myapp://details/{itemId}" })
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt("itemId")
DetailsScreen(itemId = itemId)
}
}
}
@Preview(showBackground = true)
@Composable
fun NavigationGraphPreview() {
NavigationGraph()
}
In this example:
- The
NavHostdefines the navigation graph, starting at the “home” destination. - The
composablefunction associates a route (“details/{itemId}”) with theDetailsScreencomposable. navArgumentspecifies that “itemId” is an argument of typeIntType.navDeepLinksets up the deep link with the URI pattern “myapp://details/{itemId}”.
Step 3: Create UI Composable Screens
Define the composable screens for each destination in the navigation graph.
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
@Composable
fun HomeScreen(navController: NavController) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
text = "Go to Details",
style = TextStyle(fontSize = 20.sp, color = MaterialTheme.colorScheme.primary),
modifier = Modifier.clickable {
navController.navigate("details/123")
}
)
}
}
@Composable
fun DetailsScreen(itemId: Int?) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(text = "Details Screen: Item ID = ${itemId ?: "N/A"}", style = TextStyle(fontSize = 20.sp))
}
}
In these composables:
HomeScreendisplays a clickable text that navigates to the “details” route with a hardcoded item ID.DetailsScreendisplays the item ID passed as a parameter in the route.
Step 4: Configure the AndroidManifest.xml
Add an intent-filter to your AndroidManifest.xml file for the Activity that hosts the Compose UI.
<!-- Main activity intent filter -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
In the AndroidManifest.xml:
- The
<activity>tag includes theandroid:exported="true"attribute to allow the activity to be launched by other applications. - The
<intent-filter>tag with theandroid.intent.action.VIEWaction enables the activity to handle incoming deep links. - The
<category>tags specify that the activity is accessible from the browser (android.intent.category.BROWSABLE) and should be a default handler (android.intent.category.DEFAULT). - The
<data>tag defines the URI scheme (myapp) and host (details) that the activity can handle.
Step 5: Integrate with MainActivity
Integrate the navigation graph with your MainActivity:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import com.example.deeplinkdemo.NavigationGraph
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NavigationGraph()
}
}
}
Testing Deep Links
To test the deep link, use the following ADB command:
adb shell am start -W -a android.intent.action.VIEW -d "myapp://details/123" com.example.deeplinkdemo
Replace com.example.deeplinkdemo with your application’s package name and adjust the URI as needed.
Conclusion
Deep links enhance the user experience by enabling direct navigation to specific content within your Jetpack Compose applications. By setting up the navigation graph, defining composable screens, and configuring the AndroidManifest.xml file, you can effectively implement deep links to improve user engagement and streamline navigation. Following this guide will help you create a more intuitive and user-friendly Android application.