Deep-linking using Circuit¶
Deep linking to application is a vast topic and the implementation detail can vary based on your application needs. Deep linking strategy can be highly sophisticated or simple based on the use-case.
To keep things very simple and easy to understand, we will be focusing on deep linking to Android platform only. You can then extend the idea to other platforms as needed.
Info
Before you begin, we recommend having a basic understanding of deep linking. To get the most out of this guide, please review Android’s official training guide, which provides valuable insights into deep linking for Android apps.
Deep linking strategy¶
Essentially, you need to define a strategy for you app to handle the incoming deep link. We will take a look at Circuit’s email app from the tutorial with following screens:
- Inbox Screen - List all incoming emails
- Details Screen - Show details of the email
- Draft Screen - Compose a new email (additional screen added for this demo)
By default, the app launches with Inbox Screen as the root screen. To deep link into other two screens, we will define URI path segment as:
inbox
- Inbox Screenview_email
- Details Screen withemailId
as query parameternew_email
- Draft Screen
Assuming, our app’s URI scheme is circuitapp://
with host emailonthego
, the deep links will look like:
circuitapp://emailonthego/inbox
- Deep link to Inbox Screencircuitapp://emailonthego/inbox/view_email?emailId=2
- Deep link to Details Screen with email id 2 with Inbox Screen as parentcircuitapp://emailonthego/inbox/new_email
- Deep link to Draft Screen with Inbox Screen as parentcircuitapp://emailonthego/inbox/view_email/new_email?emailId=3
- Deep link to Draft Screen and in backstack there is Details Screen and Inbox Screen.
Once you have added intent-filter in your AndroidManifest.xml
file, you can handle the incoming deep link in your Activity
.
Handling deep link in Circuit¶
In our case, we will create a parseDeepLink
function to parse the incoming deep link and return the list of screens to be displayed in the app.
// In your `MainActivity.kt` or activity that has the `intent-filter` for custom URI scheme
override fun onCreate(savedInstanceState: Bundle?) {
// ...
setContent {
MaterialTheme {
// When there is no deeplink data in the intent, default to Inbox Screen as root screen
var stackedScreens: List<Screen> by remember {
mutableStateOf(parseDeepLink(intent) ?: listOf(InboxScreen))
}
val backStack = rememberSaveableBackStack(stackedScreens)
val navigator = rememberCircuitNavigator(backStack)
// ...
}
}
}
And here is a simple implementation of parseDeepLink
function that creates the list of screens based on the incoming deep link:
/**
* Parses the deep link from the given [Intent.getData] and returns a list of stacked screens
* to navigate to when deep link URI is available.
*/
private fun parseDeepLink(intent: Intent): List<Screen>? {
val dataUri = intent.data ?: return null
val screens = mutableListOf<Screen>()
dataUri.pathSegments.filter { it.isNotBlank() }.forEach { pathSegment ->
when (pathSegment) {
"inbox" -> screens.add(InboxScreen)
"view_email" ->
dataUri.getQueryParameter("emailId")?.let {
screens.add(DetailScreen(it))
}
"new_email" -> screens.add(DraftNewEmailScreen)
else -> Log.d("App", "Unknown path segment: $pathSegment")
}
}
return screens.takeIf { it.isNotEmpty() }
}
Tip
Ideally, you would have deep link components that does the parsing and building screens based on parameters provided in the deep link URI.
To test, try the following command from the terminal:
adb shell am start -W \
-a android.intent.action.VIEW \
-d "circuitapp://emailonthego/inbox/view_email/new_email/?emailId=2"
It should launch the app and navigate to the ‘Draft Screen’ with backstack containing ‘Details Screen’ and ‘Inbox Screen’.