Создайте глубокую ссылку для места назначения

В Android глубокая ссылка — это ссылка, которая ведет непосредственно к определенному разделу внутри приложения.

В вашем приложении могут поддерживаться два разных типа глубоких ссылок: явные и неявные . Способ реализации глубоких ссылок зависит от типа графа XML or programmatic — используемого вашим приложением.

Создайте явную прямую ссылку

Явная глубокая ссылка — это единичный экземпляр глубокой ссылки, использующий PendingIntent для перевода пользователей в определенное место внутри вашего приложения. Например, вы можете отображать явную глубокую ссылку в виде уведомления или виджета приложения.

Когда пользователь открывает ваше приложение по явной прямой ссылке, стек задач "Назад" очищается и заменяется адресом перехода по прямой ссылке. При вложенности графов начальный адрес каждого уровня вложенности — то есть начальный адрес каждого элемента <navigation> в иерархии — также добавляется в стек. Это означает, что когда пользователь нажимает кнопку "Назад" по прямой ссылке, он возвращается вверх по стеку навигации так же, как если бы он вошел в ваше приложение с точки входа.

Программные графы

Если ваш навигационный граф определен программно (как это обычно бывает в Navigation Compose или Kotlin DSL), мы рекомендуем использовать TaskStackBuilder для создания 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)
}

XML-графики

Для создания объекта PendingIntent можно использовать класс NavDeepLinkBuilder , как показано в примере ниже. Обратите внимание, что если предоставленный контекст не является Activity , конструктор использует PackageManager.getLaunchIntentForPackage() в качестве Activity по умолчанию для запуска, если таковая доступна.

Котлин

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

По умолчанию NavDeepLinkBuilder запускает вашу явную глубокую ссылку в Activity по умолчанию, объявленной в манифесте вашего приложения. Если ваш NavHost находится в другой Activity, необходимо указать имя его компонента при создании построителя глубоких ссылок:

Котлин

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

Если у вас есть ComponentName , вы можете передать его напрямую в построитель:

Котлин

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

Если у вас уже есть NavController , вы также можете создать прямую ссылку, используя NavController.createDeepLink() .

Создайте неявную глубокую ссылку.

Неявная глубокая ссылка указывает на конкретное место в приложении. Когда глубокая ссылка активируется — например, когда пользователь нажимает на ссылку — Android может открыть ваше приложение по соответствующему адресу.

Глубокие ссылки могут сопоставляться по URI, действиям намерений и MIME-типам. Для одной глубокой ссылки можно указать несколько типов соответствия, но обратите внимание, что приоритет отдается сопоставлению аргументов URI, затем действиям, а затем MIME-типу.

Программные графы

Если вы определяете граф навигации программно (используя Navigation Compose или Kotlin DSL), то глубокие ссылки определяются в коде.

Сочинить

В Navigation Compose вы можете определять глубокие ссылки как часть конструктора целевых объектов composable() с помощью параметра deepLinks . Он принимает список объектов NavDeepLink , которые можно создать с помощью функции 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

При использовании Kotlin DSL вы можете определять прямые ссылки с помощью функции-конструктора deepLink() внутри целевого блока:

@Serializable
data class Profile(val id: String)

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

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

Добавьте фильтры намерений для программных графов.

Поскольку графы программной навигации создаются во время выполнения, компонент Navigation не может автоматически генерировать соответствующие элементы <intent-filter> в вашем AndroidManifest.xml . Вместо этого вам необходимо вручную добавить соответствующие элементы <intent-filter> .

Чтобы включить прямую ссылку, как в приведенных выше примерах, добавьте следующее внутри соответствующего элемента <activity> в вашем манифесте:

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

XML-графики

Для создания неявной глубокой ссылки в XML-графе можно определить элемент <deepLink> непосредственно в XML-файле или использовать редактор навигации.

Вот пример прямой ссылки, содержащей URI, действие и 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>

Вы также можете использовать редактор навигации для создания неявной прямой ссылки на целевой ресурс следующим образом:

  1. На вкладке «Дизайн» редактора навигации выберите место назначения для прямой ссылки.
  2. Нажмите кнопку «+» в разделе «Глубокие ссылки» на панели «Атрибуты» .
  3. В появившемся диалоговом окне «Добавить прямую ссылку» введите информацию для вашей прямой ссылки.

    Обратите внимание на следующее:

    • URI без указания схемы считаются либо http , либо https . Например, www.google.com соответствует как http://www.google.com , так и https://www.google.com .
    • В параметрах пути в формате {placeholder_name} соответствует одному или нескольким символам. Например, http://www.example.com/users/{id} соответствует http://www.example.com/users/4 . Компонент навигации пытается преобразовать значения заполнителей в соответствующие типы, сопоставляя имена заполнителей с определенными аргументами , заданными для целевой ссылки. Если аргумент с таким же именем не определен, для значения аргумента используется тип String по умолчанию. Вы можете использовать символ подстановки .* для сопоставления 0 или более символов.
    • Заполнители параметров запроса можно использовать вместо параметров пути или совместно с ними. Например, http://www.example.com/users/{id}?myarg={myarg} соответствует http://www.example.com/users/4?myarg=28 .
    • В параметрах запроса для переменных, определенных со значениями по умолчанию или допускающими значение NULL, совпадение не является обязательным. Например, http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2} соответствует http://www.example.com/users/4?arg2=28 или http://www.example.com/users/4?arg1=7 . С параметрами пути дело обстоит иначе. Например, http://www.example.com/users?arg1=7&arg2=28 не соответствует указанному шаблону, поскольку не указан необходимый параметр пути.
    • Посторонние параметры запроса не влияют на сопоставление URI глубоких ссылок. Например, http://www.example.com/users/{id} соответствует http://www.example.com/users/4?extraneousParam=7 , даже если extraneousParam не определен в шаблоне URI.
  4. (Необязательно) Установите флажок «Автоматическая проверка» , чтобы Google подтвердил, что вы являетесь владельцем URI. Дополнительную информацию см. в разделе «Проверка ссылок в приложениях Android» .

  5. Нажмите «Добавить» . Значок ссылки. Этот значок появляется над выбранным пунктом назначения, указывая на то, что этот пункт содержит прямую ссылку.

  6. Нажмите вкладку «Код» , чтобы переключиться в XML-режим. В целевую папку добавлен вложенный элемент <deepLink> :

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

Для включения неявной глубокой ссылки для XML-графов необходимо также внести изменения в файл manifest.xml вашего приложения. Добавьте в активность один элемент <nav-graph> , указывающий на существующий навигационный граф, как показано в следующем примере:

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

При сборке проекта компонент Navigation заменяет элемент <nav-graph> сгенерированными элементами <intent-filter> , соответствующими всем глубоким ссылкам в графе навигации.

Неявные глубокие ссылки и обратный стек

При запуске неявной глубокой ссылки состояние стека возврата зависит от того, был ли неявный Intent запущен с флагом Intent.FLAG_ACTIVITY_NEW_TASK :

  • Если флаг установлен, стек возврата задачи очищается и заменяется целевой ссылкой. Как и в случае с явной глубокой ссылкой , при вложенности графов начальная целевая ссылка с каждого уровня вложенности — то есть начальная целевая ссылка от каждого элемента <navigation> в иерархии — также добавляется в стек. Это означает, что когда пользователь нажимает кнопку «Назад» из целевой ссылки, он возвращается вверх по стеку навигации так же, как если бы он вошел в ваше приложение с его точки входа.
  • Если флаг не установлен, вы остаетесь в стеке задач предыдущего приложения, где была активирована неявная глубокая ссылка. В этом случае кнопка «Назад» возвращает вас в предыдущее приложение, а кнопка «Вверх» запускает задачу вашего приложения на иерархическом родительском пункте назначения в вашем графе навигации.

Обработка прямых ссылок

Настоятельно рекомендуется всегда использовать launchMode по умолчанию — standard при использовании Navigation. При использовании standard режима запуска Navigation автоматически обрабатывает глубокие ссылки, вызывая метод handleDeepLink() для обработки любых явных или неявных глубоких ссылок внутри Intent . Однако это не происходит автоматически, если Activity используется повторно при применении альтернативного launchMode например singleTop . В этом случае необходимо вручную вызвать handleDeepLink() в onNewIntent() , как показано в следующем примере:

Котлин

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

Java

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