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

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

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

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

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

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

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

Чтобы обеспечить стабильность и совместимость приложений, в Android 9 (уровень API 28) мы начали ограничивать использование интерфейсов, не относящихся к SDK. В 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. Например, если пользователь проводит пальцем от края экрана, система интерпретирует этот жест как переход назад, если только приложение не переопределяет этот жест для определенных частей экрана.

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

NDK

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

Чтобы узнать, вызвано ли падение приложения этой проблемой, проверьте файл tombstone в /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, эти экземпляры вызывают SSLProtocolException в Android 10 и более поздних версиях.
  • Режим 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 и более поздних версий не требуется блокировка экрана, чтобы импортировать ключи или сертификаты ЦС в объект KeyChain.

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

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

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

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

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

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

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

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

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

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

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

Kotlin

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

Java

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 и порт, предоставленные сервером:

Kotlin

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)

Java

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 на устройствах Android Go

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

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

Если приложение на устройстве Android Go отправляет намерение с действием ACTION_MANAGE_OVERLAY_PERMISSION, система автоматически отклоняет запрос и перенаправляет пользователя на экран Настройки, где указано, что разрешение не предоставлено, поскольку оно замедляет работу устройства. Если приложение на устройстве Android 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 – устаревшей функции для передачи данных между устройствами с помощью технологии связи малого радиуса действия (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. Если вам нужно старое поведение, используйте нативный код.