Текущая деятельность

В Wear OS сочетание текущего действия с текущим уведомлением добавляет это уведомление на дополнительные поверхности пользовательского интерфейса Wear OS. Это позволяет пользователям более активно участвовать в длительных действиях.

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

Например, пользователь Wear OS может использовать приложение для тренировок, чтобы записать пробежку во время занятия, а затем выйти из этого приложения, чтобы начать какую-либо другую задачу. Когда пользователь выходит из приложения для тренировок, приложение переходит к постоянному уведомлению, связанному с некоторой фоновой работой, чтобы держать пользователя в курсе своей пробежки. Уведомление предоставляет пользователю обновления и простой способ вернуться в приложение.

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

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

Например, в этом приложении для тренировок информация может отображаться на циферблате пользователя в виде значка бега, на который можно нажать:

значок бега

Рисунок 1. Индикатор активности.

В разделе «Недавние» глобальной панели запуска приложений также перечислены все текущие действия:

пусковая установка

Рисунок 2. Глобальная панель запуска.

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

таймер

Рисунок 3. Таймер: активно отсчитывает время и завершается, когда таймер приостанавливается или останавливается.

карта

Рис. 4. Пошаговая навигация: объявляет маршруты к месту назначения. Завершается, когда пользователь достигает пункта назначения или останавливает навигацию.

музыка

Рисунок 5. Медиа: музыка воспроизводится на протяжении всего сеанса. Завершается сразу после того, как пользователь приостанавливает сеанс.

Wear автоматически создает текущие действия для мультимедийных приложений.

Подробный пример создания текущих действий для других типов приложений см. в кодовой лаборатории «Текущие действия» .

Настраивать

Чтобы начать использовать API текущих действий в своем приложении, добавьте следующие зависимости в файл build.gradle вашего приложения:

dependencies {
  implementation "androidx.wear:wear-ongoing:1.0.0"
  // Includes LocusIdCompat and new Notification categories for Ongoing Activity.
  implementation "androidx.core:core:1.6.0"
}

Начать текущую деятельность

Начните с создания текущего уведомления, а затем текущего действия.

Создать постоянное уведомление

Текущая деятельность тесно связана с текущим уведомлением. Они работают вместе, чтобы информировать пользователей о задаче, которой пользователь активно занимается, или о задаче, которая каким-то образом ожидает выполнения и, следовательно, занимает устройство.

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

  • Уведомления — это запасной вариант для устройств, которые не поддерживают текущие действия. Уведомление — это единственная поверхность, которую ваше приложение отображает во время работы в фоновом режиме.
  • В Android 11 и более поздних версиях Wear OS скрывает уведомление в области уведомлений, когда приложение отображается как текущее действие на дополнительных поверхностях.
  • Текущая реализация использует само Notification в качестве механизма связи.

Создайте постоянное уведомление, используя Notification.Builder.setOngoing .

Начать текущую деятельность

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

Котлин

var notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
      
      .setSmallIcon(..)
      .setOngoing(true)

val ongoingActivityStatus = Status.Builder()
    // Sets the text used across various surfaces.
    .addTemplate(mainText)
    .build()

val ongoingActivity =
    OngoingActivity.Builder(
        applicationContext, NOTIFICATION_ID, notificationBuilder
    )
        // Sets the animated icon that will appear on the watch face in
        // active mode.
        // If it isn't set, the watch face will use the static icon in
        // active mode.
        .setAnimatedIcon(R.drawable.ic_walk)
        // Sets the icon that will appear on the watch face in ambient mode.
        // Falls back to Notification's smallIcon if not set.
        // If neither is set, an Exception is thrown.
        .setStaticIcon(R.drawable.ic_walk)
        // Sets the tap/touch event so users can re-enter your app from the
        // other surfaces.
        // Falls back to Notification's contentIntent if not set.
        // If neither is set, an Exception is thrown.
        .setTouchIntent(activityPendingIntent)
        // Here, sets the text used for the Ongoing Activity (more
        // options are available for timers and stopwatches).
        .setStatus(ongoingActivityStatus)
        .build()

ongoingActivity.apply(applicationContext)

notificationManager.notify(NOTIFICATION_ID, builder.build())

Ява

NotificationCompat.Builder notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
      
      .setSmallIcon(..)
      .setOngoing(true);

OngoingActivityStatus ongoingActivityStatus = OngoingActivityStatus.Builder()
    // Sets the text used across various surfaces.
    .addTemplate(mainText)
    .build();

OngoingActivity ongoingActivity =
    OngoingActivity.Builder(
        applicationContext, NOTIFICATION_ID, notificationBuilder
    )
        // Sets the animated icon that will appear on the watch face in
        // active mode.
        // If it isn't set, the watch face will use the static icon in
        // active mode.
        .setAnimatedIcon(R.drawable.ic_walk)
        // Sets the icon that will appear on the watch face in ambient mode.
        // Falls back to Notification's smallIcon if not set.
        // If neither is set, an Exception is thrown.
        .setStaticIcon(R.drawable.ic_walk)
        // Sets the tap/touch event so users can re-enter your app from the
        // other surfaces.
        // Falls back to Notification's contentIntent if not set.
        // If neither is set, an Exception is thrown.
        .setTouchIntent(activityPendingIntent)
        // Here, sets the text used for the Ongoing Activity (more
        // options are available for timers and stopwatches).
        .setStatus(ongoingActivityStatus)
        .build();

ongoingActivity.apply(applicationContext);

notificationManager.notify(NOTIFICATION_ID, builder.build());

Следующие шаги демонстрируют наиболее важную часть предыдущего примера:

  1. Вызовите .setOngoing(true) в NotificationCompat.Builder и задайте все необязательные поля.

  2. Создайте OngoingActivityStatus — или другой параметр состояния, как описано в следующем разделе — для представления текста.

  3. Создайте OngoingActivity и установите идентификатор уведомления.

  4. Вызовите apply() в OngoingActivity с контекстом.

  5. Вызовите notificationManager.notify() и передайте тот же идентификатор уведомления, который установлен в текущем действии, чтобы связать их вместе.

Статус

Вы используете Status , чтобы предоставить пользователю текущий текущий статус OngoingActivity на новых поверхностях, например в разделе «Последние» средства запуска. Чтобы использовать эту функцию, используйте подкласс Status.Builder .

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

Затем вы можете настроить отображение текста с помощью интервалов, используя метод addTemplate() и указав любые динамические части текста как Status.Part .

В следующем примере показано, как сделать слово «время» красным. В примере используется Status.StopwatchPart для представления секундомера в разделе «Последние» средства запуска приложений.

Котлин

val htmlStatus =
        "<p>The <font color=\"red\">time</font> on your current #type# is #time#.</p>"

val statusTemplate =
        Html.fromHtml(
                htmlStatus,
                Html.FROM_HTML_MODE_COMPACT
        )

// Creates a 5 minute timer.
// Note the use of SystemClock.elapsedRealtime(), not System.currentTimeMillis().
val runStartTime = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(5)

val status = new Status.Builder()
   .addTemplate(statusTemplate)
   .addPart("type", Status.TextPart("run"))
   .addPart("time", Status.StopwatchPart(runStartTime)
   .build()

Ява

String htmlStatus =
        "<p>The <font color=\"red\">time</font> on your current #type# is #time#.</p>";

Spanned statusTemplate =
        Html.fromHtml(
                htmlStatus,
                Html.FROM_HTML_MODE_COMPACT
        );

// Creates a 5 minute timer.
// Note the use of SystemClock.elapsedRealtime(), not System.currentTimeMillis().
Long runStartTime = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(5);

Status status = new Status.Builder()
   .addTemplate(statusTemplate)
   .addPart("type", new Status.TextPart("run"))
   .addPart("time", new Status.StopwatchPart(runStartTime)
   .build();

Чтобы сослаться на часть шаблона, используйте имя, окруженное # . Чтобы получить # в выходных данных, используйте ## в шаблоне.

В предыдущем примере HTMLCompat используется для создания CharSequence для передачи в шаблон, что проще, чем вручную определять объект Spannable .

Дополнительные настройки

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

Постоянное уведомление

  • Набор категорий определяет приоритет текущей деятельности.
    • CATEGORY_CALL : входящий голосовой или видеовызов или аналогичный запрос на синхронную связь.
    • CATEGORY_NAVIGATION : карта или пошаговая навигация.
    • CATEGORY_TRANSPORT : управление транспортировкой мультимедиа для воспроизведения.
    • CATEGORY_ALARM : будильник или таймер.
    • CATEGORY_WORKOUT : тренировка (новая категория)
    • CATEGORY_LOCATION_SHARING : временный обмен местоположением (новая категория)
    • CATEGORY_STOPWATCH : секундомер (новая категория)

Текущая деятельность

  • Анимированная иконка: черно-белый вектор, желательно с прозрачным фоном. Отображается на циферблате в активном режиме. Если анимированный значок не указан, используется значок уведомления по умолчанию. (Значок уведомления по умолчанию различен для каждого приложения.)

  • Статическая иконка: векторная иконка с прозрачным фоном. Отображается на циферблате в окружающем режиме. Если анимированный значок не установлен, на циферблате в активном режиме используется статический значок. Если это не предусмотрено, используется значок уведомления. Если ни один из них не установлен, генерируется исключение. (В средстве запуска приложения по-прежнему используется значок приложения.)

  • OngoingActivityStatus: обычный текст или Chronometer . Отображается в разделе «Последние» панели запуска приложений. Если не указано, используется «контекстный текст» уведомления.

  • Touch Intent: PendingIntent используемый для обратного переключения в приложение, если пользователь нажимает на значок текущего действия. Отображается на циферблате или на панели запуска. Оно может отличаться от исходного намерения, использованного для запуска приложения. Если не указано, используется намерение содержимого уведомления. Если ни один из них не установлен, генерируется исключение.

  • LocusId : идентификатор, который назначает ярлык запуска, которому соответствует текущее действие. Отображается на панели запуска в разделе «Последние» , пока действие продолжается. Если этот параметр не указан, средство запуска скрывает все элементы приложения в разделе «Последние» из того же пакета и показывает только текущую активность.

  • Идентификатор текущей активности: идентификатор, используемый для устранения неоднозначности вызовов fromExistingOngoingActivity() , когда приложение имеет более одного текущего действия.

Обновить текущую деятельность

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

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

Чтобы обновить текущую активность и опубликованное уведомление, используйте созданный ранее объект и вызовите update() , как показано в следующем примере:

Котлин

ongoingActivity.update(context, newStatus)

Ява

ongoingActivity.update(context, newStatus);

Для удобства существует статический метод для создания постоянной активности.

Котлин

OngoingActivity.recoverOngoingActivity(context)
               .update(context, newStatus)

Ява

OngoingActivity.recoverOngoingActivity(context)
               .update(context, newStatus);

Остановить текущую деятельность

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

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

Приостановить текущее действие

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

Лучшие практики

При работе с API текущих действий помните следующее:

  • Вызовите ongoingActivity.apply(context) перед вызовом notificationManager.notify(...) .
  • Установите статический значок для вашей текущей активности либо явно , либо в качестве резервного варианта через уведомление . Если вы этого не сделаете, вы получите IllegalArgumentException .

  • Используйте черно-белые векторные иконки с прозрачным фоном.

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

  • Для NotificationCompat используйте базовую библиотеку AndroidX core:1.5.0-alpha05+ , которая включает LocusIdCompat и новые категории для тренировок, секундомера и совместного использования местоположения.

  • Если в манифесте вашего приложения объявлено более одного действия MAIN LAUNCHER , опубликуйте динамический ярлык и свяжите его с вашим текущим действием с помощью LocusId .

Публикация медиа-уведомлений при воспроизведении мультимедиа на устройствах Wear OS

Если мультимедийный контент воспроизводится на устройстве Wear OS, опубликуйте мультимедийное уведомление . Это позволяет системе создавать соответствующую текущую деятельность.

Если вы используете Media3, уведомление публикуется автоматически. Если вы создаете уведомление вручную, оно должно использовать MediaStyleNotificationHelper.MediaStyle , а активность сеанса соответствующего MediaSession должна быть заполнена.

{% дословно %} {% дословно %} {% дословно %} {% дословно %}