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

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

Если версия targetSdkVersion вашего приложения — 29 или выше, вам также потребуется поддержка дополнительных изменений. Подробнее см. в разделе «Изменения поведения приложений, ориентированных на версию 29» .

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

  • Фоновый доступ к местоположению устройства
  • Начинается фоновая активность
  • Информация о близости контактов
  • Рандомизация MAC-адресов
  • Метаданные камеры
  • Модель разрешений

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

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

Чтобы обеспечить стабильность и совместимость приложений, платформа начала ограничивать использование интерфейсов, не входящих в SDK, в Android 9 (уровень API 28). В Android 10 обновлён список запрещённых интерфейсов, не входящих в SDK, основанный на результатах сотрудничества с разработчиками Android и последних внутренних тестов. Наша цель — убедиться в наличии общедоступных альтернатив, прежде чем ограничивать использование интерфейсов, не входящих в SDK.

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

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

Дополнительную информацию см. в разделах Обновления ограничений интерфейсов, не относящихся к SDK, в Android 10 и Ограничения для интерфейсов, не относящихся к SDK .

Навигация жестами

Начиная с Android 10, пользователи могут включить навигацию жестами по всему устройству. Включение навигации жестами влияет на все приложения на устройстве, независимо от того, поддерживает ли приложение API уровня 29. Например, если пользователь проводит пальцем от края экрана, система интерпретирует этот жест как навигацию «Назад», если только приложение специально не переопределяет этот жест для отдельных частей экрана.

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

НДК

Android 10 включает следующие изменения NDK.

Общие объекты не могут содержать перемещения текста.

В Android 6.0 (уровень API 23) запрещено использование перемещений текста в общих объектах. Код должен загружаться «как есть» и не должен изменяться. Это изменение улучшает время загрузки приложения и безопасность.

SELinux применяет это ограничение к приложениям, предназначенным для Android 10 и более поздних версий. Если эти приложения продолжат использовать общие объекты, содержащие перемещения текста, они подвергаются высокому риску выхода из строя.

Изменения в библиотеках Bionic и путях динамического компоновщика

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

  • /system/lib/libc.so -> /apex/com.android.runtime/lib/bionic/libc.so
  • /system/lib/libm.so -> /apex/com.android.runtime/lib/bionic/libm.so
  • /system/lib/libdl.so -> /apex/com.android.runtime/lib/bionic/libdl.so
  • /system/bin/linker -> /apex/com.android.runtime/bin/linker

Эти изменения применяются и к 64-битным вариантам файла, при этом lib/ заменяется на lib64/ .

Для совместимости символические ссылки предоставлены по старым путям. Например, /system/lib/libc.so — это символическая ссылка на /apex/com.android.runtime/lib/bionic/libc.so . Таким образом, dlopen(“/system/lib/libc.so”) продолжает работать, но приложения обнаружат разницу, когда попытаются проверить загруженные библиотеки, прочитав /proc/self/maps или что-то подобное. Это нетипично, но мы обнаружили, что некоторые приложения делают это в рамках своей защиты от взлома. В этом случае пути /apex/… следует добавить в качестве допустимых путей для файлов Bionic.

Системные двоичные файлы/библиотеки, отображаемые в память, доступную только для выполнения

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

Вы можете определить, вызвало ли это поведение сбой, изучив соответствующий файл-захоронение в каталоге /data/tombstones/ . Сбой, связанный только с выполнением, содержит следующее сообщение об аварийном завершении:

Cause: execute-only (no-read) memory access error; likely due to data in .text.

Чтобы обойти эту проблему и выполнять такие операции, как проверка памяти, можно пометить сегменты, доступные только для выполнения, как «чтение и выполнение», вызвав mprotect() . Однако мы настоятельно рекомендуем впоследствии вернуть статус «только выполнение», поскольку такая настройка прав доступа обеспечивает лучшую защиту вашего приложения и пользователей.

Безопасность

Android 10 включает следующие изменения безопасности.

TLS 1.3 включен по умолчанию

В Android 10 и более поздних версиях протокол TLS 1.3 включён по умолчанию для всех TLS-подключений. Вот несколько важных сведений о нашей реализации TLS 1.3:

  • Наборы шифров TLS 1.3 нельзя настраивать. Поддерживаемые наборы шифров TLS 1.3 всегда включены при включении TLS 1.3. Любая попытка отключить их вызовом setEnabledCipherSuites() игнорируется.
  • При согласовании TLS 1.3 объекты HandshakeCompletedListener вызываются до добавления сеансов в кэш сеансов. (В TLS 1.2 и других предыдущих версиях эти объекты вызываются после добавления сеансов в кэш сеансов.)
  • В некоторых ситуациях, когда экземпляры SSLEngine вызывают исключение SSLHandshakeException в предыдущих версиях Android, в Android 10 и выше эти экземпляры вызывают исключение SSLProtocolException .
  • Режим 0-RTT не поддерживается.

При желании вы можете получить SSLContext с отключенным TLS 1.3, вызвав SSLContext.getInstance("TLSv1.2") . Вы также можете включать или отключать версии протокола для каждого соединения, вызвав setEnabledProtocols() для соответствующего объекта.

Сертификаты, подписанные с помощью SHA-1, не являются доверенными в TLS.

В Android 10 сертификаты, использующие алгоритм хеширования SHA-1, не являются доверенными в TLS-подключениях. Корневые центры сертификации не выдавали такие сертификаты с 2016 года, и им больше не доверяют Chrome и другие популярные браузеры.

Любая попытка подключения завершится неудачей, если подключение осуществляется к сайту, который представляет сертификат, использующий SHA-1.

Изменения и улучшения поведения KeyChain

Некоторые браузеры, например Google Chrome, позволяют пользователям выбирать сертификат, когда TLS-сервер отправляет сообщение с запросом сертификата в рамках TLS-рукопожатия. Начиная с Android 10, объекты KeyChain учитывают параметры эмитентов и спецификации ключа при вызове метода KeyChain.choosePrivateKeyAlias() для отображения запроса на выбор сертификата. В частности, этот запрос не содержит вариантов, не соответствующих спецификациям сервера.

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

Кроме того, на устройствах с Android 10 и выше не требуется блокировка экрана для импорта ключей или сертификатов CA в объект KeyChain .

Другие изменения TLS и криптографии

В библиотеках TLS и криптографии произошло несколько незначительных изменений, которые вступают в силу в Android 10:

  • Шифры AES/GCM/NoPadding и ChaCha20/Poly1305/NoPadding возвращают более точные размеры буфера из getOutputSize() .
  • Набор шифров TLS_FALLBACK_SCSV не используется при попытках подключения с максимальной версией протокола TLS 1.2 или выше. В связи с улучшениями в реализации TLS-сервера мы не рекомендуем использовать внешний резервный протокол TLS. Вместо этого мы рекомендуем полагаться на согласование версии TLS.
  • ChaCha20-Poly1305 — это псевдоним для ChaCha20/Poly1305/NoPadding.
  • Имена хостов с конечными точками не считаются допустимыми именами хостов SNI.
  • Расширение support_signature_algorithms в CertificateRequest учитывается при выборе ключа подписи для ответов сертификатов.
  • С подписями RSA-PSS в TLS можно использовать непрозрачные ключи подписи, например из Android Keystore.

Трансляции Wi-Fi Direct

На Android 10 следующие трансляции, связанные с Wi-Fi Direct, не являются фиксированными:

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

Возможности Wi-Fi Aware

В Android 10 добавлена поддержка для упрощения создания сокетов TCP/UDP с использованием каналов передачи данных Wi-Fi Aware. Для создания сокета TCP/UDP, подключаемого к ServerSocket , клиентскому устройству необходимо знать IPv6-адрес и порт сервера. Ранее для этого требовалось передавать данные по внешнему каналу, например, с помощью Bluetooth или Wi-Fi Aware Layer 2, или обнаруживать их внутри канала с помощью других протоколов, например, mDNS. В Android 10 эта информация может передаваться в рамках настройки сети.

Сервер может выполнить одно из следующих действий:

  • Инициализируйте ServerSocket и установите или получите порт, который будет использоваться.
  • Укажите информацию о порте как часть сетевого запроса Wi-Fi Aware.

В следующем примере кода показано, как указать информацию о порте в сетевом запросе:

Котлин

val ss = ServerSocket()
val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
  .setPskPassphrase("some-password")
  .setPort(ss.localPort)
  .build()

val myNetworkRequest = NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build()

Ява

ServerSocket ss = new ServerSocket();
WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier
  .Builder(discoverySession, peerHandle)
  .setPskPassphrase(some-password)
  .setPort(ss.getLocalPort())
  .build();

NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build();

Затем клиент выполняет сетевой запрос Wi-Fi Aware, чтобы получить IPv6 и порт, предоставленные сервером:

Котлин

val callback = object : ConnectivityManager.NetworkCallback() {
  override fun onAvailable(network: Network) {
    ...
  }
  
  override fun onLinkPropertiesChanged(network: Network,
      linkProperties: LinkProperties) {
    ...
  }

  override fun onCapabilitiesChanged(network: Network,
      networkCapabilities: NetworkCapabilities) {
    ...
    val ti = networkCapabilities.transportInfo
    if (ti is WifiAwareNetworkInfo) {
       val peerAddress = ti.peerIpv6Addr
       val peerPort = ti.port
    }
  }
  override fun onLost(network: Network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback)

Ява

callback = new ConnectivityManager.NetworkCallback() {
  @Override
  public void onAvailable(Network network) {
    ...
  }
  @Override
  public void onLinkPropertiesChanged(Network network,
      LinkProperties linkProperties) {
    ...
  }
  @Override
  public void onCapabilitiesChanged(Network network,
      NetworkCapabilities networkCapabilities) {
    ...
    TransportInfo ti = networkCapabilities.getTransportInfo();
    if (ti instanceof WifiAwareNetworkInfo) {
       WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti;
       Inet6Address peerAddress = info.getPeerIpv6Addr();
       int peerPort = info.getPort();
    }
  }
  @Override
  public void onLost(Network network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback);

SYSTEM_ALERT_WINDOW на устройствах Go

Приложения, работающие на устройствах Android 10 (Go edition), не могут получить разрешение SYSTEM_ALERT_WINDOW . Это связано с тем, что отрисовка окон наложения использует слишком много памяти, что особенно негативно сказывается на производительности устройств Android с небольшим объёмом памяти.

Если приложение, работающее на устройстве Go edition под управлением Android 9 или ниже, получает разрешение SYSTEM_ALERT_WINDOW , приложение сохраняет это разрешение даже после обновления устройства до Android 10. Однако приложениям, у которых еще нет этого разрешения, его нельзя предоставить после обновления устройства.

Если приложение на устройстве Go отправляет намерение с действием ACTION_MANAGE_OVERLAY_PERMISSION , система автоматически отклоняет запрос и перенаправляет пользователя на экран настроек , где сообщается, что разрешение не предоставлено, поскольку оно замедляет работу устройства. Если приложение на устройстве Go вызывает Settings.canDrawOverlays() , метод всегда возвращает false. Опять же, эти ограничения не распространяются на приложения, получившие разрешение SYSTEM_ALERT_WINDOW до обновления устройства до Android 10.

Предупреждения для приложений, ориентированных на старые версии Android

Устройства под управлением Android 10 и выше выводят предупреждение при первом запуске любого приложения, предназначенного для Android 5.1 (уровень API 22) или ниже. Если приложение требует от пользователя предоставления разрешений, пользователю также предоставляется возможность настроить разрешения перед первым запуском приложения.

Из-за требований к целевому API Google Play пользователь видит эти предупреждения только при запуске приложения, которое давно не обновлялось. Для приложений, распространяемых через другие магазины, аналогичные требования к целевому API вступают в силу в 2019 году. Подробнее об этих требованиях см. в статье «Расширение требований к целевому API в 2019 году» .

Наборы шифров SHA-2 CBC удалены

Следующие наборы шифров SHA-2 CBC были удалены с платформы:

  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

Эти наборы шифров менее безопасны, чем аналогичные наборы шифров, использующие GCM, и большинство серверов либо поддерживают оба варианта этих наборов шифров — GCM и CBC, либо не поддерживают ни один из них.

Использование приложения

В Android 10 внесены следующие изменения в поведение, связанные с использованием приложений:

  • Улучшения в использовании приложения UsageStats — Android 10 точно отслеживает использование приложений с помощью UsageStats при работе в режиме разделённого экрана или «картинка в картинке». Кроме того, Android 10 корректно отслеживает использование приложений в режиме реального времени.

  • Оттенки серого для каждого приложения — Android 10 позволяет устанавливать режим отображения оттенков серого для каждого приложения.

  • Состояние отвлечения внимания для каждого приложения — Android 10 может выборочно устанавливать для приложений «состояние отвлечения внимания», при котором их уведомления подавляются и они не отображаются в качестве рекомендуемых приложений.

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

Изменения HTTPS-соединения

Если приложение под управлением Android 10 передаёт значение null в setSSLSocketFactory() , возникает исключение IllegalArgumentException . В предыдущих версиях передача значения null в setSSLSocketFactory() имела тот же эффект, что и передача текущей фабрики по умолчанию .

Библиотека android.preference устарела

Библиотека android.preference устарела в Android 10. Разработчикам следует использовать библиотеку настроек AndroidX, входящую в состав Android Jetpack . Дополнительные ресурсы, облегчающие миграцию и разработку, можно найти в обновлённом руководстве по настройкам, а также в нашем общедоступном примере приложения и справочной документации .

Изменения в библиотеке утилит ZIP-файла

В Android 10 внесены следующие изменения в классы пакета java.util.zip , который обрабатывает ZIP-файлы. Эти изменения делают поведение библиотеки более согласованным на Android и других платформах, использующих java.util.zip .

Инфлятор

В предыдущих версиях некоторые методы класса Inflater вызывали исключение IllegalStateException , если они вызывались после вызова end() . В Android 10 эти методы вместо этого вызывают исключение NullPointerException .

ZipFile

В Android 10 и более поздних версиях конструктор ZipFile , принимающий аргументы типа File , int и Charset , не выдает исключение ZipException если предоставленный ZIP-файл не содержит никаких файлов.

ZipOutputStream

В Android 10 и выше метод finish() в ZipOutputStream не выдает исключение ZipException при попытке записать выходной поток для ZIP-файла, который не содержит никаких файлов.

Изменения камеры

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

Приложения, ориентированные на API уровня 24 или выше, должны явно устанавливать android:resizeableActivity и предоставлять необходимую функциональность для обработки многооконного режима.

Отслеживание использования батареи

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

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

Устаревание Android Beam

В Android 10 мы официально прекращаем поддержку Android Beam, устаревшей функции обмена данными между устройствами посредством технологии Near Field Communication (NFC). Мы также прекращаем поддержку нескольких связанных API NFC. Android Beam остаётся опционально доступным для партнёров-производителей устройств, но его активная разработка прекращена. Однако Android продолжит поддерживать другие возможности и API NFC, а такие сценарии использования, как чтение с меток и оплата, будут работать как и ожидалось.

Изменение поведения java.math.BigDecimal.stripTrailingZeros()

BigDecimal.stripTrailingZeros() больше не сохраняет конечные нули как особый случай, если входное значение равно нулю.

Изменения поведения java.util.regex.Matcher и Pattern

Результат split() был изменён: теперь он не начинается с пустой String ("") при совпадении нулевой ширины в начале входных данных. Это также влияет на String.split() . Например, "x".split("") теперь возвращает {"x"} , тогда как в старых версиях Android он возвращал {"", "x"} . "aardvark".split("(?=a)" теперь возвращает {"a", "ardv", "ark"} вместо {"", "a", "ardv", "ark"} .

Также было улучшено поведение исключений для недопустимых аргументов:

  • appendReplacement(StringBuffer, String) теперь выдаёт исключение IllegalArgumentException вместо IndexOutOfBoundsException , если заменяющая String заканчивается одиночной обратной косой чертой, что недопустимо. То же исключение теперь выдаётся, если заменяющая String заканчивается символом $ . Ранее в этом случае исключение не выдавалось.
  • replaceFirst(null) больше не вызывает reset() для Matcher , если он выдаёт исключение NullPointerException . NullPointerException теперь выдаётся и при отсутствии совпадений. Раньше оно выдавалось только при наличии совпадений.
  • start(int group) , end(int group) и group(int group) теперь вызывают более общее исключение IndexOutOfBoundsException , если индекс группы выходит за границы массива. Ранее эти методы вызывали исключение ArrayIndexOutOfBoundsException .

Угол по умолчанию для GradientDrawable теперь TOP_BOTTOM

В Android 10, если вы определяете GradientDrawable в XML и не указываете измерение угла, ориентация градиента по умолчанию будет TOP_BOTTOM . Это изменение по сравнению с предыдущими версиями Android, где по умолчанию использовалось LEFT_RIGHT .

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

Ведение журнала сериализованных объектов с использованием SUID по умолчанию

Начиная с Android 7.0 (уровень API 24), платформа исправила значение serialVersionUID по умолчанию для сериализуемых объектов . Это исправление не затронуло приложения, ориентированные на API уровня 23 или ниже.

Начиная с Android 10, если приложение ориентировано на API уровня 23 или ниже и использует старый, неверный serialVersionUID по умолчанию, система регистрирует предупреждение и предлагает исправление кода.

В частности, система регистрирует предупреждение, если выполняются все следующие условия:

  • Приложение рассчитано на уровень API 23 или ниже.
  • Класс сериализован.
  • Сериализованный класс использует serialVersionUID по умолчанию вместо явного задания serialVersionUID .
  • Значение serialVersionUID по умолчанию отличается от значения serialVersionUID , которое было бы, если бы приложение предназначалось для API уровня 24 или выше.

Это предупреждение регистрируется один раз для каждого затронутого класса. В предупреждении предлагается исправление, которое заключается в явной установке serialVersionUID на значение по умолчанию, которое рассчитывалось бы, если приложение ориентировано на API уровня 24 или выше. Используя это исправление, вы можете гарантировать, что при сериализации объекта этого класса в приложении, ориентированном на API уровня 23 или ниже, этот объект будет корректно считываться приложениями, ориентированными на API уровня 24 или выше, и наоборот.

Изменения java.io.FileChannel.map()

Начиная с Android 10, FileChannel.map() не поддерживается для нестандартных файлов, таких как /dev/zero , размер которых нельзя изменить с помощью truncate() . Предыдущие версии Android обрабатывали errno, возвращаемый truncate() , но Android 10 выдаёт исключение IOException. Если вам нужно старое поведение, необходимо использовать нативный код.