В 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, в 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 и более поздними версиями ОС для импорта ключей или сертификатов ЦС в объект 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 на устройствах 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_SHA256TLS_RSA_WITH_AES_256_CBC_SHA256TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256TLS_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 Preference, которая входит в 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. Если вам нужно старое поведение, используйте нативный код.