A partir da versão 1.2.0, o Navigation 3 oferece suporte a links diretos para
destinos no seu app usando as classes DeepLinkRequest e
DeepLinkMatcher.
Para oferecer suporte a links diretos no seu app, siga estas etapas:
- Defina filtros de intent no
AndroidManifest.xmlpara especificar quais URIs o app pode processar. - Crie instâncias de
DeepLinkMatcherpara mapear as solicitações recebidas para as chaves de navegação. - Faça a correspondência das solicitações recebidas no método
onCreateouonNewIntentda atividade e atualize a backstack de acordo.
Criar um DeepLinkRequest
Um DeepLinkRequest representa um link direto de entrada. Ele contém um
DeepLinkUri e um RequestExtras opcional com outras
informações, como a ação da intent ou o tipo MIME.
// Create a request with a String URI val request = DeepLinkRequest(uri = "https://www.example.com/home") // Create a request from a DeepLinkUri val deepLinkUri = DeepLinkUri("https://www.example.com/home") val requestFromUri = DeepLinkRequest(uri = deepLinkUri) // Create a request with a URI and action val requestWithAction = DeepLinkRequest( uri = "https://www.example.com/home", extras = DeepLinkRequest.actionExtra("android.intent.action.VIEW") ) // Create a request with URI, action and mimeType val requestWithMimeType = DeepLinkRequest( uri = "https://www.example.com/image", extras = requestExtras { put(DeepLinkRequest.ActionExtrasKey, "android.intent.action.VIEW") put(DeepLinkRequest.Companion.MimeTypeExtrasKey, "image/png") } )
Fornecer extras do DeepLinkRequest
Para armazenar outras informações relacionadas ao link direto, use a
classe RequestExtras. Para que a definição e a instanciação de extras sejam seguras para tipos,
a biblioteca fornece a interface RequestExtrasKey e
a DSL requestExtras.
Além disso, a biblioteca fornece duas chaves extras e auxiliares associados:
MimeTypeExtrasKey: usado para armazenar um tipo MIMEString.ActionExtrasKey(somente Android): usado para armazenar oStringde ação de umIntent.
val extras: RequestExtras = requestExtras { put(DeepLinkRequest.Companion.MimeTypeExtrasKey, "application/json") put(DeepLinkRequest.ActionExtrasKey, Intent.ACTION_VIEW) } // Access typed values using the get operator val mimeType: String? = extras[DeepLinkRequest.Companion.MimeTypeExtrasKey] val action: String? = extras[DeepLinkRequest.ActionExtrasKey] // Create extras using helper functions and combine them val mimeTypeExtras: RequestExtras = DeepLinkRequest.mimeTypeExtra("application/json") val combinedExtras: RequestExtras = extras + DeepLinkRequest.actionExtra(Intent.ACTION_VIEW)
Para definir seus próprios extras personalizados, implemente a interface RequestExtrasKey
com um genérico tipado:
// Define a custom typed key: object CampaignIdExtrasKey : RequestExtrasKey<String> val customExtras: RequestExtras = requestExtras { put(CampaignIdExtrasKey, "123") } val campaignId: String? = customExtras[CampaignIdExtrasKey]
Também é possível usar emptyRequestExtras() para criar uma instância vazia ou
combinar extras usando os operadores + (plus) e - (minus).
Criar um DeepLinkRequest com base em um Intent
No Android, é possível criar um DeepLinkRequest diretamente de um Intent. Quando
construído dessa maneira, o DeepLinkRequest é criado da seguinte maneira:
- O
urié copiado do campodatada intent. - Se não for nulo, o tipo MIME e os extras da ação serão definidos nos campos de intent correspondentes.
- Todos os
intent.extrascom valores não nulos são salvos como umSavedStateemDeepLinkRequest.IntentExtrasKey. - Todos os extras adicionais fornecidos usando o parâmetro
extrassão adicionados.
object CampaignIdExtrasKey : RequestExtrasKey<String> val intent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("https://www.example.com/item/42") type = "application/json" putExtra("user_id", "123") } val request = DeepLinkRequest( intent = intent, extras = requestExtras { put(CampaignIdExtrasKey, "spring_promo") } ) // The resulting DeepLinkRequest contains: val uri = request.uri // "https://www.example.com/item/42" val action = request.extras[DeepLinkRequest.ActionExtrasKey] // "android.intent.action.VIEW" val mimeType = request.extras[DeepLinkRequest.Companion.MimeTypeExtrasKey] // "application/json" val intentExtras: SavedState? = request.extras[DeepLinkRequest.IntentExtrasKey] val userId: String? = intentExtras?.read { getStringOrNull("user_id") } // "123" val campaignId: String? = request.extras[CampaignIdExtrasKey] // "spring_promo"
Criar instâncias do DeepLinkMatcher
Um DeepLinkMatcher mapeia instâncias de DeepLinkRequest recebidas para
chaves de navegação que podem ser adicionadas à backstack do app. O Navigation 3
oferece três correspondentes integrados: UriDeepLinkMatcher para
correspondência de URI baseada em padrões, StaticKeyDeepLinkMatcher para links básicos e
BackStackMatcher para criar backstacks sintéticas. A biblioteca também
oferece suporte a comparadores personalizados para casos de uso não cobertos pelos comparadores
integrados.
Para mais informações, consulte Criar DeepLinkMatchers.
Adicionar filtros de intent
Para permitir que um link direto inicie sua atividade, defina os elementos <intent-filter> correspondentes no AndroidManifest.xml do app. Para mais
informações, consulte Adicionar filtros de intent para links de entrada.
Corresponder a uma solicitação recebida
Depois de criar as instâncias do DeepLinkMatcher, é possível corresponder
as solicitações recebidas na sua atividade.
Para corresponder a uma solicitação recebida, siga estas etapas:
- Instancie as instâncias de
DeepLinkMatcher. - Agrupe todas as instâncias de
DeepLinkMatcher, explicitamente ou usando multibindings. - Crie um
DeepLinkRequestcom base noIntentrecebido. - Compare a solicitação com todos os correspondentes e encontre a melhor correspondência.
- Crie a backstack com base no resultado da correspondência.
// 1. Instantiate your DeepLinkMatcher instances. val homeMatcher = StaticKeyDeepLinkMatcher(HomeKey, listOf(DeepLinkMatcher.actionFilter(Intent.ACTION_VIEW))) val userProfileMatcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/users/{id}"), serializer<UserProfileKey>() ).withBackStack { matchResult -> listOf(HomeKey, matchResult.key) } val telMatcher = TelDeepLinkMatcher() // 2. Collate all of your DeepLinkMatcher instances. // Note: Collating matchers with different generic types requires wildcards, // erasing the specific generic types. val deepLinkMatchers: List<DeepLinkMatcher<*, *>> = listOf( homeMatcher, userProfileMatcher, telMatcher ) class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // 3. Create a DeepLinkRequest from the incoming Intent val request = DeepLinkRequest(intent = intent) // 4. Match the request against all matchers and find the best match. // Because DeepLinkMatcher.MatchResult implements Comparable, you can // use maxOrNull() to find the best match. val matchResult = deepLinkMatchers .mapNotNull { it.match(request) } // List<DeepLinkMatcher.MatchResult<*>> .maxOrNull() // DeepLinkMatcher.MatchResult<*>? // 5. Create the back stack from the match result (or fall back to a default). val backStack: List<NavKey> = when (matchResult) { // If no match is found, use the default back stack (e.g., HomeKey) null -> listOf(HomeKey) // If a BackStackMatchResult is found, use the back stack from the result is BackStackMatchResult<*, *> -> { // Because star-projected matchers erase the key type, cast the back stack to List<NavKey>. @Suppress("UNCHECKED_CAST") matchResult.backStack as List<NavKey> } // Otherwise, use the key from the match result to make a single-item back stack else -> listOf(matchResult.key as NavKey) } } }