Мультирезюме

В Android 9 (и более ранних версиях) приложения переводились в состояние PAUSED когда:

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

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

В Android 10 все основные действия в видимых стеках находятся в состоянии RESUMED . Это улучшает совместимость с режимами Multi-Window и MD для приложений, которые используют onPause() вместо onStop() , чтобы прекратить обновление пользовательского интерфейса и взаимодействие с пользователем. Это означает:

  • Оба действия в разделенном экране возобновляются.
  • Возобновляются все самые видимые действия в свободном оконном режиме.
  • Действия на нескольких экранах могут быть возобновлены одновременно.

Рисунок 1. Мультирезюме на складном устройстве

Рисунок 2. Мультирезюме в режиме рабочего стола

Действия могут находиться в состоянии PAUSED когда на них нельзя сфокусироваться или они частично закрыты, например:

  • В свернутом разделенном экране (с панелью запуска сбоку) верхняя активность не возобновляется, потому что на нее нельзя сфокусироваться.
  • В режиме «картинка в картинке» действие не возобновляется, потому что на него нельзя сфокусироваться.
  • Когда действия покрываются другими прозрачными действиями в том же стеке.

Этот подход указывает приложениям, что действие может получать ввод от пользователя только в состоянии RESUMED . До Android 10 действия также могли получать входные данные в состоянии PAUSED (например, попробуйте одновременно коснуться обоих действий в режиме разделенного экрана на устройстве под управлением Android 9).

Чтобы сохранить возобновленный сигнал из предыдущих выпусков Android (и сообщить, когда приложения должны получить доступ к монопольным или одноэлементным ресурсам), Android 10 включает новый обратный вызов:

Activity#onTopResumedActivityChanged(boolean onTop)

При вызове этот обратный вызов вызывается между Activity#onResume() и Activity#onPause() . Этот обратный вызов является необязательным и может быть пропущен, поэтому действие может перейти из состояния RESUMED в состояние PAUSED , не становясь самым верхним в системе. Например, в многооконном режиме. Поскольку этот обратный вызов является необязательным, он не является частью жизненного цикла действия и должен использоваться редко.

Предыдущее действие с возобновлением наверху получает и завершает выполнение onTopResumedActivity(false) до того, как следующее действие с возобновлением наверху получит onTopResumedActivity(true) , если предыдущее действие не занимает слишком много времени для обработки вызова метода и не достигает тайм-аута 500 мс.

Совместимость

Чтобы обеспечить совместимость при реализации нескольких резюме, рассмотрите эти решения.

Несколько возобновленных действий в одном процессе приложения

  • Проблема. В Android 9 и ниже одновременно возобновляется только одно действие в системе. Все переходы между действиями предполагают приостановку действия перед возобновлением другого. Некоторые приложения и фреймворки (такие как Flutter или Android LocalActivityManager) используют этот факт и сохраняют состояние возобновленной активности в синглтонах.
  • Решение. В Android 9 и более ранних версиях, если возобновляются два действия из одного и того же процесса, система возобновляет только действие с более высоким Z-порядком. Приложения, ориентированные на Android 10, могут поддерживать одновременное возобновление нескольких действий.

Одновременный доступ к камере

  • Проблемы . Эти проблемы также присутствуют в Android 9 и более ранних версиях. Например, полноэкранное и возобновленное действие может переключить фокус камеры на приостановленное действие вверху в режиме «картинка в картинке», но стать более заметным при более широком внедрении многооконного и многоэкранного режимов.
    • Из-за изменений, внесенных в состояние RESUME , приложения могут быть отключены от камеры даже во время возобновления работы. Чтобы решить эту проблему, приложения должны обрабатывать отключение камеры без сбоев. При отключении приложения получают обратный вызов отключения, и все вызовы в API начинают CameraAccessException .
    • resizeableActivity=false не является гарантией эксклюзивного доступа к камере, поскольку другие приложения, использующие камеру, могут быть открыты на других дисплеях.
  • Решения. Разработчики должны включить логику, когда приложение отключается от камеры. Если приложение отключено от камеры, оно должно отслеживать обратные вызовы доступности камеры, чтобы попытаться повторно подключиться и продолжить использование камеры. В дополнение к существующему CameraManager#AvailabilityCallback#onCameraAvailable() в Android 10 добавлен CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged() , который охватывает случай, когда фокус (и приоритет камеры) переключается между несколькими возобновленными действиями. Разработчики приложений должны использовать оба этих обратных вызова, чтобы определить подходящее время для попытки получить доступ к камере.

Мульти-резюме

В Android 10 состояние жизненного цикла активности определяется видимостью и Z-порядком. Чтобы убедиться, что правильное состояние после обновления видимости для действия и оценить, какое состояние жизненного цикла применимо, вызовите метод ActivityRecord#makeActiveIfNeeded() из разных мест. В Android 10 активный означает RESUMED или PAUSED и работает только в этих двух случаях.

В Android 10 возобновление действия отслеживается отдельно в каждом стеке, а не в одном месте в системе. Это связано с тем, что несколько переходов активности могут выполняться одновременно в многооконных режимах. Дополнительные сведения см. в разделе ActivityStack#mInResumeTopActivity .

Обратный вызов по возобновленной активности

После действий, которые могут привести к изменению основного действия (например, запуск, возобновление действия или изменение Z-порядка), ActivityStackSupervisor#updateTopResumedActivityIfNeeded() . Этот метод проверяет, изменилась ли самая верхняя возобновленная активность, и при необходимости выполняет обновление. Если предыдущее действие с возобновлением наибольшей активности не освободило состояние возобновления наибольшей активности, то ему отправляется сообщение о потере состояния наибольшей возобновленной активности, а на стороне сервера планируется тайм-аут ( ActivityStackSupervisor#scheduleTopResumedStateLossTimeout() ). Отчет о состоянии верхнего возобновления отправляется следующему действию после того, как предыдущее освободило состояние или когда истекло время ожидания (см. Использование:

ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()

Был добавлен новый элемент транзакции TopResumedActivityChangeItem , чтобы сообщать клиентам об изменениях состояния, возобновленных в верхней части, и использует архитектуру ActivityLifecycler из Android 9.

Верхнее возобновленное состояние сохраняется на стороне клиента, и каждый раз, когда действие переходит в RESUMED или PAUSED , оно также проверяет, следует ли вызывать обратный вызов onTopResumedActivityChanged() . Это обеспечивает определенную развязку в обмене состояниями жизненного цикла и состоянием верхнего возобновления между серверной и клиентской сторонами.