Как и в предыдущих выпусках, в Android 17 есть изменения в поведении, которые могут повлиять на ваше приложение. Изменения, описанные ниже, касаются только приложений, предназначенных для Android 17 или более поздней версии. Если ваше приложение предназначено для Android 17 или более поздней версии, вам следует изменить его, чтобы поддерживать эти функции, где это применимо.
Также ознакомьтесь со списком изменений в поведении, которые затрагивают все приложения, работающие на Android 17, независимо от targetSdkVersion.
Удобство для пользователей и системный интерфейс
В Android 17 внесены изменения, которые делают интерфейс более единообразным и интуитивно понятным.
Виджет лимита памяти
Начиная с Android 17 система строго ограничивает объем памяти, выделяемый для обновлений RemoteViews в приложениях, предназначенных для Android 17 (уровень API 37) или более поздней версии. Когда приложение передает объект RemoteViews в AppWidgetManager.updateAppWidget, system_server вычисляет общий объем потребляемой памяти для всех данных изображений во всех сегментах ориентации и размера в полезной нагрузке. Если общий объем памяти превышает системный лимит (mMaxWidgetBitmapMemory), система отклоняет обновление и выдает ошибку IllegalArgumentException:
java.lang.IllegalArgumentException: RemoteViews for widget update exceeds maximum bitmap memory usage (used: XXXXX, max: YYYYY)
Для приложений с целевым уровнем API 36 или ниже система регистрирует это нарушение памяти как предупреждение (Slog.w), не вызывая исключение.
Как система рассчитывает лимит памяти
Система устанавливает бюджет памяти для битовой карты виджета в размере 6 * width * height байт (1.5 * 4 * width * height, что эквивалентно полуторному размеру полноэкранного буфера ARGB_8888) для активной конфигурации дисплея. Начиная с уровня API 37 в расчет включаются:
- Объекты
Bitmapв памяти и объектыIconна основе растровых изображений (Icon.TYPE_BITMAPиIcon.TYPE_ADAPTIVE_BITMAP), хранящиеся вRemoteViews.mBitmapCache(например, вызовыsetImageViewBitmap,Icon.createWithBitmap,Icon.createWithAdaptiveBitmapили Jetpack GlanceImageProvider(bitmap)). Каждый уникальный экземплярBitmapилиIconна основе растровых изображений вmBitmapCacheучитывается один раз в иерархииRemoteViews. - Изображения, поддерживаемые URI (
Icon.createWithContentUri,setImageViewUriили GlanceImageProvider(uri)), не учитываются в ограничении на количество байтов IPCRemoteViewsвsystem_server, но хост-процесс виджета декодирует указанный файлcontent://в полном разрешении в собственную кучу. Всегда записывайте уменьшенное изображение вcontext.cacheDir, прежде чем предоставлять к нему доступ через URIFileProvider.
Как устранить проблему
Чтобы обновления виджетов не превышали лимит памяти на телефонах, планшетах и складных устройствах, сделайте следующее:
Рассчитайте бюджет памяти во время выполнения из
WindowMetrics. На уровне API 30 и выше считывайте границы активного окна изWindowManager.currentWindowMetrics.bounds, а не изresources.displayMetrics. На устройствах с несколькими разрешениями и складных устройствахdisplayMetricsможет сообщать размеры неактивного экрана. Оцените общий бюджет изображений виджета в6L * bounds.width() * bounds.height(), как показано в следующем примере:private const val FALLBACK_MAX_BYTES = 15_000_000L fun calculateWidgetMemoryCapBytes(context: Context): Long { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val wm = context.getSystemService(WindowManager::class.java) ?: return FALLBACK_MAX_BYTES val bounds = wm.currentWindowMetrics.bounds return 6L * bounds.width().toLong() * bounds.height().toLong() } val dm = context.resources.displayMetrics return 6L * dm.widthPixels.toLong() * dm.heightPixels.toLong() }Уменьшите разрешение изображений до размеров виджета и используйте
RGB_565. Декодируйте растровые изображения со значениямиBitmapFactory.Options.inSampleSize, кратными двум, и размерами, соответствующими максимальным размерам виджета (maxWidthDpнаmaxHeightDp). ИспользуйтеBitmap.Config.RGB_565(2байта на пиксель) вместоARGB_8888(4байта на пиксель) для непрозрачных фотографий и значков.Вынесите декодирование растровых изображений за пределы
provideContentв Jetpack Glance. При использованииSizeMode.ResponsiveилиSizeMode.ExactGlance вызывает лямбда-выражениеprovideContentодин раз для каждого сегмента размера. Декодируйте каждый общий объектBitmapодин раз внутриprovideGlanceперед вызовомprovideContent, чтобы все группы размеров ссылались на один и тот же экземплярBitmapвRemoteViews.mBitmapCache.При замене изображений используйте полные вызовы
updateAppWidget. В классических реализацияхAppWidgetProviderне вызывайтеAppWidgetManager.partiallyUpdateAppWidgetдля замены представленийBitmapилиIcon. При частичном обновлении новые действия добавляются в существующее деревоRemoteViewsвsystem_serverбез удаления ранее кешированных действий с изображениями. Создайте полный макетRemoteViewsи вызовитеupdateAppWidget.Предоставьте резервный макет на случай ошибки. В Jetpack Glance переопределите
onCompositionError, чтобы при сбое обновления отображался резервный макетRemoteViewsбез растровых изображений.
Чтобы проверить текущее использование памяти сериализованного растрового изображения виджета на подключенном устройстве, выполните следующую команду:
adb shell dumpsys appwidget
Основные функции
В Android 17 внесены изменения, которые модифицируют или расширяют различные основные возможности системы Android.
Новая реализация MessageQueue без блокировки
Начиная с Android 17, приложения, предназначенные для Android 17 (уровень API 37) или более поздней версии, получают новую реализацию android.os.MessageQueue без блокировки. Новая реализация повышает производительность и уменьшает количество пропущенных кадров, но может нарушить работу клиентов, которые используют закрытые поля и методы MessageQueue.
Дополнительную информацию, в том числе о стратегиях смягчения мер, можно найти в руководстве по изменению поведения MessageQueue.
Статические финальные поля теперь нельзя изменить.
Приложения, работающие на Android 17 или более поздней версии и предназначенные для Android 17 (уровень API 37) или более поздней версии, не могут изменять поля static final. Если приложение попытается изменить поле static final с помощью рефлексии, возникнет ошибка IllegalAccessException. Попытка изменить одно из этих полей с помощью JNI API (например, SetStaticLongField()) приведет к сбою приложения.
Специальные возможности
В Android 17 внесены следующие изменения, улучшающие специальные возможности.
Поддержка специальных возможностей при вводе текста с помощью физической клавиатуры и редактора метода ввода
Эта функция добавляет новые API AccessibilityEvent и TextAttribute, которые улучшают озвучивание текста на экране при вводе на китайском, японском, корейском и вьетнамском языках. Теперь приложения с редактором метода ввода для китайского, японского, корейского и вьетнамского языков могут сообщать, был ли выбран вариант преобразования текста во время его ввода. Приложения с полями редактирования могут указывать типы изменения текста при отправке событий специальных возможностей, связанных с изменением текста.
Например, приложения могут указывать, что изменение текста произошло во время составления текста или что изменение текста произошло в результате фиксации.
Это позволяет сервисам специальных возможностей, например программам чтения с экрана, предоставлять более точную обратную связь в зависимости от характера изменения текста.
Внедрение приложения
Приложения IME. При настройке текста в полях редактирования редакторы методов ввода могут использовать
TextAttribute.Builder.setTextSuggestionSelected(), чтобы указать, был ли выбран определенный вариант конверсии.Приложения с полями редактирования. Приложения, которые поддерживают настраиваемое поле
InputConnection, могут получать данные о выбранных кандидатах, вызывая методTextAttribute.isTextSuggestionSelected(). При отправке событийTYPE_VIEW_TEXT_CHANGEDтакие приложения должны вызывать методAccessibilityEvent.setTextChangeTypes(). Для приложений, предназначенных для Android 17 (уровень API 37) и использующих стандартныйTextView, эта функция будет включена по умолчанию. (то естьTextViewбудет обрабатывать получение данных от IME и задавать типы изменений текста при отправке событий в сервисы специальных возможностей).Сервисы специальных возможностей. Сервисы специальных возможностей, которые обрабатывают события
TYPE_VIEW_TEXT_CHANGED, могут вызыватьAccessibilityEvent.getTextChangeTypes(), чтобы определить характер изменения и соответствующим образом скорректировать свои стратегии обратной связи.
Конфиденциальность
В Android 17 внесены следующие изменения, направленные на повышение конфиденциальности пользователей.
Расширение ECH (Encrypted Client Hello) включено
В Android 17 добавлена поддержка Encrypted Client Hello (ECH) – расширения TLS, которое повышает конфиденциальность пользователей, шифруя Server Name Indication (SNI) при подтверждении TLS. Это шифрование помогает предотвратить легкую идентификацию домена, к которому подключается ваше приложение, наблюдателями за сетью.
В приложениях, предназначенных для Android 17 (уровень API 37) или более поздней версии, для TLS-подключений используется ECH. ECH работает, только если сетевая библиотека, используемая приложением (например, HttpEngine, WebView или OkHttp), поддерживает ECH и удаленный сервер также поддерживает протокол ECH. Если согласовать ECH не удается, клиент отправляет расширение ECH со случайным содержимым (механизм ECH GREASE). Подробнее о том, как работает ECH GREASE, читайте в RFC 9849.
Чтобы приложения могли настраивать это поведение, в Android 17 в файл конфигурации сетевой безопасности добавлен новый элемент <domainEncryption>.
Разработчики могут использовать <domainEncryption> в тегах <base-config> или <domain-config>, чтобы выбрать режим ECH (например, "enabled" или "disabled") на глобальном уровне или для отдельных доменов.
Дополнительную информацию можно найти в документации по Encrypted Client Hello.
Для приложений, предназначенных для Android 17, требуется разрешение на доступ к локальной сети
В Android 17 появилось динамическое разрешение ACCESS_LOCAL_NETWORK, которое защищает пользователей от несанкционированного доступа к локальной сети. Поскольку это разрешение относится к существующей группе разрешений NEARBY_DEVICES, пользователям, которые уже предоставили другие разрешения NEARBY_DEVICES, не будет предлагаться сделать это снова. Это требование не позволяет вредоносным приложениям использовать неограниченный доступ к локальной сети для скрытого отслеживания пользователей и создания цифровых отпечатков. Объявив и запросив это разрешение, ваше приложение сможет обнаруживать устройства в локальной сети (LAN), такие как устройства умного дома или приемники трансляций, и подключаться к ним.
У приложений, предназначенных для Android 17 (уровень API 37) или более поздней версии, теперь есть два способа поддерживать связь с устройствами в локальной сети: использовать системные инструменты выбора устройств, обеспечивающие конфиденциальность, чтобы пропускать запрос разрешения, или явно запрашивать это новое разрешение во время выполнения, чтобы поддерживать связь в локальной сети.
Подробную информацию вы найдете в документации.
Скрытие паролей на физических устройствах
Если приложение поддерживает Android 17 (уровень API 37) или более позднюю версию и пользователь вводит пароль с помощью физического устройства ввода, например внешней клавиатуры, операционная система Android применяет новую настройку show_passwords_physical ко всем символам в поле пароля. По умолчанию эта настройка скрывает все символы пароля.
Система Android показывает последний введенный символ пароля, чтобы пользователь мог проверить, правильно ли он его ввел. Однако это гораздо менее необходимо при использовании больших внешних клавиатур. Кроме того, у устройств с внешними клавиатурами часто бывают большие экраны, что увеличивает риск того, что кто-то увидит вводимый пароль.
Если пользователь взаимодействует с сенсорным экраном, система применяет новое значение параметра show_passwords_touch.
Защита одноразовых кодов в стандартных SMS
Начиная с Android 17, защита одноразовых кодов из SMS будет распространяться и на стандартные SMS (содержащие одноразовый код, но не использующие форматы WebOTP или SMS Retriever). Для большинства приложений, предназначенных для Android 17 (уровень API 37) или более поздней версии, такие SMS-сообщения становятся доступны только через три часа после получения. Эта задержка предназначена для предотвращения перехвата одноразового пароля. В течение этого времени трансляция SMS_RECEIVED_ACTION задерживается, а запросы к базе данных SMS provider фильтруются. После задержки SMS-сообщение становится доступно этим приложениям.
Некоторые приложения, например помощник по умолчанию для SMS и сопутствующие приложения для подключенных устройств, не задерживаются. Чтобы обеспечить бесперебойную работу, все приложения, которые считывают SMS для извлечения одноразовых кодов, должны перейти на SMS Retriever API или SMS User Consent API.
Безопасность
В Android 17 улучшена безопасность устройств и приложений.
Безопасность действий
В Android 17 мы продолжили развивать архитектуру, защищенную по умолчанию. В частности, мы добавили ряд улучшений, которые помогают предотвращать серьезные атаки, такие как фишинг, перехват взаимодействия и атаки типа "заместитель с затуманенным сознанием". Чтобы обеспечить совместимость приложений и защиту пользователей, разработчикам необходимо явно согласиться с новыми стандартами безопасности.
Основные изменения для разработчиков:
- Усиление защиты от запуска фоновых действий и улучшенное согласие. Мы совершенствуем ограничения на запуск фоновых действий, распространяя защиту на
IntentSender. Разработчикам необходимо отказаться от использования устаревшей константыMODE_BACKGROUND_ACTIVITY_START_ALLOWED. Вместо этого следует использовать более точные элементы управления, такие какMODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE, которые ограничивают запуск действий сценариями, в которых вызывающее приложение видно, что значительно сокращает направления атак. - Инструменты для внедрения. Разработчикам следует использовать строгий режим и обновленные проверки lint, чтобы выявлять устаревшие шаблоны и обеспечивать готовность к будущим требованиям к целевому уровню SDK.
Включить прозрачность сертификатов по умолчанию
Если приложение поддерживает Android 17 (уровень API 37) или более поздние версии, проверка сертификата (CT) включена по умолчанию. В Android 16 эта функция доступна, но приложениям нужно включить ее.
Safer Native DCL—C
Если ваше приложение предназначено для Android 17 (уровень API 37) или более поздней версии, то защита Safer Dynamic Code Loading (DCL), представленная в Android 14 для файлов DEX и JAR, теперь распространяется и на нативные библиотеки.
Все нативные файлы, загруженные с помощью System.load(), должны быть помечены как доступные только для чтения.
В противном случае система выдает ошибку UnsatisfiedLinkError.
Мы рекомендуем по возможности избегать динамической загрузки кода, поскольку она значительно повышает риск того, что приложение будет взломано путем внедрения или изменения кода.
Ограничение доступа к полям с информацией, позволяющей идентифицировать личность, в представлении данных CP2
В приложениях, предназначенных для Android 17 (уровень API 37) и более поздних версий, Contacts Provider 2 (CP2) ограничивает доступ к определенным столбцам, содержащим информацию, позволяющую идентифицировать личность. Когда это изменение вступит в силу, эти столбцы будут удалены из представления данных, чтобы повысить конфиденциальность пользователей. К столбцам с ограниченным доступом относятся:
Приложения, которые используют эти столбцы из ContactsContract.Data, могут извлекать их из ContactsContract.RawContacts, объединив с RAW_CONTACT_ID.
Принудительно применять строгие проверки SQL в CP2
В приложениях, предназначенных для Android 17 (уровень API 37) и более поздних версий, поставщик контактов 2 (CP2) строго проверяет SQL-запросы, когда доступ к таблице ContactsContract.Data запрашивается без разрешения READ_CONTACTS.
Теперь, если у приложения нет разрешения READ_CONTACTS, при запросе таблицы ContactsContract.Data устанавливаются параметры StrictColumns и StrictGrammar. Если запрос использует шаблон, несовместимый с ними, он будет отклонен и вызовет исключение.
Обнаружение
В Android 17 внесены следующие изменения в системный интеллект.
Прекращение поддержки setContentCaptureEnabled
На некоторых устройствах функция "Запись контента" включена по умолчанию. Она позволяет ИИ-функциям на устройстве анализировать содержимое экрана, чтобы предлагать умные возможности.
Начиная с Android 17 метод API ContentCaptureManager.setContentCaptureEnabled(boolean) больше не поддерживается. В приложениях, предназначенных для Android 17 (уровень API 37) или более поздних версий, вызов setContentCaptureEnabled(false) больше не отключает Content Capture.
Если в вашем приложении по-прежнему нужно отключать Content Capture или запрещать системе записывать содержимое экрана, перейдите на параметр макета окна FLAG_SECURE.
Чтобы отключить захват контента, установите флаг FLAG_SECURE в окне, как показано в примере ниже.
Kotlin
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
Java
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);
Подробную информацию вы можете найти в справочной документации по WindowManager.LayoutParams.FLAG_SECURE.
Мультимедиа
В Android 17 внесены следующие изменения в работу с медиаконтентом.
Усиление защиты аудио в фоновом режиме
Начиная с Android 17, аудиофреймворк накладывает ограничения на фоновые аудиовзаимодействия, включая воспроизведение аудио, запросы на фокусировку звука и API изменения громкости, чтобы гарантировать, что эти изменения запускаются пользователем намеренно.
Некоторые ограничения на аудио действуют для всех приложений. Однако ограничения становятся более строгими, если приложение предназначено для Android 17 (уровень API 37). Если одно из этих приложений взаимодействует с аудио в фоновом режиме, у него должна быть запущена активная служба. Кроме того, приложение должно соответствовать одному или обоим следующим требованиям:
- Активная служба должна иметь возможности, доступные во время использования.
- У приложения должно быть разрешение на операции в точное время и взаимодействие с аудиопотоками
USAGE_ALARM.
Дополнительную информацию, в том числе о стратегиях устранения уязвимостей, можно найти в статье Усиление защиты фонового аудио.
Типы устройств
В Android 17 внесены изменения, которые повышают удобство использования устройств разных размеров и форм-факторов.
Изменения в Platform API, позволяющие игнорировать ограничения на ориентацию, изменение размера и соотношение сторон на больших экранах (sw>=600 dp)
В Android 16 мы изменили API платформы, чтобы игнорировать ограничения на ориентацию, изменение размера и соотношение сторон на больших экранах (sw >= 600 dp) для приложений, предназначенных для целевого уровня API 36 или выше. Разработчики могут отказаться от этих изменений в SDK 36, но этот вариант будет недоступен для приложений, предназначенных для Android 17 (уровень API 37) или более поздней версии.
Подробнее о том, почему игнорируются ограничения на ориентацию и изменение размера…
Функции связи
В Android 17 внесены следующие изменения, чтобы улучшить согласованность и соответствие стандартному поведению InputStream в Java для сокетов RFCOMM Bluetooth.
Согласованное поведение метода read() класса BluetoothSocket для RFCOMM
В приложениях, предназначенных для Android 17 (уровень API 37), метод read() класса InputStream, полученного из BluetoothSocket на основе RFCOMM, теперь возвращает -1, когда сокет закрыт или подключение прервано.
Это изменение делает поведение сокета RFCOMM согласованным с сокетами LE CoC и соответствует стандартной документации InputStream.read(), в которой говорится, что -1 возвращается, когда достигается конец потока.
Это изменение может повлиять на приложения, которые полагаются исключительно на перехват исключения IOException для выхода из цикла чтения. В таких приложениях необходимо обновить циклы чтения BluetoothSocket, чтобы явно проверять возвращаемое значение -1. Это гарантирует, что цикл завершится правильно, когда удаленное устройство отключится или сокет будет закрыт. Пример рекомендуемой реализации можно найти в фрагменте кода в руководстве Передача данных по Bluetooth.