Criar um link direto para um destino

No Android, um link direto é aquele que leva você diretamente a um destino específico em um app.

É possível oferecer suporte a dois tipos diferentes de links diretos no app: explícito e implícito. A maneira como você implementa links diretos varia de acordo com o tipo de gráfico usado pelo app:XML or programmatic.

Criar um link direto explícito

Um link direto explícito é uma instância única de um link direto que usa uma PendingIntent para direcionar os usuários a um local específico do app. Você pode mostrar um link direto explícito como parte de uma notificação ou de um widget de app, por exemplo.

Quando um usuário abre o app usando um link direto explícito, a backstack da tarefa é limpa e substituída pelo destino do link direto. Ao aninhar gráficos, o destino inicial de cada nível de aninhamento, ou seja, o destino inicial de cada elemento <navigation> na hierarquia, também é adicionado à pilha. Isso significa que, quando um usuário pressiona o botão "Voltar" em um destino de link direto, ele navega pela pilha de navegação como se tivesse entrado no app a partir do ponto de entrada.

Gráficos programáticos

Se o gráfico de navegação for definido de maneira programática (como é comum no Navigation Compose ou na DSL do Kotlin), recomendamos o uso de TaskStackBuilder para criar o link direto PendingIntent.

val id = "exampleId"
val context = LocalContext.current
val deepLinkIntent = Intent(
    Intent.ACTION_VIEW,
    "https://www.example.com/profile/$id".toUri(),
    context,
    MyActivity::class.java
)

val pendingIntent: PendingIntent? = TaskStackBuilder.create(context).run {
    addNextIntentWithParentStack(deepLinkIntent)
    getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}

Gráficos XML

Você pode usar a NavDeepLinkBuilder classe para construir uma PendingIntent, como mostrado no exemplo abaixo. Se o contexto fornecido não for uma Activity, o construtor usará PackageManager.getLaunchIntentForPackage() como a atividade padrão para iniciar, se disponível.

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent();

Por padrão, o NavDeepLinkBuilder inicia seu link direto explícito para o lançamento padrão da Activity declarada no manifesto do app. Se o NavHost estiver em outra atividade, especifique o nome do componente ao criar o builder de links diretos:

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(DestinationActivity::class.java)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(DestinationActivity.class)
        .createPendingIntent();

Se você tiver um ComponentName, poderá transmiti-lo diretamente para o builder:

Kotlin

val componentName = ...

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(componentName)
    .createPendingIntent()

Java

ComponentName componentName = ...;

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(componentName)
        .createPendingIntent();

Se você já tiver um NavController, também será possível criar um link direto usando NavController.createDeepLink().

Criar um link direto implícito

Um link direto implícito é uma referência a um destino específico em um app. Quando o link direto é invocado, por exemplo, quando um usuário clica em um link, o Android pode abrir o app no destino correspondente.

Os links diretos podem ser correspondidos por URI, ações de intent e tipos MIME. É possível especificar vários tipos de correspondência para um único link direto, mas a correspondência de argumentos de URI é priorizada, seguida pela de ações e, em seguida, pela de tipos MIME.

Gráficos programáticos

Se você definir o gráfico de navegação de maneira programática (usando o Navigation Compose ou a DSL do Kotlin), defina links diretos no código.

Escrever

No Navigation Compose, é possível definir links diretos como parte do builder de destino composable() usando o parâmetro deepLinks. Ele aceita uma lista de NavDeepLink objetos, que podem ser criados usando a navDeepLink() função:

@Serializable
data class Profile(val id: String)

val uri = "https://www.example.com"

composable<Profile>(
  deepLinks = listOf(
    navDeepLink<Profile>(basePath = "$uri/profile")
  )
) { backStackEntry ->
  val profile: Profile = backStackEntry.toRoute()
  ProfileScreen(id = profile.id)
}

DSL do Kotlin

Ao usar a DSL do Kotlin, é possível definir links diretos usando a deepLink() função do builder no bloco de destino:

@Serializable
data class Profile(val id: String)

val uri = "https://www.example.com"

fragment<ProfileFragment, Profile> {
    deepLink<Profile>(basePath = "$uri/profile")
}

Adicionar filtros de intent para gráficos programáticos

Como os gráficos de navegação programáticos são criados no ambiente de execução, o componente de navegação não pode gerar automaticamente os elementos <intent-filter>correspondentes em seu AndroidManifest.xml. Em vez disso, é necessário adicionar manualmente os elementos adequados <intent-filter>.

Para ativar o link direto nos exemplos anteriores, adicione o código abaixo ao elemento correspondente <activity> no manifesto:

<activity …>
  <intent-filter>
    ...
    <data android:scheme="https" android:host="www.example.com" />
  </intent-filter>
</activity>

Gráficos XML

Para criar um link direto implícito em um gráfico baseado em XML, defina o <deepLink> elemento diretamente no XML ou use o Navigation Editor.

Veja um exemplo de link direto que contém um URI, uma ação e um tipo MIME:

<fragment android:id="@+id/a"
          android:name="com.example.myapplication.FragmentA"
          tools:layout="@layout/a">
        <deepLink app:uri="www.example.com"
                app:action="android.intent.action.MY_ACTION"
                app:mimeType="type/subtype"/>
</fragment>

Você pode usar o Navigation Editor para criar um link direto implícito para um destino, desta forma:

  1. Na guia Design do Navigation Editor, selecione o destino do link direto.
  2. Clique em + na seção Deep Links do painel Attributes.
  3. Na caixa de diálogo Add Deep Link exibida, insira as informações do link direto.

    Observe o seguinte:

    • Os URIs sem um esquema são considerados http ou https. Por exemplo, www.google.com corresponde a http://www.google.com e https://www.google.com.
    • Os marcadores de parâmetros de caminho na forma de {placeholder_name} correspondem a um ou mais caracteres. Por exemplo, http://www.example.com/users/{id} corresponde a http://www.example.com/users/4. O componente de navegação tenta analisar os valores dos marcadores nos tipos apropriados, combinando nomes dos marcadores com os argumentos definidos para o destino do link direto. Se nenhum argumento for definido com o mesmo nome, um tipo String padrão será usado como valor do argumento. Você pode usar o caractere curinga * para criar correspondência com 0 ou mais caracteres.
    • Os marcadores de parâmetros de consulta podem ser usados em vez de ou em conjunto com parâmetros de caminho. Por exemplo, http://www.example.com/users/{id}?myarg={myarg} corresponde a http://www.example.com/users/4?myarg=28.
    • Os marcadores de parâmetros de consulta para variáveis definidas com valores padrão ou anuláveis não precisam ser correspondentes. Por exemplo, http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2} corresponde a http://www.example.com/users/4?arg2=28 ou http://www.example.com/users/4?arg1=7. Esse não é o caso com parâmetros de caminho. Por exemplo, http://www.example.com/users?arg1=7&arg2=28 não corresponde ao padrão acima porque o parâmetro de caminho necessário não é fornecido.
    • Os parâmetros de consulta irrelevantes não afetam a correspondência de URI de link direto. Por exemplo, http://www.example.com/users/{id} corresponde a http://www.example.com/users/4?extraneousParam=7, mesmo que extraneousParam não esteja definido no padrão de URI.
  4. Opcional: selecione Auto Verify para exigir que o Google verifique se você é o proprietário do URI. Para ver mais informações, consulte Verificar links de apps para Android.

  5. Clique em Adicionar. Um ícone de link aparece acima do destino selecionado para indicar que o destino tem um link direto.

  6. Clique na guia Code para alternar para a visualização XML. Um elemento <deepLink> aninhado foi adicionado ao destino:

    <deepLink app:uri="https://www.google.com" />
    

Para ativar o link direto implícito para gráficos baseados em XML, você também precisa fazer adições ao arquivo manifest.xml do app. Adicione um único <nav-graph> elemento a uma atividade que aponta para um gráfico de navegação existente, como mostrado no exemplo abaixo:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application ... >

        <activity name=".MainActivity" ...>
            ...

            <nav-graph android:value="@navigation/nav_graph" />

            ...

        </activity>
    </application>
</manifest>

Ao criar seu projeto, o componente de navegação substitui o <nav-graph> elemento por elementos <intent-filter> gerados por para corresponder a todos os links diretos no gráfico de navegação.

Links diretos implícitos e a backstack

Ao acionar um link direto implícito, o estado do backstack depende de o Intent implícito ter sido inicializado com a Intent.FLAG_ACTIVITY_NEW_TASK sinalização:

  • Se a sinalização estiver configurada, a backstack da tarefa vai ser limpa e substituída pelo destino do link direto. Assim como no caso do link direto explícito, ao aninhar gráficos, o destino inicial de cada nível de aninhamento, ou seja, o destino inicial de cada elemento <navigation> na hierarquia, também é adicionado à pilha. Isso significa que quando um usuário pressiona o botão "Voltar" em um destino de link direto, ele navega pela pilha de navegação como se tivesse entrado no app a partir do ponto de entrada.
  • Se a sinalização não estiver configurada, você vai permanecer na pilha de tarefas do app anterior, em que o link direto implícito foi acionado. Nesse caso, o botão "Voltar" levará você de volta ao app anterior, enquanto o botão "Para cima" iniciará a tarefa do app no destino pai hierárquico no gráfico de navegação.

Processar links diretos

É altamente recomendável usar sempre o padrão launchMode de standard ao usar o componente de navegação. Ao usar o modo de inicialização standard, o componente de navegação processa automaticamente os links diretos chamando handleDeepLink() para processar qualquer link direto explícito ou implícito na Intent. No entanto, isso não acontecerá automaticamente se a Activity for reutilizada ao usar um launchMode alternativo, como singleTop. Nesse caso, é necessário chamar handleDeepLink() manualmente em onNewIntent(), conforme mostrado no exemplo a seguir:

Kotlin

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    navController.handleDeepLink(intent)
}

Java

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    navController.handleDeepLink(intent);
}