Crea un link diretto per una destinazione

In Android, un link diretto è un link che ti porta direttamente a una destinazione specifica all'interno di un'app.

Puoi supportare due tipi diversi di link diretti nella tua app: espliciti e impliciti. La modalità di implementazione dei link diretti varia a seconda del tipo di grafico utilizzato dall'app:XML or programmatic.

Creare un deep link esplicito

Un deep link esplicito è una singola istanza di un deep link che utilizza un PendingIntent per indirizzare gli utenti a una posizione specifica all'interno dell'app. Ad esempio, potresti mostrare un deep link esplicito come parte di una notifica o di un widget dell'app, ad esempio.

Quando un utente apre l'app tramite un deep link esplicito, il back stack delle attività viene cancellato e sostituito con la destinazione del deep link. Quando si annidano i grafici, allo stack viene aggiunta anche la destinazione iniziale di ogni livello di annidamento, ovvero la destinazione iniziale di ogni elemento <navigation> nella gerarchia. Ciò significa che quando un utente preme il pulsante Indietro da una destinazione di link diretto, torna indietro nello stack di navigazione come se fosse entrato nell'app dal suo punto di ingresso.

Grafici programmatici

Se il grafico di navigazione è definito in modo programmatico (come di consueto in Navigation Compose o Kotlin DSL), ti consigliamo di utilizzare TaskStackBuilder per creare il PendingIntent del link diretto.

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)
}

Grafici XML

Puoi utilizzare la NavDeepLinkBuilder classe per creare un PendingIntent, come mostrato nell'esempio riportato di seguito. Tieni presente che se il contesto fornito non è un Activity, il costruttore utilizza PackageManager.getLaunchIntentForPackage() come attività predefinita da avviare, se disponibile.

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();

Per impostazione predefinita, NavDeepLinkBuilder avvia il deep link esplicito nell' attività di avvio predefinita Activity dichiarata nel manifest dell'app. Se NavHost si trova in un'altra attività, devi specificarne il nome del componente quando crei il builder del link diretto:

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 hai un ComponentName, puoi passarlo direttamente al 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 hai un NavController, puoi anche creare un link diretto utilizzando NavController.createDeepLink().

Creare un deep link implicito

Un deep link implicito si riferisce a una destinazione specifica in un'app. Quando viene richiamato il deep link, ad esempio, quando un utente fa clic su un link, Android può aprire l'app nella destinazione corrispondente.

I link diretti possono essere abbinati in base a URI, azioni intent e tipi MIME. Puoi specificare più tipi di corrispondenza per un singolo link diretto, ma tieni presente che la corrispondenza degli argomenti URI ha la priorità, seguita dall'azione e poi dal tipo MIME.

Grafici programmatici

Se definisci il grafico di navigazione in modo programmatico (utilizzando Navigation Compose o Kotlin DSL), definisci i link diretti nel codice.

Compose

In Navigation Compose, puoi definire i link diretti come parte del builder di destinazione composable() utilizzando il parametro deepLinks. Accetta un elenco di NavDeepLink oggetti, che puoi creare utilizzando la navDeepLink() funzione:

@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)
}

Kotlin DSL

Quando utilizzi Kotlin DSL, puoi definire i link diretti utilizzando la deepLink() funzione del builder all'interno del blocco di destinazione:

@Serializable
data class Profile(val id: String)

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

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

Aggiungere filtri intent per i grafici programmatici

Poiché i grafici di navigazione programmatici vengono creati in fase di runtime, il componente Navigation non può generare automaticamente gli elementi <intent-filter>corrispondenti in AndroidManifest.xml. Devi invece aggiungere manualmente gli elementi appropriati <intent-filter>.

Per attivare il link diretto negli esempi precedenti, aggiungi quanto segue all'interno dell' elemento <activity> corrispondente nel manifest:

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

Grafici XML

Per creare un deep link implicito in un grafico basato su XML, puoi definire l' <deepLink> elemento direttamente in XML o utilizzare l'editor di navigazione.

Di seguito è riportato un esempio di link diretto che contiene un URI, un'azione e un 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>

Puoi anche utilizzare l'editor di navigazione per creare un deep link implicito a una destinazione come segue:

  1. Nella scheda Progettazione dell'editor di navigazione, seleziona la destinazione per il link diretto.
  2. Fai clic su + nella sezione Link diretti del riquadro Attributi.
  3. Nella finestra di dialogo Aggiungi link diretto visualizzata, inserisci le informazioni per il link diretto.

    Tieni presente quanto segue:

    • Gli URI senza schema vengono considerati come http o https. Ad esempio, www.google.com corrisponde sia a http://www.google.com sia a https://www.google.com.
    • I segnaposto dei parametri del percorso nel formato {placeholder_name} corrispondono a uno o più caratteri. Ad esempio, http://www.example.com/users/{id} corrisponde a http://www.example.com/users/4. Il componente Navigation tenta di analizzare i valori dei segnaposto in tipi appropriati abbinando i nomi dei segnaposto agli argomenti definiti per la destinazione del link diretto. Se non è definito alcun argomento con lo stesso nome, viene utilizzato un tipo String predefinito per il valore dell'argomento. Puoi utilizzare il carattere jolly .* per trovare la corrispondenza di 0 o più caratteri.
    • I segnaposto dei parametri di query possono essere utilizzati al posto dei parametri del percorso o in combinazione con questi. Ad esempio, http://www.example.com/users/{id}?myarg={myarg} corrisponde a http://www.example.com/users/4?myarg=28.
    • Non è necessario che i segnaposto dei parametri di query per le variabili definite con valori predefiniti o nullable corrispondano. Ad esempio, http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2} corrisponde a http://www.example.com/users/4?arg2=28 o http://www.example.com/users/4?arg1=7. Questo non è il caso dei parametri del percorso. Ad esempio, http://www.example.com/users?arg1=7&arg2=28 non corrisponde al pattern precedente perché non viene fornito il parametro del percorso obbligatorio.
    • I parametri di query estranei non influiscono sulla corrispondenza dell'URI del link diretto. Ad esempio, http://www.example.com/users/{id} corrisponde http://www.example.com/users/4?extraneousParam=7, anche se extraneousParam non è definito nel pattern URI.
  4. (Facoltativo) Seleziona Verifica automatica per richiedere a Google di verificare che tu sia il proprietario dell'URI. Per maggiori informazioni, consulta Verificare gli app link Android.

  5. Fai clic su Aggiungi. Sopra la destinazione selezionata viene visualizzata un'icona di link per indicare che la destinazione ha un link diretto.

  6. Fai clic sulla scheda Codice per passare alla visualizzazione XML. Alla destinazione è stato aggiunto un <deepLink> elemento annidato:

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

Per attivare i link diretti impliciti per i grafici basati su XML, devi anche apportare modifiche al file manifest.xml dell'app. Aggiungi un singolo <nav-graph> elemento a un'attività che rimanda a un grafico di navigazione esistente, come mostrato nell'esempio seguente:

<?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>

Quando crei il progetto, il componente Navigation sostituisce l'elemento <nav-graph> con elementi <intent-filter> generati per corrispondere a tutti i link diretti nel grafico di navigazione.

Link diretti impliciti e back stack

Quando si attiva un deep link implicito, lo stato del back stack dipende dal fatto che l'intent implicito sia stato avviato con il flag:IntentIntent.FLAG_ACTIVITY_NEW_TASK

  • Se il flag è impostato, il back stack delle attività viene cancellato e sostituito con la destinazione del deep link. Come per i link diretti espliciti, quando si annidano i grafici, allo stack viene aggiunta anche la destinazione iniziale di ogni livello di annidamento, ovvero la destinazione iniziale di ogni elemento <navigation> nella gerarchia. Ciò significa che quando un utente preme il pulsante Indietro da una destinazione di link diretto, torna indietro nello stack di navigazione come se fosse entrato nell'app dal suo punto di ingresso.
  • Se il flag non è impostato, rimani nello stack delle attività dell'app precedente in cui è stato attivato il deep link implicito. In questo caso, il pulsante Indietro ti riporta all'app precedente, mentre il pulsante Su avvia l'attività dell'app nella destinazione principale gerarchica all'interno del grafico di navigazione.

Gestire i link diretti

Ti consigliamo vivamente di utilizzare sempre il predefinito launchMode di standard quando utilizzi Navigation. Quando utilizzi la modalità di avvio standard, Navigation gestisce automaticamente i link diretti chiamando handleDeepLink() per elaborare eventuali link diretti espliciti o impliciti all'interno del Intent. Tuttavia, questo non avviene automaticamente se l'Activity viene riutilizzata quando si utilizza un launchMode alternativo come singleTop. In questo caso, è necessario chiamare manualmente handleDeepLink() in onNewIntent(), come mostrato nell'esempio seguente:

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);
}