Постоянно включенные приложения и режим окружающей среды системы

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

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

Ключевые понятия

Когда приложение Wear OS отображается на весь экран, оно находится в одном из двух энергосберегающих состояний:

  • Интерактивный режим : состояние высокой мощности, при котором экран имеет максимальную яркость, что позволяет пользователю взаимодействовать с экраном в полном объеме.
  • Ambient : Режим пониженного энергопотребления, при котором дисплей затемняется для экономии энергии. В этом режиме пользовательский интерфейс приложения по-прежнему занимает весь экран, но система может изменять его внешний вид, размывая его или отображая наложенный контент, например, время. Этот режим также называется режимом Ambient .

Переход между этими состояниями контролируется операционной системой.

Приложение с постоянной активацией (Always-On App) — это приложение, которое отображает контент как в интерактивном , так и в фоновом режимах.

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

Переходы в системе и поведение по умолчанию

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

  • Тайм-аут №1: Переход из интерактивного состояния в фоновое: После периода бездействия пользователя устройство переходит в фоновое состояние.
  • Тайм-аут №2: Возврат к циферблату: После очередного периода бездействия система может скрыть текущее приложение и отобразить циферблат.

Сразу после первого перехода системы в состояние Ambient , поведение по умолчанию зависит от версии Wear OS и конфигурации вашего приложения:

  • В Wear OS 5 и более ранних версиях система отображает размытый снимок экрана приостановленного приложения с наложенным поверх него временем. Это состояние представлено узлом «AOD Lite» на следующей блок-схеме .
  • В Wear OS 6 и более поздних версиях , если приложение использует SDK 36 или более новую версию, оно считается постоянно включенным. Дисплей приглушается, но приложение продолжает работать и остается видимым. (Обновления могут происходить даже раз в минуту.) Это состояние представлено узлом «Global AOD» на следующей блок-схеме .

Настройка поведения для состояния окружающей среды

Независимо от поведения системы по умолчанию, во всех версиях Wear OS вы можете настроить внешний вид или поведение вашего приложения в режиме Ambient , используя LocalAmbientModeManager для отслеживания переходов состояний в Jetpack Compose на Wear OS. Это состояние представлено узлом "Ambiactive Mode" на следующей блок-схеме .

Наблюдайте за состоянием окружающей среды.

Для реагирования на события режима окружающего освещения в Jetpack Compose на Wear OS:

  1. Используйте LocalAmbientModeManager для отслеживания изменений состояния окружающего режима системы и соответствующей настройки ваших компонентов. Настройте свой компонент так, чтобы он переключался в режим с пониженным энергопотреблением в состоянии AmbientMode.Ambient и восстанавливал полнофункциональный интерактивный режим отображения в состоянии AmbientMode.Interactive .

    // In a production application, the AmbientModeManager should be instantiated and provided at
    // the highest level of the Compose hierarchy (typically in the host Activity's setContent
    // block) using a CompositionLocalProvider. This ensures proper lifecycle management and
    // broad accessibility.
    
    // For this self-contained demo, AmbientModeManager is created and provided locally:
    val activityAmbientModeManager = rememberAmbientModeManager()
    CompositionLocalProvider(LocalAmbientModeManager provides activityAmbientModeManager) {
        val ambientModeManager = LocalAmbientModeManager.current
        val ambientMode = ambientModeManager?.currentAmbientMode
    
        if (ambientModeManager != null) {
            ambientModeManager.AmbientTickEffect {
                // While device is in ambient mode, update properties every minute or so
                // ...
            }
        }
    
        // ...
            val ambientModeName =
                when (ambientMode) {
                    is AmbientMode.Interactive -> "Interactive"
                    is AmbientMode.Ambient -> "Ambient"
                    else -> "Unknown"
                }
    
            Text(text = "$ambientModeName Mode")
            // ...
    }

Блок-схема поведения окружающей среды

Следующая блок-схема иллюстрирует, как система определяет поведение в окружающей среде на основе версии Wear OS устройства, targetSdkVersion вашего приложения и того, отслеживает ли она переходы состояний окружающей среды (с помощью LocalAmbientModeManager или AmbientLifecycleCallback ).

Блок-схема, иллюстрирующая логику принятия решений для режима Ambient Mode в Wear OS. Она показывает, как версия ОС устройства и конфигурация приложения определяют один из трех результатов: размытое наложение, глобальный AOD или управляемый приложением режим Ambiactive Mode.
Рисунок 1. Блок-схема, иллюстрирующая логику принятия решений для режима работы Wear OS в фоновом режиме.

Управление длительностью включения экрана

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

Предотвратите возвращение к циферблату с помощью текущей активности или обновления в реальном времени.

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

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

В качестве альтернативы, на Wear OS 7 и более поздних версиях вы можете использовать Live Update вместо Ongoing Activity. Для обеспечения обратной совместимости продолжайте поддерживать Ongoing Activity на устройствах под управлением Wear OS 6 или более ранних версий.

Для реализации этого, намерение касания текущего уведомления должно указывать на вашу постоянно активную активность, как показано в следующем фрагменте кода:

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)

val notification = notificationBuilder.build()

Оставьте экран включенным и предотвратите появление состояния Ambient State.

В редких случаях может потребоваться полностью предотвратить переход устройства в состояние Ambient . То есть, чтобы избежать таймаута №1. Для этого можно использовать модификатор keepScreenOn . Он работает как блокировка пробуждения, удерживая устройство в интерактивном состоянии. Используйте его с особой осторожностью, так как он серьезно влияет на время работы от батареи.

Рекомендации по использованию режима Ambient

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

  • Уменьшите визуальный беспорядок и сэкономьте энергию дисплея. Чистый, минималистичный пользовательский интерфейс сигнализирует пользователю о том, что приложение находится в режиме низкого энергопотребления, и значительно экономит заряд батареи за счет ограничения количества ярких пикселей.
    • Не менее 85% экрана должно быть черным (коэффициент загрузки пикселей должен составлять 15% или меньше).
    • Отображайте только самую важную информацию, вынося второстепенные детали на интерактивный экран.
    • Для крупных значков или кнопок используйте контуры вместо сплошной заливки, регулируя контрастность контуров таким образом, чтобы элементы оставались читаемыми без риска мерцания или выгорания экрана.
    • Избегайте больших блоков сплошного цвета, а также нефункциональной фирменной символики или фоновых изображений.
  • Обработка устаревших динамических данных и анимаций.
    • Функция обратного вызова AmbientTickEffect вызывается лишь периодически — обычно раз в минуту — для экономии энергии. Из-за этого ограничения любые часто изменяющиеся данные, такие как показания секундомера, частота сердечных сокращений или пройденное расстояние во время тренировки, устаревают между обновлениями. Чтобы избежать отображения вводящей в заблуждение и некорректной информации, замените эти текущие значения статическим содержимым-заполнителем, например -- .
    • Удалите индикаторы выполнения, требующие частых обновлений для обеспечения полезности в текущем контексте или ситуации пользователя, например, кольца прогресса для коротких медиасессий. Вы можете сохранить индикаторы выполнения, для которых обновления раз в минуту по-прежнему имеют ценность, например, для длительных таймеров.
    • В фоновом режиме можно приостановить или отключить все анимации, включая анимированные индикаторы выполнения и бегущую строку.
  • Поддерживайте единообразную планировку.
    • Для обеспечения плавного перехода сохраняйте элементы в одном и том же положении как в интерактивном , так и в фоновом режимах. Интерактивные элементы пользовательского интерфейса, такие как кнопки, могут оставаться видимыми, поскольку современные устройства Wear OS поддерживают сенсорный ввод во время фоновых сеансов.
    • Всегда отображайте текущее время. В Jetpack Compose для Wear OS TimeText (включенный по умолчанию в ScreenScaffold ) учитывает окружающее пространство и автоматически обновляется раз в минуту в режиме окружающего освещения.
  • Учитывайте контекст.
    • Если пользователь находился на экране настроек или конфигурации, когда устройство перешло в режим ожидания, рассмотрите возможность показа более релевантного экрана из вашего приложения вместо окна настроек.
  • Обработка требований, специфичных для конкретного устройства.
    • Когда currentAmbientMode возвращает AmbientMode.Ambient :
      • Если isLowBitAmbientSupported имеет true , дисплей поддерживает меньшее количество бит на цвет в режиме окружающего освещения. Отключите сглаживание (например, в пользовательских операциях рисования Canvas или Paint ) и по возможности избегайте цветовых градиентов.
      • Если isBurnInProtectionRequired имеет значение true , система периодически сдвигает содержимое дисплея, чтобы предотвратить выгорание пикселей. Не сдвигайте элементы пользовательского интерфейса вручную в вашем приложении. Вместо этого избегайте сплошных белых областей и размещайте критически важные элементы пользовательского интерфейса на расстоянии не менее 10 пикселей от края экрана, чтобы они не обрезались при сдвиге дисплея системой. (Стандартные макеты Wear Compose, такие как ScreenScaffold уже обеспечивают достаточный отступ по краям.)

Отладка и тестирование

Эти команды adb могут быть полезны при разработке или тестировании поведения вашего приложения в режиме ожидания устройства:

# 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 State и не заменяться циферблатом часов.

Для достижения этой цели разработчику следует выполнить следующие действия:

  1. Используйте LocalAmbientModeManager для управления изменениями пользовательского интерфейса между интерактивным и окружающим состояниями, например, для затемнения экрана и удаления несущественных данных.
  2. Создайте новый, энергоэффективный макет для состояния Ambient , соответствующий передовым практикам.
  3. Используйте API текущей активности (или обновления в реальном времени в Wear OS 7 и выше) на протяжении всей тренировки, чтобы предотвратить возврат системы к циферблату часов.

Полную реализацию см. в примере упражнения на основе Compose на GitHub. Этот пример также демонстрирует использование объекта LocalAmbientModeManager для упрощения обработки режимов окружающего освещения в Compose.