В 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()
. Это обеспечивает определенную развязку в обмене состояниями жизненного цикла и состоянием верхнего возобновления между серверной и клиентской сторонами.