Используйте пузыри, чтобы позволить пользователям участвовать в беседах.

«Всплывающие окна» упрощают пользователям просмотр и участие в беседах.

Рисунок 1. Облачко чата.

В систему уведомлений встроены всплывающие окна. Они отображаются поверх другого контента приложения и следуют за пользователем, куда бы он ни пошел. Пользователи могут разворачивать всплывающие окна, чтобы отобразить и взаимодействовать с содержимым приложения, и сворачивать их, когда они не используются.

Когда устройство заблокировано или активирована функция постоянно включенного экрана, появляются всплывающие уведомления, как обычно.

Функция всплывающих окон является необязательной. Когда приложение отображает первое всплывающее окно, в диалоговом окне запроса разрешения предлагаются два варианта:

  • Заблокируйте все всплывающие уведомления в вашем приложении. Уведомления не блокируются, но они никогда не отображаются в виде всплывающих окон.
  • Разрешите все всплывающие уведомления из вашего приложения. Все уведомления, отправленные с использованием BubbleMetaData будут отображаться в виде всплывающих окон.

API всплывающих уведомлений

Всплывающие уведомления создаются с помощью API уведомлений, поэтому отправляйте уведомление как обычно. Если вы хотите, чтобы ваше уведомление отображалось в виде всплывающего окна, добавьте к нему дополнительные данные.

Расширенное представление всплывающего окна создается на основе выбранного вами действия. Настройте действие для корректного отображения в виде всплывающего окна. Действие должно быть изменяемым по размеру и встроенным . Если ни одно из этих требований не выполняется, оно будет отображаться как уведомление.

Следующий код демонстрирует, как реализовать всплывающее окно:

<activity
  android:name=".bubbles.BubbleActivity"
  android:theme="@style/AppTheme.NoActionBar"
  android:label="@string/title_activity_bubble"
  android:allowEmbedded="true"
  android:resizeableActivity="true"
/>

Если ваше приложение отображает несколько всплывающих окон одного типа, например, несколько чатов с разными контактами, то активность должна иметь возможность запускать несколько экземпляров. На устройствах под управлением Android 10 и ниже уведомления не отображаются в виде всплывающих окон, если вы явно не установите documentLaunchMode в значение "always" . Начиная с Android 11, вам не нужно явно устанавливать это значение, поскольку система автоматически устанавливает documentLaunchMode для всех диалогов в значение "always" .

Чтобы отправить пузырёк, выполните следующие шаги:

  1. Создайте уведомление, как обычно.
  2. Для создания объекта BubbleMetadata вызовите BubbleMetadata.Builder(PendingIntent, Icon) или BubbleMetadata.Builder(String) .
  3. Используйте setBubbleMetadata() , чтобы добавить метаданные к уведомлению.
  4. Если вы ориентируетесь на Android 11 или более позднюю версию, убедитесь, что метаданные всплывающего окна или уведомления содержат ссылку на ярлык для обмена данными.
  5. Измените ваше приложение так, чтобы оно не отменяло уведомления, отображаемые в виде всплывающих окон. Чтобы проверить, запущено ли уведомление в виде всплывающего окна, вызовите Activity#isLaunchedFromBubble() . Отмена уведомления удаляет всплывающее окно с экрана. Открытие всплывающего окна автоматически скрывает связанное с ним уведомление.

Эти шаги показаны в следующем примере:

Котлин

// Create a bubble intent.
val target = Intent(context, BubbleActivity::class.java)
val bubbleIntent = PendingIntent.getActivity(context, 0, target, 0 /* flags */)
val category = "com.example.category.IMG_SHARE_TARGET"

val chatPartner = Person.Builder()
    .setName("Chat partner")
    .setImportant(true)
    .build()

// Create a sharing shortcut.
val shortcutId = generateShortcutId()
val shortcut =
   ShortcutInfo.Builder(mContext, shortcutId)
       .setCategories(setOf(category))
       .setIntent(Intent(Intent.ACTION_DEFAULT))
       .setLongLived(true)
       .setShortLabel(chatPartner.name)
       .build()

// Create a bubble metadata.
val bubbleData = Notification.BubbleMetadata.Builder(bubbleIntent,
            Icon.createWithResource(context, R.drawable.icon))
    .setDesiredHeight(600)
    .build()

// Create a notification, referencing the sharing shortcut.
val builder = Notification.Builder(context, CHANNEL_ID)
    .setContentIntent(contentIntent)
    .setSmallIcon(smallIcon)
    .setBubbleMetadata(bubbleData)
    .setShortcutId(shortcutId)
    .addPerson(chatPartner)

Java

// Create a bubble intent.
Intent target = new Intent(mContext, BubbleActivity.class);
PendingIntent bubbleIntent =
    PendingIntent.getActivity(mContext, 0, target, 0 /* flags */);

private val CATEGORY_TEXT_SHARE_TARGET =
    "com.example.category.IMG_SHARE_TARGET"

Person chatPartner = new Person.Builder()
        .setName("Chat partner")
        .setImportant(true)
        .build();

// Create a sharing shortcut.
private String shortcutId = generateShortcutId();
ShortcutInfo shortcut =
   new ShortcutInfo.Builder(mContext, shortcutId)
       .setCategories(Collections.singleton(CATEGORY_TEXT_SHARE_TARGET))
       .setIntent(Intent(Intent.ACTION_DEFAULT))
       .setLongLived(true)
       .setShortLabel(chatPartner.getName())
       .build();

// Create a bubble metadata.
Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder(bubbleIntent,
            Icon.createWithResource(context, R.drawable.icon))
        .setDesiredHeight(600)
        .build();

// Create a notification, referencing the sharing shortcut.
Notification.Builder builder =
    new Notification.Builder(mContext, CHANNEL_ID)
        .setContentIntent(contentIntent)
        .setSmallIcon(smallIcon)
        .setBubbleMetadata(bubbleData)
        .setShortcutId(shortcutId)
        .addPerson(chatPartner);

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

Создайте расширенный пузырь

Вы можете настроить автоматическое отображение всплывающего окна. Мы рекомендуем использовать эту функцию только в том случае, если пользователь выполняет действие, приводящее к появлению всплывающего окна, например, нажимает кнопку для начала нового чата. В этом случае также имеет смысл отключить первоначальное уведомление, отправляемое при создании всплывающего окна.

Существуют методы, позволяющие установить флаги, которые включают такое поведение: setAutoExpandBubble() и setSuppressNotification() .

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

Котлин

val bubbleMetadata = Notification.BubbleMetadata.Builder()
    .setDesiredHeight(600)
    .setIntent(bubbleIntent)
    .setAutoExpandBubble(true)
    .setSuppressNotification(true)
    .build()

Java

Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder()
        .setDesiredHeight(600)
        .setIntent(bubbleIntent)
        .setAutoExpandBubble(true)
        .setSuppressNotification(true)
        .build();

Жизненный цикл содержимого пузырьков

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

Когда всплывающее окно сворачивается или закрывается, активность уничтожается. Это может привести к кэшированию процесса и его последующему завершению, в зависимости от того, запущены ли в приложении другие компоненты на переднем плане.

Когда появляются пузырьки

Чтобы минимизировать отвлекающие факторы для пользователя, всплывающие окна появляются только при определенных обстоятельствах.

Если приложение ориентировано на Android 11 или выше, уведомление не отображается в виде всплывающего окна, если оно не соответствует требованиям диалога . Если приложение ориентировано на Android 10 или ниже, уведомление отображается в виде всплывающего окна только при выполнении одного или нескольких из следующих условий:

  • В уведомлении используется MessagingStyle , и добавлен объект Person .
  • Уведомление получено в результате вызова Service.startForeground , имеет category CATEGORY_CALL и содержит добавленного Person .
  • В момент отправки уведомления приложение находится на переднем плане.

Если ни одно из этих условий не выполняется, вместо всплывающего окна отображается уведомление.

Запуск мероприятий из «пузырей»

Когда всплывающее окно запускает новое действие, это новое действие либо запустится в рамках той же задачи и в том же всплывающем окне, либо в новой задаче в полноэкранном режиме, свернув всплывающее окно, которое его запустило.

Чтобы запустить новую активность в той же задаче, что и всплывающее окно: 1. Используйте контекст активности при запуске интентов, activity.startActivity(intent) , и 2. Не устанавливайте флаг FLAG_ACTIVITY_NEW_TASK для интента.

В противном случае новое действие запускается в новой задаче, и всплывающее окно схлопывается.

Следует помнить, что всплывающее окно представляет собой конкретный диалог, поэтому действия, запускаемые внутри всплывающего окна, должны быть связаны с этим диалогом. Кроме того, запуск действия внутри всплывающего окна увеличивает количество задач в нем и может потенциально усложнить пользовательский опыт, особенно в части навигации.

Передовые методы

  • Уведомление в виде всплывающего окна отправляется только в случае необходимости, например, в рамках текущей переписки или если пользователь явно запрашивает всплывающее окно для отображения контента. Всплывающие окна занимают место на экране и закрывают другой контент приложения.
  • Убедитесь, что всплывающее уведомление также работает как обычное уведомление. Когда пользователь отключает всплывающее уведомление, оно отображается как обычное уведомление.
  • При переопределении метода onBackPressed в активности всплывающего окна необходимо вызывать super.onBackPressed . В противном случае всплывающее окно может работать некорректно.

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

  • Обновите BubbleMetadata , чтобы отключить уведомление. Вызовите BubbleMetadata.Builder.setSuppressNotification() . Это удалит значок, указывающий на то, что пользователь взаимодействовал с сообщением.
  • Установите значение Notification.Builder.setOnlyAlertOnce() в true , чтобы отключить звук или вибрацию, сопровождающие обновление BubbleMetadata .

Пример приложения

Демонстрационное приложение SociaLite — это приложение для общения, использующее всплывающие окна. В целях демонстрации в этом приложении используются чат-боты. В реальных приложениях всплывающие окна следует использовать для сообщений от людей.