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

Платформа 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 действия, чтобы определить, может ли действие выполняться в многооконном режиме. Если resizeableActivity="false" , приложение не сможет работать в многооконном режиме независимо от минимальной ширины и высоты.

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

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

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

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

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

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

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

Ограниченный сегмент ожидания приложений

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

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

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

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

Проверьте, находится ли ваше приложение в ограниченном сегменте

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

Проверьте поведение ограниченного сегмента

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

adb shell am set-standby-bucket PACKAGE_NAME restricted

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

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

Диалоговое окно имеет два набора параметров, один над другим.
Рисунок 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 Launcher больше не завершаются при нажатии «Назад»

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

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

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

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

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

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

В 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);

Возможности подключения

Обновления пароля

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