Изменения в поведении: все приложения

В Android 12 есть изменения, которые могут повлиять на работу вашего приложения. Они касаются всех приложений, запущенных на устройствах с Android 12, независимо от значения targetSdkVersion. Протестируйте приложение и при необходимости измените его, чтобы обеспечить поддержку этих функций.

Также ознакомьтесь со списком изменений в поведении, которые затрагивают только приложения, предназначенные для Android 12.

Удобство использования

Эффект растяжения при достижении конца прокрутки

На устройствах с Android 12 и более поздними версиями ОС меняется визуальное поведение событий прокрутки за пределы экрана.

В Android 11 и более ранних версиях при эффекте достижения конца прокрутки визуальные элементы подсвечиваются. В Android 12 и более поздних версиях при событии перетаскивания они растягиваются и возвращаются в исходное положение, а при проведении по экрану – отскакивают и возвращаются в исходное положение.

Дополнительную информацию вы найдете в руководстве по анимации жестов прокрутки.

Заставки приложений

Если вы ранее реализовали собственную заставку в Android 11 или более ранней версии, вам нужно перенести приложение на API SplashScreen, чтобы оно правильно отображалось в Android 12 и более поздних версиях. Если вы не перенесете приложение, его запуск может работать некорректно.

Инструкции вы найдете в статье Как перенести существующую заставку в Android 12.

Кроме того, начиная с Android 12, система всегда применяет новую заставку по умолчанию при холодном и теплом запуске всех приложений. По умолчанию заставка создается на основе значка приложения и атрибута windowBackground темы (если он одноцветный).

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

Разрешение веб-намерений

Начиная с Android 12 (уровень API 31) стандартное веб-намерение разрешается в действие в вашем приложении, только если оно одобрено для определенного домена, содержащегося в этом веб-намерении. Если приложение не одобрено для домена, веб-намерение будет разрешено в браузере по умолчанию.

Для этого разработчики могут сделать следующее:

Если ваше приложение вызывает веб-намерения, рекомендуем добавить запрос или диалоговое окно, в котором пользователь сможет подтвердить действие.

Улучшения режима погружения для навигации жестами

В Android 12 существующие функции объединены, чтобы пользователям было проще выполнять команды навигации жестами в режиме комфортного просмотра. Кроме того, в Android 12 предусмотрена обратная совместимость для режима погружения с закреплением.

Display#getRealSize и getRealMetrics: прекращение поддержки и ограничения

Устройства Android доступны в различных форм-факторах, таких как большие экраны, планшеты и складные устройства. Чтобы контент отображался корректно на каждом устройстве, приложению необходимо определить размер экрана или дисплея. Со временем в Android появились разные API для получения этой информации. В Android 11 мы добавили API WindowMetrics и прекратили поддержку следующих методов:

В Android 12 мы по-прежнему рекомендуем использовать WindowMetrics и прекращаем поддержку следующих методов:

Чтобы смягчить последствия использования Display API для получения границ приложения, в Android 12 ограничиваются значения, возвращаемые API для приложений, размер которых нельзя изменить полностью. Это может повлиять на приложения, которые используют эту информацию с MediaProjection.

Приложения должны использовать API WindowMetrics, чтобы запрашивать границы своего окна, и Configuration.densityDpi, чтобы запрашивать текущую плотность.

Чтобы обеспечить совместимость с более ранними версиями Android, используйте библиотеку Jetpack WindowManager, которая включает класс WindowMetrics, поддерживающий Android 4.0 (уровень API 14) и более поздние версии.

Примеры использования WindowMetrics

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

Для работы с интерфейсом, в частности с WindowManager.getCurrentWindowMetrics() или WindowMetricsCalculator.computeCurrentWindowMetrics() из Jetpack, в действии должен использоваться WindowMetrics из контекста действия.

Если ваше приложение создает MediaProjection, границы должны быть правильно заданы, поскольку проекция захватывает раздел экрана, в котором запущено приложение-проектор.

Если размер приложения можно полностью изменить, контекст действия возвращает правильные границы, например:

Kotlin

val projectionMetrics: WindowMetrics = activityContext
      .getSystemService(WindowManager::class.java).maximumWindowMetrics

Java

WindowMetrics projectionMetrics = activityContext
      .getSystemService(WindowManager.class).getMaximumWindowMetrics();

Если размер приложения нельзя изменить полностью, оно должно отправить запрос из экземпляра WindowContext и получить WindowMetrics границ действия с помощью WindowManager.getMaximumWindowMetrics() или метода Jetpack WindowMetricsCalculator.computeMaximumWindowMetrics().

Kotlin

val windowContext = context.createWindowContext(mContext.display!!,
      WindowManager.LayoutParams.TYPE_APPLICATION, null)
val projectionMetrics = windowContext.getSystemService(WindowManager::class.java)
      .maximumWindowMetrics

Java

Context windowContext = context.createWindowContext(mContext.getDisplay(),
      WindowManager.LayoutParams.TYPE_APPLICATION, null);
WindowMetrics projectionMetrics = windowContext.getSystemService(WindowManager.class)
      .getMaximumWindowMetrics();

Все приложения в многооконном режиме

В Android 12 многооконный режим включен по умолчанию.

На больших экранах (sw >= 600 dp) платформа поддерживает все приложения в многооконном режиме независимо от их конфигурации. Если задано значение resizeableActivity="false", приложение при необходимости переходит в режим совместимости, чтобы подстроиться под размеры экрана.

На небольших экранах (sw < 600dp) система проверяет атрибуты minWidth и minHeight, чтобы определить, может ли действие выполняться в многооконном режиме. Если задано значение resizeableActivity="false", приложение не будет работать в многооконном режиме независимо от минимальной ширины и высоты.

Подробнее о поддержке многооконного режима…

Предварительный просмотр для камеры на больших экранах

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

В Android 12 приложения камеры, которые запрашивают определенную ориентацию экрана и не поддерживают изменение размера (resizeableActivity="false"), автоматически переходят в режим портретной съемки. Это обеспечивает правильную ориентацию и соотношение сторон при предпросмотре. На складных и других устройствах с аппаратно-зависимым уровнем камеры к ее выходному сигналу применяется дополнительный поворот, чтобы компенсировать ориентацию датчика камеры. Кроме того, выходной сигнал обрезается в соответствии с соотношением сторон предварительного просмотра камеры в приложении. Кадрирование и дополнительный поворот обеспечивают правильное отображение предпросмотра камеры независимо от ориентации устройства и того, сложено оно или разложено.

Задержка UX для уведомлений об активных службах

Чтобы сделать работу с кратковременными активными службами более удобной, на устройствах с Android 12 и более поздними версиями ОС показ уведомлений от таких служб может задерживаться на 10 секунд. Однако есть несколько исключений. Это изменение позволяет быстро выполняемым задачам завершиться до появления уведомлений.

Эффективность

Группа App Standby с ограниченным доступом

В Android 11 (уровень API 30) появилась группа с ограниченным доступом. Начиная с Android 12, эта группа активна по умолчанию. У ограниченной группы самый низкий приоритет и самые строгие ограничения. Ниже перечислены сегменты в порядке убывания приоритета.

  1. "Активно" – приложение используется в данный момент или использовалось недавно.
  2. Рабочий набор: приложение используется регулярно.
  3. Часто: приложение используется часто, но не каждый день.
  4. Редко. Приложение используется нечасто.
  5. Ограничено. Приложение потребляет много системных ресурсов или может вести себя нежелательным образом.

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

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

Как проверить, находится ли приложение в группе ограниченного доступа

Чтобы проверить, поместила ли система ваше приложение в группу с ограниченным доступом, вызовите метод getAppStandbyBucket(). Если метод возвращает значение STANDBY_BUCKET_RESTRICTED, то приложение находится в группе с ограниченным доступом.

Проверьте работу ограниченного сегмента

Чтобы проверить, как ведет себя приложение, когда система помещает его в группу с ограниченным доступом, вы можете вручную переместить его в эту группу. Для этого выполните в окне терминала следующую команду:

adb shell am set-standby-bucket PACKAGE_NAME restricted

Доступ к геолокации в активном режиме и режим энергосбережения

Начиная с Android 12, данные о местоположении в активном режиме (в том числе от активной службы) могут передаваться, даже если включен режим энергосбережения и выключен экран.

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

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

  1. Вызовите метод getLocationPowerSaverMode(), чтобы проверить, как работают функции геолокации, когда включен режим энергосбережения.
  2. Если возвращается значение LOCATION_MODE_FOREGROUND_ONLY, приложение продолжит получать данные о местоположении, когда оно активно или запущена активная служба, даже если включен режим энергосбережения и выключен экран.

Безопасность и конфиденциальность

Приблизительное местоположение

В диалоговом окне есть два набора параметров, один над другим.
Рисунок 1. Диалоговое окно системных разрешений, в котором пользователь может предоставить доступ к данным о приблизительном местоположении.

На устройствах с Android 12 и более поздними версиями пользователи могут разрешить приложению доступ только к приблизительному местоположению.

Если приложение запрашивает динамическое разрешение ACCESS_FINE_LOCATION, то также следует запросить разрешение ACCESS_COARSE_LOCATION на случай, если пользователь разрешит приложению доступ только к приблизительному местоположению. Оба разрешения должны быть включены в один динамический запрос.

В диалоговом окне системных разрешений пользователю предлагаются следующие варианты (см. рис. 1):

  • Точное. Приложение получит доступ к точным данным о местоположении.
  • Приблизительное местоположение. Приложение получит доступ только к приблизительным геоданным.

Переключатели микрофона и камеры

На поддерживаемых устройствах с Android 12 и более поздних версий пользователи могут разрешать и запрещать доступ к камере и микрофону для всех приложений с помощью одного переключателя. Пользователи могут включать и отключать эти функции в быстрых настройках (см. рисунок 1) или в разделе "Конфиденциальность" в настройках системы.

Узнайте больше об этих переключателях и о том, как проверить, соответствует ли ваше приложение рекомендациям по разрешениям CAMERA и RECORD_AUDIO.

Индикаторы микрофона и камеры

На устройствах с Android 12 или более поздней версией ОС, когда приложение использует микрофон или камеру, в строке состояния появляется значок.

Узнайте больше об этих индикаторах и о том, как проверить, что ваше приложение соответствует рекомендациям по разрешениям CAMERA и RECORD_AUDIO.

Параметры быстрых настроек называются &quot;Доступ к камере&quot; и &quot;Доступ к микрофону&quot;.
Рисунок 2. Переключатели микрофона и камеры в быстрых настройках.
Закругленный прямоугольник в правом верхнем углу, в котором есть значки камеры и микрофона.
Рисунок 3. Индикаторы микрофона и камеры, которые показывают, когда в последний раз использовались эти устройства.

Разрешение на доступ к списку пакетов

На устройствах с Android 12 или более поздней версии приложения, предназначенные для Android 11 (уровня API 30) или более поздней версии и вызывающие один из следующих методов, получают отфильтрованный набор результатов на основе видимости пакета приложения для других приложений:

Реализация BouncyCastle удалена

В Android 12 удалены многие реализации криптографических алгоритмов BouncyCastle, которые ранее были объявлены устаревшими, включая все алгоритмы AES. Вместо этого система использует реализации этих алгоритмов в Conscrypt.

Это изменение затронет ваше приложение, если выполняется хотя бы одно из следующих условий:

  • В вашем приложении используются 512-битные ключи. Conscrypt не поддерживает этот размер ключа. При необходимости обновите криптографическую логику приложения, чтобы использовать ключи разных размеров.
  • В вашем приложении используются недопустимые размеры ключей с KeyGenerator. Реализация KeyGenerator в Conscrypt выполняет дополнительную проверку ключевых параметров по сравнению с BouncyCastle. Например, Conscrypt не позволяет приложению генерировать 64-битный ключ AES, поскольку AES поддерживает только 128-, 192- и 256-битные ключи.

    BouncyCastle позволяет генерировать ключи недопустимых размеров, но при их использовании с Cipher возникает ошибка. Conscrypt завершает работу раньше.

  • Вы инициализируете шифры GCM, используя размер, отличный от 12 байт. Реализация GcmParameterSpec в Conscrypt требует инициализации 12 байт, что соответствует рекомендациям NIST.

Уведомления о доступе к буферу обмена

В Android 12 и более поздних версиях, когда приложение вызывает getPrimaryClip(), чтобы впервые получить доступ к данным буфера обмена из другого приложения, пользователь видит всплывающее уведомление.

Текст во всплывающем сообщении имеет следующий формат: APP pasted from your clipboard.

Информация о тексте в описании клипа

На устройствах с Android 12 и более поздними версиями ОС getPrimaryClipDescription() может определять следующие данные:

  • Стилизованный текст, используя isStyledText().
  • Различные классификации текста, например URL, с помощью getConfidenceScore().

Приложения не могут закрывать системные диалоговые окна.

Чтобы пользователям было удобнее взаимодействовать с приложениями и системой, начиная с Android 12 действие intent ACTION_CLOSE_SYSTEM_DIALOGS больше не поддерживается. За исключением нескольких особых случаев, когда ваше приложение пытается вызвать намерение, содержащее это действие, система выполняет одно из следующих действий в зависимости от целевой версии SDK вашего приложения:

  • Если приложение предназначено для Android 12 или более поздней версии, возникает ошибка SecurityException.
  • Если приложение предназначено для Android 11 (уровень API 30) или более ранней версии, намерение не выполняется, а в Logcat появляется следующее сообщение:

    E ActivityTaskManager Permission Denial: \
    android.intent.action.CLOSE_SYSTEM_DIALOGS broadcast from \
    com.package.name requires android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, \
    dropping broadcast.
    

Исключения

В следующих случаях приложение может закрывать системные диалоговые окна на устройствах с Android 12 и более поздними версиями:

  • В приложении выполняется инструментальный тест.
  • Приложение предназначено для Android 11 или более ранней версии и показывает окно поверх панели уведомлений.

  • Приложение предназначено для Android 11 или более ранней версии. Кроме того, пользователь взаимодействовал с уведомлением, возможно, с помощью командных кнопок, а ваше приложение обрабатывает сервис или широковещательный приемник в ответ на это действие.

  • Приложение предназначено для Android 11 или более ранней версии и имеет активный сервис специальных возможностей. Если ваше приложение предназначено для Android 12 и вы хотите закрыть панель уведомлений, используйте действие специальных возможностей GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE.

Ненадежные события касания заблокированы

Чтобы обеспечить безопасность системы и удобство для пользователей, в Android 12 приложения не могут обрабатывать события касания, если оверлей небезопасным образом перекрывает приложение. Другими словами, система блокирует нажатия, которые проходят через определенные окна, за некоторыми исключениями.

Затронутые приложения

Изменение затронет приложения, которые пропускают касания через свои окна, например с помощью флага FLAG_NOT_TOUCHABLE. Вот несколько примеров:

  • Оверлеи, для которых требуется разрешение SYSTEM_ALERT_WINDOW, например окна, использующие TYPE_APPLICATION_OVERLAY и флаг FLAG_NOT_TOUCHABLE.
  • Окна действий, в которых используется флаг FLAG_NOT_TOUCHABLE.

Исключения

В следующих случаях разрешены сквозные касания:

  • Взаимодействие с приложением. Оверлей показывается только тогда, когда пользователь взаимодействует с приложением.
  • Надежные окна. К таким окнам относятся, помимо прочего, следующие:

  • Невидимые окна. Корневое представление окна – GONE или INVISIBLE.

  • Полностью прозрачные окна. Свойство alpha для окна равно 0,0.

  • Достаточно прозрачные системные окна оповещений. Набор окон системных оповещений считается достаточно прозрачным, если общая непрозрачность меньше или равна максимальной непрозрачности, при которой система может регистрировать касания. В Android 12 максимальная непрозрачность по умолчанию равна 0, 8.

Как определить, что ненадежное касание заблокировано

Если система блокирует нажатие, в Logcat появляется следующее сообщение:

Untrusted touch due to occlusion by PACKAGE_NAME

Протестируйте изменение

На устройствах с Android 12 и более поздними версиями ненадежные касания блокируются по умолчанию. Чтобы разрешить ненадежные касания, выполните в окне терминала следующую команду ADB:

# A specific app
adb shell am compat disable BLOCK_UNTRUSTED_TOUCHES com.example.app

# All apps
# If you'd still like to see a Logcat message warning when a touch would be
# blocked, use 1 instead of 0.
adb shell settings put global block_untrusted_touches 0

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

# A specific app
adb shell am compat reset BLOCK_UNTRUSTED_TOUCHES com.example.app

# All apps
adb shell settings put global block_untrusted_touches 2

Жизненный цикл объекта activity

Действия корневого средства запуска больше не завершаются при нажатии кнопки "Назад"

В Android 12 изменена обработка по умолчанию нажатия кнопки "Назад" в действиях запуска, которые находятся в корне задач. В предыдущих версиях система завершала эти действия при нажатии кнопки "Назад". В Android 12 система теперь перемещает действие и его задачу в фоновый режим, а не завершает действие. Новое поведение соответствует текущему поведению при выходе из приложения с помощью кнопки главного экрана или жеста.

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

Рекомендуем протестировать приложения с учетом этого изменения. Если в вашем приложении переопределен метод onBackPressed() для обработки обратной навигации и завершения Activity, обновите реализацию, чтобы вместо завершения вызывался метод super.onBackPressed(). Вызов super.onBackPressed() перемещает действие и его задачу в фоновый режим, когда это необходимо, и обеспечивает более согласованную навигацию для пользователей в разных приложениях.

Также обратите внимание, что в целом мы рекомендуем использовать API AndroidX Activity для обеспечения пользовательской обратной навигации, а не переопределять onBackPressed(). AndroidX Activity API автоматически переключаются на соответствующее поведение системы, если нет компонентов, перехватывающих нажатие кнопки "Назад".

Графика и изображения

Улучшенное переключение частоты обновления

В Android 12 частота обновления, заданная с помощью метода setFrameRate(), может меняться независимо от того, поддерживает ли экран плавный переход к новой частоте. Плавный переход – это переход без визуальных прерываний, например без черного экрана в течение одной-двух секунд. Ранее, если дисплей не поддерживал плавный переход, он обычно продолжал использовать ту же частоту обновления после вызова setFrameRate(). Вы можете заранее определить, будет ли переход на новую частоту обновления плавным, вызвав метод getAlternativeRefreshRates(). Обычно обратный вызов onDisplayChanged() выполняется после завершения переключения частоты обновления, но для некоторых внешних экранов он выполняется во время неплавного перехода.

Вот пример того, как это можно сделать:

Kotlin

// Determine whether the transition will be seamless.
// Non-seamless transitions may cause a 1-2 second black screen.
val refreshRates = this.display?.mode?.alternativeRefreshRates
val willBeSeamless = Arrays.asList<FloatArray>(refreshRates).contains(newRefreshRate)

// Set the frame rate even if the transition will not be seamless.
surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)

Java

// Determine whether the transition will be seamless.
// Non-seamless transitions may cause a 1-2 second black screen.
Display display = context.getDisplay(); // API 30+
Display.Mode mode = display.getMode();
float[] refreshRates = mode.getAlternativeRefreshRates();
boolean willBeSeamless = Arrays.asList(refreshRates).contains(newRefreshRate);

// Set the frame rate even if the transition will not be seamless.
surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS);

Функции связи

Обновления Passpoint

В Android 12 добавлены следующие API:

  • isPasspointTermsAndConditionsSupported() Условия использования – это функция Passpoint, которая позволяет заменить небезопасные страницы входа, использующие открытые сети, на защищенную сеть Passpoint. Если пользователю нужно принять условия использования, он увидит уведомление. Приложения, которые предлагают сети Passpoint, ограниченные условиями использования, должны сначала вызвать этот API, чтобы убедиться, что устройство поддерживает эту функцию. Если устройство не поддерживает эту функцию, оно не сможет подключиться к сети и необходимо предложить альтернативную или устаревшую сеть.
  • isDecoratedIdentitySupported(). При аутентификации в сетях с префиксом операторы могут обновлять идентификатор доступа к сети (NAI), чтобы выполнять явную маршрутизацию через несколько прокси-серверов в сети AAA (подробнее об этом читайте в RFC 7542).

    В Android 12 эта функция реализована в соответствии со спецификацией WBA для расширений PPS-MO. Приложения, которые предлагают сети Passpoint, требующие декорированного идентификатора, должны сначала вызвать этот API, чтобы убедиться, что устройство поддерживает эту функцию. Если устройство не поддерживает эту функцию, идентификатор не будет дополнен и аутентификация в сети может завершиться ошибкой.

Чтобы создать рекомендацию Passpoint, приложения должны использовать классы PasspointConfiguration, Credential и HomeSp. Эти классы описывают профиль Passpoint, который определен в спецификации Wi-Fi Alliance Passpoint.

Подробнее о Wi-Fi Suggestion API для подключения к интернету…

Обновленные ограничения для интерфейсов, не входящих в SDK

В Android 12 обновлены списки ограниченных интерфейсов, не относящихся к SDK. Они составлены на основе сотрудничества с разработчиками Android и последних внутренних тестов. По возможности мы стараемся сделать так, чтобы перед ограничением интерфейсов, не входящих в SDK, были доступны общедоступные альтернативы.

Если ваше приложение не поддерживает Android 12, некоторые из этих изменений могут не затронуть вас сразу. Однако, хотя в настоящее время вы можете использовать некоторые интерфейсы, не относящиеся к SDK (в зависимости от целевого уровня API вашего приложения), использование любого метода или поля, не относящегося к SDK, всегда сопряжено с высоким риском нарушения работы вашего приложения.

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

Подробнее об изменениях в ограничениях на использование интерфейсов, не входящих в SDK, в Android 12… Подробнее об ограничениях на интерфейсы, не входящие в SDK…