As with previous lessons, you’ll continue to build on the movie-booking app.
In this part of the lesson, you’ll define a deep link to the app’s movie-selection screen so the user journey improves for cases such as when a user is reading a movie’s description on a website or app and is interested in watching it in a nearby cinema.
In this case, it’d be ideal that the redirection to the movie-booking app takes the user directly to the movie-selection screen and has that movie as the pre-selected choice among the list of available movies.
Open the starter project and locate the composable() function that defines the route for the movie selection-screen in MainActivity.
You can define your deep link using the navDeepLink() function and pass it to the composable() function in the deepLinks parameter, which accepts a list of NavDeepLink objects:
composable(
MOVIE_SELECTION_SCREEN.route,
deepLinks = listOf(navDeepLink {
uriPattern = "https://njc-sample-host.kodeco.com/{$MOVIE_NAME_ARG}"
action = Intent.ACTION_VIEW
})
) { ... }
Now, you must pass the movie name that exists as part of the deep-link uri to the MovieSelectionScreen so the movie can be pre-selected when the screen opens. Given that the deep-link uri is dynamic, the movie name can be extracted and passed to the movie-selection screen by accessing the arguments of NavBackStackEntry.
backStackEntry.arguments?.getString(MOVIE_NAME_ARG)
To pass the movie name to the MovieSelectionScreen composable, add to it a parameter named movieNameFromDeeplink of type String?:
@Composable
fun MovieSelectionScreen(
modifier: Modifier = Modifier,
onNextClick: (String) -> Unit,
movieNameFromDeeplink: String?
) { ... }
Note that movieNameFromDeeplink will be null in case the user accesses the screen without the deep link.
To ensure the code compiles, change MovieSelectionScreenPreview to the following:
fun MovieSelectionScreenPreview() {
MovieSelectionScreen(onNextClick = {}, movieNameFromDeeplink = "")
}
You can then pass the movie name extracted earlier as:
MovieSelectionScreen(
onNextClick = { movieName ->
navController.navigate(
TICKET_SELECTION_SCREEN.route.replace(
"{$MOVIE_NAME_ARG}",
movieName
)
)
},
movieNameFromDeeplink = backStackEntry.arguments?.getString(MOVIE_NAME_ARG)
)
To make the deep link accessible to external apps, define an <intent-filter> in the <activity> tag for MainActivity in the app’s AndroidManifest.xml.
<intent-filter>
<data android:scheme="https" android:host="njc-sample-host.kodeco.com" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<action android:name="android.intent.action.VIEW"/>
</intent-filter>
Note that intent filters define categories and actions for supporting deep links based on how the links originate and how they should be processed. For instance, adding the category android.intent.category.BROWSABLE allows the user to access the deep link from a web browser.
Although this falls outside the scope of this lesson, you’re recommended to check the official documentation for detailed information.
You’ve now successfully set up a deep link to the movie-selection screen. However, you still must add functionality to have the movie name pre-selected in case the screen was opened using a deep link.
To do so, define a function in MovieSelectionScreen.kt that returns the movie name if it’s one of the available movies or else returns null.
private fun getPreSelectedMovie(
movieNameList: List<String>,
preselectedMovieName: String?
): String? {
return if (movieNameList.indexOf(preselectedMovieName) >= 0) {
preselectedMovieName
} else {
null
}
}
Now, update the code for the variable selectedMovieName, which is a state variable representing the currently selected movie. If nothing is selected, its value is null.
var selectedMovieName: String? by remember {
mutableStateOf(getPreSelectedMovie(movieNameList, movieNameFromDeeplink))
}
Great, you’ve implemented the deep-link functionality along with pre-selecting the movie name! You can test the deep link in multiple ways — one of which, for instance, is triggering the deep link using ADB (Android Debug Bridge). Not that this will require you to have an emulator or a physical device connected and have debugging enabled.
Build and run the app.
Close the app, open a terminal, and run the following commands:
adb shell am start -W -a android.intent.action.VIEW -d "https://njc-sample-host.kodeco.com/The%20Dark%20Knight%20%282008%29" com.kodeco.njc.navigationcomponent
Notice how the app launches directly into the movie selection screen, with “The Dark Knight” selected.
To ensure everything works fine, try changing the selected movie in the deep link. Run the following commands:
adb shell am start -W -a android.intent.action.VIEW -d "https://njc-sample-host.kodeco.com/Pulp%20Fiction%20%281994%29" com.kodeco.njc.navigationcomponent
This time, “Pulp Fiction” is the selected movie, and the same title is reflected on the app.