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

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

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

Пользовательский опыт

Эффект растягивания прокрутки

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

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

Более подробную информацию см. в руководстве по анимации жестов прокрутки .

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

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

Инструкции см. в разделе Перенос существующей реализации экрана-заставки на Android 12 .

Кроме того, начиная с Android 12, система всегда применяет новый системный экран-заставку Android по умолчанию при холодном и тёплом запуске всех приложений. По умолчанию этот системный экран-заставка формируется на основе значка вашего приложения и 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

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

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

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

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

Котлин

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

Ява

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

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

Котлин

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

Ява

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

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

В Android 12 многооконный режим становится стандартным поведением.

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

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

Более подробную информацию см. в разделе Поддержка многооконного режима .

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

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

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

Задержка UX для уведомлений служб переднего плана

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

Производительность

Ограниченный резервный контейнер приложений

В Android 11 (уровень API 30) появился ограниченный контейнер в качестве резервного контейнера приложений (App Standby Bucket). Начиная с 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 .

Плитки быстрых настроек называются «Доступ к камере» и «Доступ к микрофону».
Рисунок 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() .

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

Чтобы улучшить контроль пользователя при взаимодействии с приложениями и системой, действие намерения ACTION_CLOSE_SYSTEM_DIALOGS устарело, начиная с Android 12. За исключением нескольких особых случаев , когда ваше приложение пытается вызвать намерение , содержащее это действие, система выполняет одно из следующих действий в зависимости от целевой версии 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

Жизненный цикл деятельности

Действия root-лаунчера больше не завершаются при нажатии «Назад».

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

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

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

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

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

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

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

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

Котлин

// 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)

Ява

// 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 .

Дополнительную информацию см. в разделе API предложений Wi-Fi для подключения к Интернету .

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

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

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

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

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