Как создать ссылку на контент для целевой страницы

В 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() в качестве действия по умолчанию для запуска, если оно доступно.

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

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

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

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

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

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

Как создать неявную ссылку на контент

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

Ссылки на контент можно сопоставлять по URI, действиям intent и 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>

Вы также можете использовать Navigation Editor, чтобы создать неявную ссылку на контент, выполнив следующие действия:

  1. На вкладке Design (Дизайн) в Navigation Editor выберите целевую страницу для ссылки на контент.
  2. Нажмите + в разделе Ссылки на контент на панели Атрибуты.
  3. В открывшемся диалоговом окне Добавление ссылки на контент введите информацию о ссылке.

    объявлений.

    • Если схема не указана, то подразумевается 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. Компонент Navigation пытается преобразовать значения плейсхолдеров в соответствующие типы, сопоставляя имена плейсхолдеров с определенными аргументами, которые определены для целевого объекта ссылки на контент. Если аргумент с таким же названием не определен, для значения аргумента используется тип String по умолчанию. Вы можете использовать подстановочный знак .* для соответствия нулю или более символов.
    • Плейсхолдеры параметров запроса можно использовать вместо параметров пути или вместе с ними. Например, 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. Это не относится к параметрам пути. Например, URL 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 приложения. Добавьте в объект activity один элемент <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. При использовании режима запуска standard Navigation автоматически обрабатывает ссылки на контент, вызывая handleDeepLink() для обработки явных и неявных ссылок на контент в Intent. Однако это не происходит автоматически, если Activity используется повторно с альтернативным launchMode, например singleTop. В этом случае необходимо вручную вызвать handleDeepLink() в onNewIntent(), как показано в следующем примере:

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