В этом руководстве объясняется, как сделать так, чтобы ваше приложение работало постоянно, как реагировать на изменения состояния питания и как управлять поведением приложения, чтобы обеспечить удобство использования и при этом экономить заряд батареи .
Постоянное отображение приложения существенно влияет на время работы батареи, поэтому при добавлении этой функции учитывайте влияние на энергопотребление.
Ключевые концепции
Когда приложение Wear OS отображается на весь экран, оно находится в одном из двух состояний питания:
- Интерактивный : режим высокой мощности, при котором экран имеет полную яркость, что обеспечивает полное взаимодействие с пользователем.
- Ambient : Состояние низкого энергопотребления, когда дисплей затемняется для экономии энергии. В этом состоянии пользовательский интерфейс вашего приложения по-прежнему занимает весь экран, но система может изменить его внешний вид, размыв его или наложив поверх него контент, например время. Это также называется Ambient Mode .
Переходом между этими состояниями управляет операционная система.
Always-On App — это приложение, которое отображает контент как в интерактивном , так и в фоновом режиме.
Когда постоянно активное приложение продолжает отображать свой собственный пользовательский интерфейс, пока устройство находится в режиме пониженного энергопотребления Ambient , оно описывается как находящееся в режиме ambiactive .
Системные переходы и поведение по умолчанию
Когда приложение находится на переднем плане, система управляет переходами состояний питания на основе двух тайм-аутов, вызванных бездействием пользователя.
- Тайм-аут №1: Переход из интерактивного состояния в состояние «Окружающий мир». После определенного периода бездействия пользователя устройство переходит в состояние «Окружающий мир» .
- Тайм-аут №2: Возврат к циферблату: После дальнейшего периода бездействия система может скрыть текущее приложение и отобразить циферблат.
Сразу после того, как система пройдет первый переход в состояние Ambient , поведение по умолчанию зависит от версии Wear OS и конфигурации вашего приложения:
- В Wear OS 5 и более ранних версиях система отображает размытый снимок экрана приостановленного приложения с наложенным поверх него временем.
- На Wear OS 6 и выше , если приложение ориентировано на SDK 36 или более новую версию, оно считается постоянно включенным. Дисплей затемняется, но приложение продолжает работать и остается видимым. (Обновления могут быть нечастыми, например раз в минуту.)
Настройте поведение для состояния Ambient
Независимо от поведения системы по умолчанию, во всех версиях Wear OS вы можете настроить внешний вид или поведение своего приложения в состоянии Ambient , используя AmbientLifecycleObserver
для прослушивания обратных вызовов при переходах между состояниями.
Использовать AmbientLifecycleObserver
Чтобы реагировать на события режима окружения, используйте класс AmbientLifecycleObserver
:
Реализуйте интерфейс
AmbientLifecycleObserver.AmbientLifecycleCallback
. Используйте методonEnterAmbient()
для настройки пользовательского интерфейса для состояния низкого энергопотребления иonExitAmbient()
для восстановления полного интерактивного отображения.val ambientCallback = object : AmbientLifecycleObserver.AmbientLifecycleCallback { override fun onEnterAmbient(ambientDetails: AmbientLifecycleObserver.AmbientDetails) { // ... Called when moving from interactive mode into ambient mode. // Adjust UI for low-power state: dim colors, hide non-essential elements. } override fun onExitAmbient() { // ... Called when leaving ambient mode, back into interactive mode. // Restore full UI. } override fun onUpdateAmbient() { // ... Called by the system periodically (typically once per minute) // to allow the app to update its display while in ambient mode. } }
Создайте
AmbientLifecycleObserver
и зарегистрируйте его в жизненном цикле вашей активности или компонуемого объекта.private val ambientObserver = AmbientLifecycleObserver(activity, ambientCallback) override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) lifecycle.addObserver(ambientObserver) // ... }
Вызовите
removeObserver()
, чтобы удалить наблюдателя вonDestroy()
.
Для разработчиков, использующих Jetpack Compose, библиотека Horologist предоставляет полезную утилиту AmbientAware
composable, которая упрощает реализацию этого шаблона.
TimeText с учетом окружающей среды
В качестве исключения из требования к пользовательскому наблюдателю, на Wear OS 6 виджет TimeText
учитывает окружение. Он автоматически обновляется раз в минуту, когда устройство находится в состоянии Ambient , без какого-либо дополнительного кода.
Управление длительностью включения экрана
В следующих разделах описывается, как управлять временем отображения приложения на экране.
Запретить возврат к циферблату с текущей активностью
После определенного периода времени в состоянии Ambient (Timeout #2) система обычно возвращается к циферблату. Пользователь может настроить длительность тайм-аута в настройках системы. Для определенных случаев использования, например, когда пользователь отслеживает тренировку, приложению может потребоваться оставаться видимым дольше.
На Wear OS 5 и выше вы можете предотвратить это, внедрив Ongoing Activity . Если ваше приложение отображает информацию о текущей задаче пользователя, например, о сеансе тренировки, вы можете использовать API Ongoing Activity , чтобы ваше приложение оставалось видимым до тех пор, пока задача не завершится. Если пользователь вручную возвращается к циферблату, индикатор текущей активности предоставляет ему возможность одним нажатием вернуться в ваше приложение
Чтобы реализовать это, сенсорное намерение текущего уведомления должно указывать на вашу постоянно активную активность, как показано в следующем фрагменте кода:
private fun createNotification(): Notification { val activityIntent = Intent(this, AlwaysOnActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP } val pendingIntent = PendingIntent.getActivity( this, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) // ... // ... .setOngoing(true) // ... val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // ... // ... .setTouchIntent(pendingIntent) .build() ongoingActivity.apply(applicationContext) return notificationBuilder.build() }
Оставьте экран включенным и предотвратите состояние Ambient
В редких случаях вам может потребоваться полностью запретить устройству переходить в состояние Ambient . То есть, чтобы избежать Timeout #1. Для этого вы можете использовать флаг окна FLAG_KEEP_SCREEN_ON
. Он работает как блокировка пробуждения, удерживая устройство в интерактивном состоянии. Используйте его с особой осторожностью, так как он сильно влияет на срок службы батареи.
Рекомендации для режима Ambient
Чтобы обеспечить наилучшие условия для пользователя и экономить электроэнергию в режиме Ambient , следуйте этим рекомендациям по проектированию.
- Используйте минималистичный дисплей с низким энергопотреблением
- Оставьте не менее 85% экрана черным.
- Для крупных значков и кнопок используйте контуры, а не сплошную заливку.
- Показывайте только самую важную информацию, перенося второстепенные детали на интерактивный дисплей.
- Избегайте использования больших блоков сплошного цвета, а также нефункциональных фирменных знаков или фоновых изображений.
- Обеспечьте своевременное обновление контента
- Для часто меняющихся данных, таких как секундомер, пройденное расстояние или время тренировки, отображайте замещающий контент, например
--
, чтобы не создавалось впечатления, что контент новый. - Удалите индикаторы прогресса, которые постоянно обновляются, например, для колец обратного отсчета и медиа-сеансов.
- Обратный вызов
onUpdateAmbient()
следует использовать только для важных обновлений, обычно один раз в минуту.
- Для часто меняющихся данных, таких как секундомер, пройденное расстояние или время тренировки, отображайте замещающий контент, например
- Поддерживайте единообразную компоновку
- Сохраняйте элементы в одинаковом положении в интерактивном и фоновом режимах, чтобы обеспечить плавный переход.
- Всегда показывайте время.
- Будьте внимательны к контексту
- Если пользователь находился на экране настроек или конфигурации, когда устройство перешло в режим Ambient Mode, рассмотрите возможность отображения более подходящего экрана из вашего приложения вместо представления настроек.
- Обработка требований, специфичных для устройств
- В объекте
AmbientDetails
, переданном вonEnterAmbient()
:- Если
deviceHasLowBitAmbient
имеетtrue
, отключите сглаживание, где это возможно. - Если
burnInProtectionRequired
имеет значениеtrue
, периодически слегка сдвигайте элементы пользовательского интерфейса и избегайте сплошных белых областей, чтобы предотвратить выгорание экрана.
- Если
- В объекте
Отладка и тестирование
Эти команды adb
могут быть полезны при разработке или тестировании поведения вашего приложения, когда устройство находится в режиме Ambient Mode:
# put device in ambient mode if the always on display is enabled in settings
# (and not disabled by other settings, such as theatre mode)
$ adb shell input keyevent KEYCODE_SLEEP
# put device in interactive mode
$ adb shell input keyevent KEYCODE_WAKEUP
Пример: приложение для тренировок
Рассмотрим приложение для тренировок, которое должно отображать метрики для пользователя на протяжении всей его тренировки. Приложение должно оставаться видимым при переходах состояния Ambient и не должно заменяться циферблатом.
Для этого разработчику необходимо сделать следующее:
- Реализуйте
AmbientLifecycleObserver
для обработки изменений пользовательского интерфейса между интерактивным и окружающим состояниями, таких как затемнение экрана и удаление ненужных данных. - Создайте новый маломощный макет для состояния Ambient , соответствующий лучшим практикам.
- Используйте API текущей активности во время тренировки, чтобы предотвратить возврат системы к циферблату.
Для полной реализации см. пример Compose-based Exercise на GitHub. Этот пример также демонстрирует использование компонуемого AmbientAware
из библиотеки Horologist для упрощения обработки режима окружения в Compose.