Устройства на базе Wear OS часто используются для длительных тренировок, например, для отслеживания тренировок. Это создаёт определённую проблему: если пользователь запускает какое-либо приложение, а затем переходит на циферблат, как вернуться обратно? Возврат к приложению с помощью лаунчера может быть затруднён, особенно на ходу, что создаёт ненужное напряжение.
Решение заключается в сопряжении текущего уведомления с OngoingActivity
. Это позволяет устройству отображать информацию о длительном действии в пользовательском интерфейсе, активируя такие функции, как нажимаемый значок в нижней части циферблата. Это информирует пользователей о фоновой задаче и позволяет вернуться в приложение одним касанием.
Например, в этом приложении для тренировок информация может отображаться на циферблате часов пользователя в виде нажимаемого значка бега:
Рисунок 1. Индикатор активности.
Текущее уведомление также отображает информацию в разделе «Недавние» глобального лончера приложений. Это ещё один удобный способ для пользователей увидеть статус своей задачи и вернуться к работе с приложением:
Рисунок 2. Глобальная пусковая установка.
Ниже приведены подходящие ситуации для использования постоянного уведомления, привязанного к текущей активности:
Рисунок 3. Таймер: активно отсчитывает время и останавливается, когда таймер останавливается или приостанавливается.
Рисунок 4. Пошаговая навигация: объявляет маршрут до пункта назначения. Завершается, когда пользователь достигает пункта назначения или останавливает навигацию.
Рисунок 5. Медиа: Воспроизведение музыки в течение всего сеанса. Завершается сразу после того, как пользователь ставит сеанс на паузу.
Wear автоматически создает текущие действия для медиаприложений.
Подробный пример создания текущих действий для других типов приложений см. в практической работе по созданию текущих действий.
Настраивать
Чтобы начать использовать API текущей активности в своем приложении, добавьте следующие зависимости в файл build.gradle
вашего приложения:
dependencies {
implementation "androidx.wear:wear-ongoing:1.1.0"
implementation "androidx.core:core:1.17.0"
}
Создайте текущую деятельность
Процесс включает три этапа:
- Создайте стандартный
NotificationCompat.Builder
и настройте его как непрерывный. - Создайте и настройте объект
OngoingActivity
, передав ему конструктор уведомлений. - Примените текущую активность к конструктору уведомлений и опубликуйте полученное уведомление.
Создать и настроить уведомление
Начнем с создания NotificationCompat.Builder
. Ключевым шагом является вызов setOngoing(true)
, чтобы отметить уведомление как текущее. На этом этапе также можно задать другие свойства уведомления, например, небольшой значок и категорию.
// Create a PendingIntent to pass to the notification builder val pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, AlwaysOnActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Always On Service") .setContentText("Service is running in background") .setSmallIcon(R.drawable.animated_walk) // Category helps the system prioritize the ongoing activity .setCategory(NotificationCompat.CATEGORY_WORKOUT) .setContentIntent(pendingIntent) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setOngoing(true) // Important!
Создайте текущую деятельность
Затем создайте экземпляр OngoingActivity
с помощью его конструктора. OngoingActivity.Builder
требуются Context
, идентификатор уведомления и NotificationCompat.Builder
, созданный на предыдущем шаге.
Настройте ключевые свойства, которые будут отображаться на новых поверхностях пользовательского интерфейса:
- Анимированные и статические значки : предоставляют значки, которые отображаются на циферблате часов в активном и фоновом режимах.
- Touch Intent :
PendingIntent
, который возвращает пользователя в ваше приложение при нажатии на значок текущего действия. Вы можете повторно использоватьpendingIndent
, созданный на предыдущем шаге.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // Sets the icon that appears on the watch face in active mode. .setAnimatedIcon(R.drawable.animated_walk) // Sets the icon that appears on the watch face in ambient mode. .setStaticIcon(R.drawable.ic_walk) // Sets the tap target to bring the user back to the app. .setTouchIntent(pendingIntent) .build()
Подать заявку на уведомление и разместить
Последний шаг — связать OngoingActivity
с уведомлением и опубликовать его. Метод ongoingActivity.apply()
изменяет исходный конструктор уведомлений, добавляя необходимые данные для отображения уведомления на дополнительных поверхностях. После применения метода вы можете создать и опубликовать уведомление как обычно.
// This call modifies notificationBuilder to include the ongoing activity data. ongoingActivity.apply(applicationContext) // Post the notification. startForeground(NOTIFICATION_ID, notificationBuilder.build())
Добавить динамический текст статуса в лаунчер
Приведённый выше код добавляет на циферблат значок, который можно нажать. Чтобы обеспечить ещё более содержательные обновления в режиме реального времени в разделе «Недавние» лаунчера, создайте объект Status
и прикрепите его к OngoingActivity
. Если вы не укажете собственный Status
, система по умолчанию будет использовать текст уведомления (заданный с помощью setContentText()
).
Для отображения динамического текста используйте Status.Builder
. Вы можете определить строку шаблона с плейсхолдерами и предоставить объекты Status.Part
для их заполнения. Status.Part
может быть динамическим, например, секундомером или таймером.
В следующем примере показано, как создать статус, отображающий «Выполнить [таймер секундомера]»:
// Define a template with placeholders for the activity type and the timer. val statusTemplate = "#type# for #time#" // Set the start time for a stopwatch. // Use SystemClock.elapsedRealtime() for time-based parts. val runStartTime = SystemClock.elapsedRealtime() val ongoingActivityStatus = Status.Builder() // Sets the template string. .addTemplate(statusTemplate) // Fills the #type# placeholder with a static text part. .addPart("type", Status.TextPart("Run")) // Fills the #time# placeholder with a stopwatch part. .addPart("time", Status.StopwatchPart(runStartTime)) .build()
Наконец, свяжите этот Status
с вашей OngoingActivity
, вызвав setStatus()
в OngoingActivity.Builder
.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // ... // Add the status to the OngoingActivity. .setStatus(ongoingActivityStatus) .build()
Дополнительные настройки
Помимо Status
, вы можете настроить текущую активность или уведомления следующими способами. Однако эти настройки могут быть недоступны в зависимости от реализации OEM-производителя.
Текущее уведомление
- Установленная категория определяет приоритет текущей деятельности.
-
CATEGORY_CALL
: входящий голосовой или видеовызов или аналогичный запрос синхронной связи -
CATEGORY_NAVIGATION
: карта или пошаговая навигация -
CATEGORY_TRANSPORT
: управление транспортировкой медиаданных для воспроизведения -
CATEGORY_ALARM
: будильник или таймер -
CATEGORY_WORKOUT
: тренировка -
CATEGORY_LOCATION_SHARING
: временная категория совместного использования местоположения) -
CATEGORY_STOPWATCH
: секундомер
-
Текущая деятельность
Анимированный значок: чёрно-белый векторный рисунок, желательно на прозрачном фоне. Отображается на циферблате в активном режиме. Если анимированный значок отсутствует, используется значок уведомления по умолчанию. Значок уведомления по умолчанию отличается для каждого приложения.
Статичный значок: векторный значок с прозрачным фоном. Отображается на циферблате в режиме Ambient. Если анимированный значок не задан, в активном режиме на циферблате используется статический значок. Если он не задан, используется значок уведомления. Если ни один из них не задан, возникает исключение. (Панель запуска приложений по-прежнему использует значок приложения.)
OngoingActivityStatus: простой текст или
Chronometer
. Отображается в разделе « Недавние » панели запуска приложений. Если не указано, используется «контекстный текст» уведомления.Touch Intent:
PendingIntent
используемый для возврата в приложение при нажатии пользователем на значок текущего действия. Отображается на циферблате или на панели запуска. Может отличаться от исходного Intent, использованного для запуска приложения. Если не указано, используется Intent содержимого уведомления. Если ни одно из них не задано, генерируется исключение.LocusId
: идентификатор, назначающий ярлыку панели запуска, соответствующему текущему действию. Отображается в разделе «Недавние» панели запуска, пока выполняется действие. Если не указан, панель запуска скрывает все элементы приложений в разделе « Недавние» из того же пакета и отображает только текущее действие.Идентификатор текущей активности: идентификатор, используемый для устранения неоднозначности вызовов
fromExistingOngoingActivity()
, когда приложение имеет более одной текущей активности.
Обновить текущую активность
В большинстве случаев разработчики создают новые текущие уведомления и новые текущие активности, когда им нужно обновить данные на экране. Однако API текущих активностей также предлагает вспомогательные методы для обновления OngoingActivity
, если вы хотите сохранить экземпляр, а не создавать его заново.
Если приложение работает в фоновом режиме, оно может отправлять обновления в API текущей активности. Однако не делайте этого слишком часто, поскольку метод обновления игнорирует слишком частые вызовы. Несколько обновлений в минуту — разумное количество.
Чтобы обновить текущую активность и отправленное уведомление, используйте созданный ранее объект и вызовите update()
, как показано в следующем примере:
ongoingActivity.update(context, newStatus)
Для удобства существует статический метод создания текущей активности.
OngoingActivity.recoverOngoingActivity(context)
.update(context, newStatus)
Остановить текущую деятельность
Когда приложение завершит работу в качестве текущей активности, достаточно отменить только текущее уведомление.
Вы также можете отменить уведомление или текущую активность, когда они появляются на переднем плане, а затем заново создать их при возвращении в фоновый режим, но это не обязательно.
Приостановить текущую деятельность
Если в вашем приложении есть явное действие остановки, продолжайте текущую активность после возобновления работы. Если в приложении нет явной команды остановки, завершайте активность после её приостановки.
Лучшие практики
При работе с API текущей активности помните следующее:
Установите статический значок для текущей активности, либо явно , либо в качестве запасного варианта с помощью уведомления . В противном случае вы получите исключение
IllegalArgumentException
.Используйте черно-белые векторные иконки с прозрачным фоном.
Задайте намерение касания для текущего действия, либо явно , либо в качестве запасного варианта с помощью уведомления . Если вы этого не сделаете, возникнет исключение
IllegalArgumentException
.Если в манифесте вашего приложения объявлено более одного действия
MAIN LAUNCHER
, опубликуйте динамический ярлык и свяжите его с текущей активностью с помощьюLocusId
.
Публиковать уведомления о медиафайлах при воспроизведении медиафайлов на устройствах Wear OS
Если на устройстве Wear OS воспроизводится медиаконтент, опубликуйте уведомление о медиа . Это позволит системе создать соответствующее текущее действие.
При использовании Media3 уведомление публикуется автоматически. Если вы создаёте уведомление вручную, оно должно использовать MediaStyleNotificationHelper.MediaStyle
, а соответствующий сеанс MediaSession
должен быть заполнен.
Рекомендовано для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Создать уведомление {:#notification}
- Взаимодействуйте с пользователями Wear OS по-новому с помощью API текущей активности
- Создать расширяемое уведомление {:#expandable-notification}