Tworzenie precyzyjnego linku dla miejsca docelowego

W Androidzie precyzyjny link to link, który prowadzi bezpośrednio do określonego miejsca docelowego w aplikacji.

Aplikacja może obsługiwać 2 rodzaje precyzyjnych linków: explicitimplicit. Sposób implementacji precyzyjnych linków zależy od tego, jakiego typu wykresu – XML or programmatic – używa Twoja aplikacja.

Tworzenie precyzyjnego linku typu explicit

Jawny precyzyjny link to pojedynczy precyzyjny link, który za pomocą PendingIntent kieruje użytkowników do określonego miejsca w aplikacji. Jawny precyzyjny link możesz wyświetlać np. w powiadomieniu lub widżecie aplikacji.

Gdy użytkownik otworzy aplikację za pomocą precyzyjnego linku typu explicit, stos wsteczny zostanie wyczyszczony i zastąpiony miejscem docelowym precyzyjnego linku. Podczas zagnieżdżania wykresów do stosu dodawane jest też miejsce docelowe na początku każdego poziomu zagnieżdżenia, czyli miejsce docelowe na początku każdego elementu <navigation> w hierarchii. Oznacza to, że gdy użytkownik naciśnie przycisk Wstecz na stronie docelowej precyzyjnego linku, wróci do poprzedniego elementu w stosie nawigacji, tak jakby wszedł do aplikacji z punktu wejścia.

Wykresy automatyzacji

Jeśli Twój wykres nawigacji jest zdefiniowany programowo (co jest typowe w przypadku Navigation Compose lub Kotlin DSL), zalecamy użycie TaskStackBuilder do utworzenia precyzyjnego linku 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)
}

Wykresy XML

Możesz użyć klasy NavDeepLinkBuilder, aby utworzyć PendingIntent, jak pokazano w przykładzie poniżej. Pamiętaj, że jeśli podany kontekst nie jestActivity, konstruktor używaPackageManager.getLaunchIntentForPackage() jako domyślnej aktywności do uruchomienia, jeśli jest dostępna.

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

Domyślnie polecenie NavDeepLinkBuilder uruchamia precyzyjny link typu explicit w domyślnym uruchomieniu Activity zadeklarowanym w manifeście aplikacji. Jeśli NavHost znajduje się w innej aktywności, podczas tworzenia narzędzia do tworzenia precyzyjnych linków musisz podać nazwę komponentu:

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

Jeśli masz ComponentName, możesz przekazać go bezpośrednio do konstruktora:

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

Jeśli masz już NavController, możesz też utworzyć precyzyjny link za pomocą NavController.createDeepLink().

Tworzenie precyzyjnego linku typu implicit

Niejawny precyzyjny link odnosi się do konkretnego miejsca docelowego w aplikacji. Gdy precyzyjny link zostanie wywołany – na przykład gdy użytkownik kliknie link – Android może otworzyć aplikację w odpowiednim miejscu docelowym.

Precyzyjne linki można dopasowywać według identyfikatora URI, działań intencji i typów MIME. Możesz określić wiele typów dopasowania dla jednego linku do aplikacji, ale pamiętaj, że dopasowywanie argumentów URI ma wyższy priorytet niż dopasowywanie działania, a następnie typu MIME.

Wykresy automatyzacji

Jeśli definiujesz wykres nawigacji programowo (za pomocą Navigation Compose lub Kotlin DSL), precyzyjne linki określasz w kodzie.

Utwórz

W Navigation Compose możesz zdefiniować precyzyjne linki w ramach composable() konstruktora miejsca docelowego za pomocą parametru deepLinks. Przyjmuje listę obiektów NavDeepLink, które możesz utworzyć za pomocą funkcji navDeepLink():

@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

W przypadku DSL w języku Kotlin możesz zdefiniować precyzyjne linki za pomocą funkcji konstruktora deepLink() w bloku miejsca docelowego:

@Serializable
data class Profile(val id: String)

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

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

Dodawanie filtrów intencji do wykresów zautomatyzowanych

Zautomatyzowane wykresy nawigacji są tworzone w czasie działania aplikacji, więc komponent Navigation nie może automatycznie generować pasujących elementów <intent-filter> w pliku AndroidManifest.xml. Musisz ręcznie dodać odpowiednie elementy <intent-filter>.

Aby włączyć precyzyjny link w powyższych przykładach, dodaj w odpowiednim elemencie <activity> w pliku manifestu ten kod:

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

Wykresy XML

Aby utworzyć w grafie opartym na XML-u niejawny precyzyjny link, możesz zdefiniować element <deepLink> bezpośrednio w XML-u lub użyć edytora nawigacji.

Oto przykładowy precyzyjny link zawierający identyfikator URI, działanie i typ 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>

Możesz też utworzyć niejawny precyzyjny link do miejsca docelowego w Edytorze nawigacji w ten sposób:

  1. Na karcie Projekt w edytorze nawigacji wybierz miejsce docelowe precyzyjnego linku.
  2. W sekcji Linki bezpośrednie w panelu Atrybuty kliknij +.
  3. W wyświetlonym oknie Dodaj precyzyjny link wpisz informacje o precyzyjnym linku.

    Uwaga:

    • Identyfikatory URI bez schematu są traktowane jako http lub https. Na przykład www.google.com pasuje zarówno do http://www.google.com, jak i do https://www.google.com.
    • Symbole zastępcze parametrów ścieżki w formie {placeholder_name} pasują do co najmniej 1 znaku. Na przykład http://www.example.com/users/{id} pasuje do http://www.example.com/users/4. Komponent nawigacji próbuje przeanalizować wartości zastępcze i przekształcić je w odpowiednie typy, dopasowując nazwy zmiennych do zdefiniowanych argumentów, które są zdefiniowane dla miejsca docelowego precyzyjnego linku. Jeśli nie zdefiniowano argumentu o tej samej nazwie, dla wartości argumentu używany jest domyślny typ String. Za pomocą symbolu wieloznacznego .* możesz dopasować 0 lub więcej znaków.
    • Obiekty zastępcze parametrów zapytania mogą być używane zamiast parametrów ścieżki lub w połączeniu z nimi. Na przykład http://www.example.com/users/{id}?myarg={myarg} pasuje do http://www.example.com/users/4?myarg=28.
    • Zmienne zastępcze parametrów zapytania dla zmiennych zdefiniowanych z wartościami domyślnymi lub dopuszczającymi wartość null nie muszą być zgodne. Na przykład wzorzec http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2} pasuje do http://www.example.com/users/4?arg2=28 lub http://www.example.com/users/4?arg1=7. W przypadku parametrów ścieżki tak nie jest. Na przykład http://www.example.com/users?arg1=7&arg2=28 nie pasuje do powyższego wzorca, ponieważ nie podano wymaganego parametru ścieżki.
    • Dodatkowe parametry zapytania nie mają wpływu na dopasowywanie identyfikatorów URI precyzyjnych linków. Na przykład http://www.example.com/users/{id} pasuje do http://www.example.com/users/4?extraneousParam=7, mimo że extraneousParam nie jest zdefiniowany we wzorcu URI.
  4. (Opcjonalnie) Zaznacz Automatyczna weryfikacja, aby Google zweryfikowało, czy jesteś właścicielem identyfikatora URI. Więcej informacji znajdziesz w artykule Weryfikowanie linków do aplikacji na Androida.

  5. Kliknij Dodaj. Nad wybranym miejscem docelowym pojawi się ikona linku , co oznacza, że ma ono link bezpośredni.

  6. Kliknij kartę Kod, aby przełączyć się na widok XML. Do miejsca docelowego dodano zagnieżdżony element <deepLink>:

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

Aby włączyć niejawne precyzyjne linki w przypadku wykresów opartych na XML, musisz też wprowadzić zmiany w pliku manifest.xml aplikacji. Dodaj do aktywności pojedynczy element <nav-graph>, który wskazuje istniejący wykres nawigacji, jak pokazano w tym przykładzie:

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

Podczas tworzenia projektu komponent Navigation zastępuje element <nav-graph> wygenerowanymi elementami <intent-filter>, aby dopasować wszystkie precyzyjne linki na wykresie nawigacji.

Precyzyjne linki typu implicit i stos wsteczny

Stan stosu wstecznego podczas wywoływania precyzyjnego linku typu implicit zależy od tego, czy Intent został uruchomiony z flagą Intent.FLAG_ACTIVITY_NEW_TASK:

  • Jeśli flaga jest ustawiona, stos zadań jest czyszczony i zastępowany miejscem docelowym linku bezpośredniego. Podobnie jak w przypadku precyzyjnego linkowania, podczas zagnieżdżania wykresów do stosu dodawane jest też miejsce docelowe na początku każdego poziomu zagnieżdżenia, czyli miejsce docelowe na początku każdego elementu <navigation> w hierarchii. Oznacza to, że gdy użytkownik naciśnie przycisk Wstecz w miejscu docelowym precyzyjnego linku, wróci do poprzedniego elementu w stosie nawigacji, tak jakby wszedł do aplikacji z punktu wejścia.
  • Jeśli flaga nie jest ustawiona, pozostaniesz na stosie zadań poprzedniej aplikacji, w której został wywołany precyzyjny link typu implicit. W takim przypadku przycisk Wstecz przenosi Cię z powrotem do poprzedniej aplikacji, a przycisk W górę rozpoczyna zadanie aplikacji w hierarchicznym miejscu docelowym nadrzędnym w grafie nawigacji.

Obsługa precyzyjnych linków

Podczas korzystania z nawigacji zdecydowanie zalecamy używanie domyślnego ustawienia launchMode, czyli standard. W standardtrybie uruchamiania biblioteka Navigation automatycznie obsługuje precyzyjne linki, wywołując handleDeepLink() w celu przetworzenia wszystkich jawnych lub niejawnych precyzyjnych linków w Intent. Nie dzieje się to jednak automatycznie, jeśli Activity jest ponownie używany podczas korzystania z alternatywnego launchMode, np. singleTop. W takim przypadku konieczne jest ręczne wywołanie handleDeepLink()onNewIntent(), jak pokazano w tym przykładzie:

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