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

Android 9 (уровень API 28) вносит ряд изменений в систему Android. Следующие изменения поведения применяются ко всем приложениям , работающим на платформе Android 9, независимо от уровня API, на который они нацелены. Всем разработчикам следует просмотреть эти изменения и модифицировать свои приложения для их надлежащей поддержки, если это применимо к приложению.

Изменения, которые затрагивают только приложения, ориентированные на уровень API 28 или выше, см. в разделе Изменения поведения: приложения, ориентированные на уровень API 28+ .

Управление энергопотреблением

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

Подробности см. в разделе Управление питанием .

Изменения конфиденциальности

Для повышения конфиденциальности пользователей в Android 9 внесено несколько изменений поведения, таких как ограничение доступа фоновых приложений к датчикам устройства, ограничение информации, получаемой при сканировании Wi-Fi, а также новые правила разрешений и группы разрешений, связанные с телефонными звонками, состоянием телефона и Wi-Fi. Fi сканирует.

Эти изменения затрагивают все приложения, работающие на Android 9, независимо от целевой версии SDK.

Ограниченный доступ к датчикам в фоновом режиме

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

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

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

Ограниченный доступ к журналам вызовов

В Android 9 представлена ​​группа разрешений CALL_LOG и перемещены разрешения READ_CALL_LOG , WRITE_CALL_LOG и PROCESS_OUTGOING_CALLS в эту группу. В предыдущих версиях Android эти разрешения находились в группе разрешений PHONE .

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

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

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

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

Ограниченный доступ к телефонным номерам

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

Номера телефонов, связанные с входящим и исходящим вызовами, отображаются в широковещательной передаче состояния телефона , например, для входящих и исходящих вызовов, и доступны из класса PhoneStateListener . Однако без разрешения READ_CALL_LOG поле номера телефона, предоставляемое в широковещательных рассылках PHONE_STATE_CHANGED и через PhoneStateListener , пусто.

Чтобы читать номера телефонов из состояния телефона, обновите приложение, чтобы оно запрашивало необходимые разрешения в зависимости от вашего варианта использования:

Ограниченный доступ к данным о местоположении и подключении Wi-Fi.

В Android 9 требования к разрешениям приложения на сканирование Wi-Fi более строгие, чем в предыдущих версиях. Подробную информацию см. в разделе Ограничения сканирования Wi-Fi .

Аналогичные ограничения также применяются к методу getConnectionInfo() , который возвращает объект WifiInfo , описывающий текущее соединение Wi-Fi. Вы можете использовать методы этого объекта для получения значений SSID и BSSID только в том случае, если вызывающее приложение имеет следующие разрешения:

  • ACCESS_FINE_LOCATION или ACCESS_COARSE_LOCATION
  • ACCESS_WIFI_STATE

Для получения SSID или BSSID также необходимо включить службы определения местоположения на устройстве (в разделе «Настройки» > «Местоположение »).

Информация удалена из методов обслуживания Wi-Fi.

В Android 9 следующие события и трансляции не получают информацию о местоположении пользователя или личные данные:

Системная трансляция NETWORK_STATE_CHANGED_ACTION из Wi-Fi больше не содержит SSID (ранее EXTRA_SSID), BSSID (ранее EXTRA_BSSID) или информацию о соединении (ранее EXTRA_NETWORK_INFO). Если вашему приложению нужна эта информация, вместо этого вызовите getConnectionInfo() .

Информация о телефонии теперь зависит от настроек местоположения устройства.

Если пользователь отключил определение местоположения устройства на устройстве под управлением Android 9, следующие методы не дадут результатов:

Ограничения на использование интерфейсов, отличных от SDK.

Чтобы обеспечить стабильность и совместимость приложения, платформа ограничивает использование некоторых методов и полей, отличных от SDK; эти ограничения применяются независимо от того, пытаетесь ли вы получить доступ к этим методам и полям напрямую, через отражение или с помощью JNI. В Android 9 ваше приложение может продолжать получать доступ к этим ограниченным интерфейсам; платформа использует всплывающие уведомления и записи журнала, чтобы привлечь к ним ваше внимание. Если в вашем приложении отображается такое всплывающее уведомление, важно, чтобы вы придерживались стратегии реализации, отличной от ограниченного интерфейса. Если вы считаете, что никакая альтернативная стратегия невозможна, вы можете сообщить об ошибке и потребовать пересмотра ограничения.

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

Изменения в поведении безопасности

Изменения безопасности устройства

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

Изменения реализации TLS

Реализация TLS системы претерпела несколько изменений в Android 9:

  • Если экземпляру SSLSocket не удается подключиться во время его создания, система выдает IOException вместо NullPointerException .
  • Класс SSLEngine аккуратно обрабатывает любые возникающие оповещения close_notify .

Дополнительные сведения о выполнении безопасных веб-запросов в приложении Android см. в разделе «Пример HTTPS» .

Более строгий фильтр SECOMP

Android 9 дополнительно ограничивает системные вызовы, доступные приложениям. Такое поведение является расширением фильтра SECCOMP, который включен в Android 8.0 (уровень API 26) .

Криптографические изменения

В Android 9 внесено несколько изменений в реализацию и обработку криптографических алгоритмов.

Коншифровать реализации параметров и алгоритмов

Android 9 предоставляет дополнительные реализации параметров алгоритма в Conscrypt . К этим параметрам относятся: AES, DESEDE, OAEP и EC. Версии этих параметров и многих алгоритмов в Bouncy Castle устарели, начиная с Android 9.

Если ваше приложение предназначено для Android 8.1 (уровень API 27) или ниже, вы получите предупреждение при запросе реализации Bouncy Castle одного из этих устаревших алгоритмов. Однако если вы ориентируетесь на Android 9, каждый из этих запросов генерирует NoSuchAlgorithmException .

Другие изменения

В Android 9 представлено несколько других изменений, связанных с криптографией:

  • Если при использовании ключей PBE Bouncy Castle ожидает вектор инициализации (IV), а ваше приложение его не предоставляет, вы получите предупреждение.
  • Реализация шифра ARC4 в Conscrypt позволяет указать либо ARC4/ECB/NoPadding , либо ARC4/NONE/NoPadding .
  • Поставщик криптографической архитектуры Java (JCA) был удален. В результате, если ваше приложение вызывает SecureRandom.getInstance("SHA1PRNG", "Crypto") , возникает NoSuchProviderException .
  • Если ваше приложение анализирует ключи RSA из буферов, размер которых превышает структуру ключей, исключение больше не возникает.

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

Безопасные зашифрованные файлы Android больше не поддерживаются.

В Android 9 полностью удалена поддержка безопасных зашифрованных файлов Android (ASEC).

В Android 2.2 (уровень API 8) Android представил ASEC для поддержки функций приложений на SD-карте. В Android 6.0 (уровень API 23) платформа представила адаптируемую технологию устройств хранения данных , которую разработчики могут использовать вместо ASEC.

Обновления библиотек ICU

Android 9 использует библиотеку ICU версии 60. Android 8.0 (уровень API 26) и Android 8.1 (уровень API 27) используют ICU 58.

ICU используется для предоставления общедоступных API в android.icu package и используется внутри платформы Android для поддержки интернационализации. Например, он используется для реализации классов Android в java.util , java.text и android.text.format .

Обновление ICU 60 содержит множество небольших, но полезных изменений, включая поддержку данных Emoji 5.0 и улучшенные форматы даты и времени, как описано в примечаниях к выпуску ICU 59 и ICU 60.

Заметные изменения в этом обновлении:

  • Изменился способ обработки часовых поясов платформой.
    • Платформа лучше обрабатывает GMT и UTC; UTC больше не является синонимом GMT.

      ICU теперь предоставляет переведенные названия зон для GMT и UTC. Это изменение влияет на форматирование и анализ данных android.icu для таких зон, как «GMT», «Etc/GMT», «UTC», «Etc/UTC» и «Zulu».

    • java.text.SimpleDateFormat теперь использует ICU для предоставления отображаемых имен для UTC/GMT, что означает:
      • Форматирование zzzz создает длинную локализованную строку для многих локалей. Раньше он создавал «UTC» для UTC и строки типа «GMT+00:00» для GMT.
      • Анализ zzzz распознает такие строки, как «Всемирное координированное время» и «Среднее время по Гринвичу».
      • Приложения могут столкнуться с проблемами совместимости, если предполагают, что для zzzz на всех языках выводятся «UTC» или «GMT+00:00».
    • Поведение java.text.DateFormatSymbols.getZoneStrings() изменилось:
      • Как и в случае с SimpleDateFormat , UTC и GMT теперь имеют длинные имена. Варианты названий часовых поясов летнего времени для зоны UTC, такие как «UTC», «Etc/UTC» и «Zulu», становятся GMT+00:00, что является стандартным запасным вариантом, когда нет доступных имен, а не жестко закодированная строка UTC .
      • Некоторые идентификаторы зон правильно распознаются как синонимы других зон, поэтому Android находит строки для устаревших идентификаторов зон, таких как Eire , которые ранее не могли быть разрешены.
    • Азия/Ханой больше не является признанной зоной. По этой причине java.util.TimeZones.getAvailableIds() не возвращает это значение, а java.util.TimeZone.getTimeZone() не распознает его. Такое поведение соответствует существующему поведению android.icu .
  • Метод android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String) может вызывать исключение ParseException даже при анализе текста допустимой валюты. Избегайте этой проблемы, используя NumberFormat.parseCurrency , доступный начиная с Android 7.0 (уровень API 24), для текста валюты в стиле PLURALCURRENCYSTYLE .

Изменения в тесте Android

В Android 9 внесено несколько изменений в библиотеку и структуру классов платформы Android Test. Эти изменения помогают разработчикам использовать общедоступные API, поддерживаемые платформой, но изменения также обеспечивают большую гибкость при создании и запуске тестов с использованием сторонних библиотек или пользовательской логики.

Библиотеки удалены из фреймворка

В Android 9 классы на основе JUnit реорганизуются в три библиотеки: android.test.base , android.test.runner и android.test.mock . Это изменение позволяет вам запускать тесты на той версии JUnit, которая лучше всего работает с зависимостями вашего проекта. Эта версия JUnit может отличаться от той, которую предоставляет android.jar .

Чтобы узнать больше о том, как классы на основе JUnit организованы в эти библиотеки, а также о том, как подготовить проект вашего приложения к написанию и запуску тестов, см. раздел Настройка проекта для Android Test .

Изменения в сборке тестового набора

Метод addRequirements() в классе TestSuiteBuilder был удален, а сам класс TestSuiteBuilder объявлен устаревшим. Метод addRequirements() требовал от разработчиков предоставления аргументов, типы которых являются скрытыми API, что делало API недействительным.

Java-декодер UTF

UTF-8 — это кодировка по умолчанию в Android. Последовательность байтов UTF-8 можно декодировать с помощью конструктора String , например String(byte[] bytes) .

Декодер UTF-8 в Android 9 более строго соответствует стандартам Unicode, чем в предыдущих версиях. Изменения включают в себя следующее:

  • Несамая короткая форма UTF-8, такая как <C0, AF> , считается неправильной.
  • Суррогатная форма UTF-8, такая как U+D800 .. U+DFFF , считается неправильной.
  • Максимальная часть заменяется одним U+FFFD . Например, в последовательности байтов « 41 C0 AF 41 F4 80 80 41 » максимальными частями являются « C0 », « AF » и « F4 80 80 ». « F4 80 80 » может быть начальной подпоследовательностью « F4 80 80 80 », но « C0 » не может быть начальной подпоследовательностью любой правильно сформированной последовательности кодовой единицы. Таким образом, результат должен быть « A\ufffd\ufffdA\ufffdA ».
  • Чтобы декодировать измененную последовательность UTF-8/CESU-8 в Android 9 или более поздней версии, используйте метод DataInputStream.readUTF() или метод JNI NewStringUTF() .

Проверка имени хоста с помощью сертификата

RFC 2818 описывает два метода сопоставления имени домена с сертификатом — использование доступных имен в расширении subjectAltName ( SAN ) или, при отсутствии расширения SAN , использование commonName ( CN ).

Однако возврат к CN объявлен устаревшим в RFC 2818. По этой причине Android больше не возвращается к использованию CN . Чтобы проверить имя хоста, сервер должен предоставить сертификат с соответствующим SAN . Сертификаты, которые не содержат SAN , соответствующий имени хоста, больше не считаются доверенными.

Поиск сетевых адресов может вызвать сетевые нарушения

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

Класс StrictMode — это инструмент разработки, который помогает разработчикам обнаруживать проблемы в их коде.

В Android 9 и более поздних версиях StrictMode обнаруживает сетевые нарушения, вызванные поиском сетевых адресов, требующим разрешения имен.

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

Разрешение числового IP-адреса не считается операцией блокировки. Разрешение числовых IP-адресов работает так же, как и в версиях до Android 9.

Маркировка сокетов

В версиях платформы ниже Android 9, если сокет помечен с помощью метода setThreadStatsTag() , сокет не помечен, когда он отправляется в другой процесс с использованием связывателя IPC с контейнером ParcelFileDescriptor .

В Android 9 и более поздних версиях тег сокета сохраняется, когда он отправляется в другой процесс с помощью связывателя IPC. Это изменение может повлиять на статистику сетевого трафика, например, при использовании метода queryDetailsForUidTag() .

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

Сообщается количество доступных байтов в сокете

Метод available() возвращает 0 когда он вызывается после вызова метода shutdownInput() .

Более подробные отчеты о сетевых возможностях VPN.

В Android 8.1 (уровень API 27) и ниже класс NetworkCapabilities сообщал только ограниченный набор информации для VPN, например TRANSPORT_VPN , но опускал NET_CAPABILITY_NOT_VPN . Эта ограниченная информация затрудняла определение того, приведет ли использование VPN к взиманию платы с пользователя приложения. Например, проверка NET_CAPABILITY_NOT_METERED не позволит определить, измерялись ли базовые сети или нет.

В Android 9 и более поздних версиях, когда VPN вызывает метод setUnderlyingNetworks() , система Android объединяет транспорты и возможности любых базовых сетей и возвращает результат как эффективные сетевые возможности сети VPN.

В Android 9 и более поздних версиях приложения, которые уже проверяют NET_CAPABILITY_NOT_METERED получают сетевые возможности VPN и базовых сетей.

Файлы в папке xt_qtaguid больше не доступны приложениям.

Начиная с Android 9, приложениям не разрешен прямой доступ для чтения к файлам в папке /proc/net/xt_qtaguid . Причина в том, чтобы обеспечить совместимость с некоторыми устройствами, на которых эти файлы вообще отсутствуют.

Публичные API, использующие эти файлы, TrafficStats и NetworkStatsManager , продолжают работать должным образом. Однако неподдерживаемые функции Cutils , такие как qtaguid_tagSocket() , могут работать не так, как ожидалось, или вообще не работать на разных устройствах.

Требование FLAG_ACTIVITY_NEW_TASK теперь применяется.

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

Изменения поворота экрана

Начиная с Android 9, в режим поворота портретной ориентации внесены существенные изменения. В Android 8.0 (уровень API 26) пользователи могли переключаться между режимами автоматического поворота и портретного поворота с помощью плитки быстрых настроек или настроек дисплея. Портретный режим был переименован в « Блокировку вращения» и активен, когда автоматический поворот отключен. В режиме автоповорота изменений нет.

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

Действия, запрашивающие определенную ориентацию (например, screenOrientation=landscape ), игнорируют предпочтения блокировки пользователя и ведут себя так же, как в Android 8.0.

Предпочтение ориентации экрана можно установить на уровне активности в манифесте Android или программно с помощью setRequestedOrientation() .

Режим блокировки вращения работает путем установки предпочтений вращения пользователя, которые WindowManager использует при обработке вращения действий. Предпочтение ротации пользователей может быть изменено в следующих случаях. Обратите внимание, что существует тенденция возврата к естественному повороту устройства, который обычно является портретным для устройств форм-фактора телефона:

  • Когда пользователь принимает предложение о ротации, предпочтение ротации меняется на это предложение.
  • Когда пользователь переключается на приложение с принудительной портретной ориентацией (включая экран блокировки или панель запуска), предпочтение поворота меняется на портретное.

В следующей таблице приведены сведения о поведении вращения для распространенных ориентаций экрана:

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

Пользователям блокировки поворота будет предоставлена ​​возможность заблокировать перевернутую портретную ориентацию, часто на 180°.
сенсор, полныйСенсор, сенсорПортрет, сенсорЛандшафт Предпочтение режима блокировки вращения игнорируется и рассматривается так, как если бы автоповорот активен. Используйте это только в исключительных случаях и с очень тщательным учетом UX.

Устаревание HTTP-клиента Apache влияет на приложения с нестандартным ClassLoader

В Android 6.0 мы удалили поддержку HTTP-клиента Apache . Это изменение не повлияет на подавляющее большинство приложений, не предназначенных для Android 9 или более поздних версий. Однако это изменение может повлиять на некоторые приложения, использующие нестандартную структуру ClassLoader , даже если эти приложения не предназначены для Android 9 или более поздней версии.

Приложение может быть затронуто, если оно использует нестандартный ClassLoader , который явно делегирует системному ClassLoader . Вместо этого этим приложениям необходимо делегировать приложение ClassLoader при поиске классов в org.apache.http.* . Если они делегируют системному ClassLoader , приложения на Android 9 или более поздних версиях завершатся с ошибкой NoClassDefFoundError , поскольку эти классы больше не известны системному ClassLoader . Чтобы предотвратить подобные проблемы в будущем, приложения обычно должны загружать классы через ClassLoader приложения, а не обращаться к системному ClassLoader напрямую.

Перечисление камер

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

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