Изменения в поведении Android 7.0

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

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

Батарея и память

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

Доза

Представленный в Android 6.0 (уровень API 23), Doze увеличивает время автономной работы, откладывая работу ЦП и сети, когда пользователь оставляет устройство отключенным, неподвижным и с выключенным экраном. Android 7.0 вносит дополнительные улучшения в Doze, применяя подмножество ограничений ЦП и сети, когда устройство отключено от сети с выключенным экраном, но не обязательно неподвижно, например, когда телефон находится в кармане пользователя.

Иллюстрация того, как Doze применяет первый уровень ограничения активности системы для увеличения срока службы батареи

Рисунок 1. Иллюстрация того, как Doze применяет первый уровень ограничения активности системы для увеличения срока службы батареи.

Когда устройство работает от аккумулятора и экран выключен в течение определенного времени, устройство переходит в режим дремоты и применяет первый подмножество ограничений: оно отключает доступ приложения к сети, а также откладывает задания и синхронизацию. Если устройство находится в неподвижном состоянии в течение определенного времени после входа в режим Doze, система применяет остальные ограничения режима Doze к PowerManager.WakeLock , сигналам тревоги AlarmManager , GPS и сканированию Wi-Fi. Независимо от того, применяются ли некоторые или все ограничения Doze, система выводит устройство из спящего режима на короткие окна обслуживания, во время которых приложениям разрешен доступ к сети и они могут выполнять любые отложенные задания/синхронизацию.

Иллюстрация того, как Doze применяет второй уровень ограничения активности системы после того, как устройство находится в неподвижном состоянии в течение определенного времени

Рисунок 2. Иллюстрация того, как Doze применяет второй уровень ограничения активности системы после того, как устройство находится в неподвижном состоянии в течение определенного времени.

Обратите внимание, что активация экрана или подключение устройства приводит к выходу из Doze и снятию ограничений обработки. Дополнительное поведение не влияет на рекомендации и рекомендации по адаптации вашего приложения к предыдущей версии Doze, представленной в Android 6.0 (уровень API 23), как описано в разделе «Оптимизация для Doze и режима ожидания приложения» . Вам по-прежнему следует следовать этим рекомендациям, например использовать Firebase Cloud Messaging (FCM) для отправки и получения сообщений, а также начать планировать обновления, чтобы учесть дополнительное поведение Doze.

Проект Svelte: фоновая оптимизация

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

На мобильных устройствах часто происходят изменения в подключении, например при переходе между Wi-Fi и мобильными данными. В настоящее время приложения могут отслеживать изменения в подключении, регистрируя получатель неявной трансляции CONNECTIVITY_ACTION в своем манифесте. Поскольку многие приложения регистрируются для получения этой трансляции, один сетевой коммутатор может заставить их всех проснуться и обработать трансляцию одновременно.

Аналогичным образом, в предыдущих версиях Android приложения могли регистрироваться для получения неявных трансляций ACTION_NEW_PICTURE и ACTION_NEW_VIDEO от других приложений, таких как Камера. Когда пользователь делает снимок с помощью приложения «Камера», эти приложения активизируются для обработки трансляции.

Чтобы решить эти проблемы, Android 7.0 применяет следующие оптимизации:

  • Приложения, предназначенные для Android 7.0 (уровень API 24) и более поздних версий, не получают широковещательные сообщения CONNECTIVITY_ACTION , если они объявляют свой получатель широковещательных сообщений в манифесте. Приложения по-прежнему будут получать широковещательные сообщения CONNECTIVITY_ACTION , если они зарегистрируют свой BroadcastReceiver с помощью Context.registerReceiver() и этот контекст все еще действителен.
  • Система больше не отправляет трансляции ACTION_NEW_PICTURE или ACTION_NEW_VIDEO . Эта оптимизация затрагивает все приложения, а не только те, которые ориентированы на Android 7.0.

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

Дополнительную информацию о фоновой оптимизации в Android 7.0 (уровень API 24) и о том, как адаптировать ваше приложение, см. в разделе «Фоновая оптимизация» .

Изменения разрешений

Android 7.0 включает изменения в разрешениях, которые могут повлиять на ваше приложение.

Изменения разрешений файловой системы

Чтобы повысить безопасность личных файлов, к частному каталогу приложений, ориентированных на Android 7.0 или выше, доступ ограничен ( 0700 ). Этот параметр предотвращает утечку метаданных личных файлов, таких как их размер или существование. Это изменение разрешений имеет несколько побочных эффектов:

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

    Примечание. На данный момент это ограничение не соблюдается в полной мере. Приложения по-прежнему могут изменять разрешения для своего частного каталога с помощью собственных API или API File . Однако мы настоятельно не рекомендуем ослаблять разрешения для частного каталога.

  • Передача file:// за пределами домена пакета может оставить получателя недоступным путем. Таким образом, попытки передать file:// вызывают исключение FileUriExposedException . Рекомендуемый способ поделиться содержимым частного файла — использовать FileProvider .
  • DownloadManager больше не может делиться файлами, хранящимися в частном порядке, по имени файла. Устаревшие приложения могут оказаться с недоступным путем при доступе к COLUMN_LOCAL_FILENAME . Приложения, предназначенные для Android 7.0 или более поздней версии, вызывают исключение SecurityException при попытке доступа к COLUMN_LOCAL_FILENAME . Устаревшие приложения, которые устанавливают общедоступное расположение загрузки с помощью DownloadManager.Request.setDestinationInExternalFilesDir() или DownloadManager.Request.setDestinationInExternalPublicDir() по-прежнему могут получить доступ к пути в COLUMN_LOCAL_FILENAME , однако этот метод настоятельно не рекомендуется. Предпочтительный способ доступа к файлу, предоставляемому DownloadManager , — использование ContentResolver.openFileDescriptor() .

Обмен файлами между приложениями

Для приложений, ориентированных на Android 7.0, платформа Android применяет политику StrictMode API, которая запрещает раскрытие URI file:// за пределами вашего приложения. Если намерение, содержащее URI файла, покидает ваше приложение, приложение завершается с ошибкой FileUriExposedException .

Чтобы обмениваться файлами между приложениями, вам следует отправить content:// и предоставить временное разрешение доступа к этому URI. Самый простой способ предоставить это разрешение — использовать класс FileProvider . Дополнительную информацию о разрешениях и совместном использовании файлов см. в разделе Общий доступ к файлам .

Улучшения специальных возможностей

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

Масштаб экрана

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

Экран с изображением системы Android 7.0 в неувеличенном масштабе.
Экран, демонстрирующий эффект увеличения размера экрана устройства под управлением образа системы Android 7.0.

Рис. 3. На экране справа показан эффект увеличения размера дисплея устройства под управлением образа системы Android 7.0.

При изменении плотности устройств система уведомляет запущенные приложения следующими способами:

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

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

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

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

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

Настройки зрения в мастере настройки

Android 7.0 включает настройки зрения на экране приветствия, где пользователи могут настроить следующие параметры специальных возможностей на новом устройстве: жест увеличения , размер шрифта , размер дисплея и TalkBack . Это изменение повышает видимость ошибок, связанных с различными настройками экрана. Чтобы оценить влияние этой функции, вам следует протестировать свои приложения с включенными этими настройками. Настройки можно найти в разделе «Настройки» > «Доступность» .

Приложения NDK, связывающиеся с библиотеками платформы

Начиная с Android 7.0, система предотвращает динамическое связывание приложений с библиотеками, не относящимися к NDK, что может привести к сбою вашего приложения. Это изменение в поведении направлено на создание единообразного взаимодействия с приложениями на всех обновлениях платформы и разных устройствах. Даже если ваш код не связывается с частными библиотеками, вполне возможно, что это может делать сторонняя статическая библиотека в вашем приложении. Поэтому всем разработчикам следует убедиться, что их приложения не аварийно завершают работу на устройствах под управлением Android 7.0. Если ваше приложение использует собственный код, вам следует использовать только общедоступные API NDK .

Ваше приложение может попытаться получить доступ к API частной платформы тремя способами:

  • Ваше приложение напрямую обращается к частным библиотекам платформы. Вам следует обновить свое приложение, включив в него собственную копию этих библиотек или использовать общедоступные API NDK .
  • Ваше приложение использует стороннюю библиотеку, которая имеет доступ к частным библиотекам платформы. Даже если вы уверены, что ваше приложение не имеет прямого доступа к частным библиотекам, вам все равно следует протестировать свое приложение на предмет этого сценария.
  • Ваше приложение ссылается на библиотеку, которая не включена в его APK. Например, это могло произойти, если вы попытались использовать собственную копию OpenSSL, но забыли связать ее с APK вашего приложения. Приложение может нормально работать на версиях платформы Android, включая libcrypto.so . Однако приложение может аварийно завершить работу в более поздних версиях Android, которые не включают эту библиотеку (например, Android 6.0 и более поздних версий). Чтобы это исправить, убедитесь, что вы связали все библиотеки, не относящиеся к NDK, с APK.

Приложения не должны использовать собственные библиотеки, не включенные в NDK, поскольку они могут изменяться или удаляться в разных версиях Android. Переход с OpenSSL на BoringSSL является примером такого изменения. Кроме того, поскольку не существует требований совместимости для библиотек платформы, не включенных в NDK, разные устройства могут предлагать разные уровни совместимости.

Чтобы уменьшить влияние, которое это ограничение может оказать на выпущенные в настоящее время приложения, набор библиотек, которые активно используются, например libandroid_runtime.so , libcutils.so , libcrypto.so и libssl.so , временно доступны в Android 7.0. (уровень API 24) для приложений, ориентированных на уровень API 23 или ниже. Если ваше приложение загружает одну из этих библиотек, logcat генерирует предупреждение, и на целевом устройстве появляется всплывающее уведомление, уведомляющее вас. Если вы видите эти предупреждения, вам следует обновить свое приложение, включив в него собственную копию этих библиотек или используя только общедоступные API-интерфейсы NDK. Будущие выпуски платформы Android могут полностью ограничить использование частных библиотек и привести к сбою вашего приложения.

Все приложения генерируют ошибку времени выполнения, когда вызывают API, который не является ни общедоступным, ни временно доступным. В результате System.loadLibrary и dlopen(3) возвращают NULL и могут привести к сбою вашего приложения. Вам следует просмотреть код своего приложения, чтобы исключить использование API частной платформы, и тщательно протестировать свои приложения с помощью устройства или эмулятора под управлением Android 7.0 (уровень API 24). Если вы не уверены, использует ли ваше приложение частные библиотеки, вы можете проверить logcat, чтобы определить ошибку времени выполнения.

В следующей таблице описано поведение, которое вы можете ожидать от приложения в зависимости от использования им частных собственных библиотек и целевого уровня API ( android:targetSdkVersion ).

Библиотеки Целевой уровень API Доступ во время выполнения через динамический компоновщик Поведение Android 7.0 (уровень API 24) Будущее поведение платформы Android
НДК Общественный Любой Доступный Работает так, как ожидалось Работает так, как ожидалось
Частные (временно доступные частные библиотеки) 23 или ниже Временно доступен Работает как положено, но вы получаете предупреждение logcat. Ошибка выполнения
Частные (временно доступные частные библиотеки) 24 или выше Ограниченный Ошибка выполнения Ошибка выполнения
Частное (другое) Любой Ограниченный Ошибка выполнения Ошибка выполнения

Проверьте, использует ли ваше приложение частные библиотеки

Чтобы помочь вам выявить проблемы с загрузкой частных библиотек, logcat может генерировать предупреждение или ошибку во время выполнения. Например, если ваше приложение ориентировано на уровень API 23 или ниже и пытается получить доступ к частной библиотеке на устройстве под управлением Android 7.0, вы можете увидеть предупреждение, подобное следующему:

03-21 17:07:51.502 31234 31234 W linker  : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120

Эти предупреждения logcat сообщают вам, какая библиотека пытается получить доступ к API частной платформы, но не приводят к сбою вашего приложения. Однако если приложение нацелено на уровень API 24 или выше, logcat генерирует следующую ошибку времени выполнения, и ваше приложение может аварийно завершить работу:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by
"/system/lib/libnativeloader.so" is not accessible for the namespace
"classloader-namespace"
  at java.lang.Runtime.loadLibrary0(Runtime.java:977)
  at java.lang.System.loadLibrary(System.java:1602)

Вы также можете увидеть эти выходные данные logcat, если ваше приложение использует сторонние библиотеки, которые динамически связываются с API частной платформы. Инструмент readelf в Android 7.0DK позволяет вам создать список всех динамически связанных общих библиотек данного файла .so , выполнив следующую команду:

aarch64-linux-android-readelf -dW libMyLibrary.so

Обновите свое приложение

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

  • Если ваше приложение использует библиотеки частной платформы, вам следует обновить его, включив в него собственную копию этих библиотек, или использовать общедоступные API-интерфейсы NDK .
  • Если ваше приложение использует стороннюю библиотеку, которая обращается к частным символам, обратитесь к автору библиотеки, чтобы обновить ее.
  • Обязательно упакуйте все библиотеки, не относящиеся к NDK, вместе с APK.
  • Используйте стандартные функции JNI вместо getJavaVM и getJNIEnv из libandroid_runtime.so :
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • Используйте __system_property_get вместо символа Private property_get из libcutils.so . Для этого используйте __system_property_get со следующим включением:
    #include <sys/system_properties.h>
    

    Примечание. Доступность и содержимое системных свойств не проверяются с помощью CTS. Лучшим решением было бы вообще избегать использования этих свойств.

  • Используйте локальную версию символа SSL_ctrl из libcrypto.so . Например, вам следует статически связать libcyrpto.a в файле .so или включить динамически связанную версию libcrypto.so из BoringSSL/OpenSSL и упаковать ее в свой APK.

Android для работы

Android 7.0 содержит изменения для приложений, предназначенных для Android for Work, включая изменения в установке сертификатов, сбросе пароля, управлении дополнительными пользователями и доступе к идентификаторам устройств. Если вы создаете приложения для сред Android for Work, вам следует просмотреть эти изменения и внести соответствующие изменения в свое приложение.

  • Прежде чем ЦОД сможет установить установщик делегированного сертификата, необходимо установить его. Как для приложений профиля, так и для приложений владельца устройства, ориентированных на Android 7.0 (уровень API 24), вам следует установить установщик делегированного сертификата до того, как контроллер политики устройства (DPC) вызовет DevicePolicyManager.setCertInstallerPackage() . Если установщик еще не установлен, система выдает исключение IllegalArgumentException .
  • Ограничения по сбросу пароля для администраторов устройств теперь распространяются и на владельцев профилей. Администраторы устройств больше не могут использовать DevicePolicyManager.resetPassword() для очистки или изменения уже установленных паролей. Администраторы устройства по-прежнему могут устанавливать пароль, но только если на устройстве нет пароля, PIN-кода или шаблона.
  • Владельцы устройств и профилей могут управлять учетными записями, даже если установлены ограничения. Владельцы устройств и владельцы профилей могут вызывать API управления учетными записями, даже если установлены ограничения пользователей DISALLOW_MODIFY_ACCOUNTS .
  • Владельцам устройств будет проще управлять дополнительными пользователями. Когда устройство работает в режиме владельца устройства, автоматически устанавливается ограничение DISALLOW_ADD_USER . Это не позволяет пользователям создавать неуправляемых вторичных пользователей. Кроме того, методы CreateUser() и createAndInitializeUser() устарели; их заменяет новый метод DevicePolicyManager.createAndManageUser() .
  • Владельцы устройств могут получить доступ к идентификаторам устройств. Владелец устройства может получить доступ к MAC-адресу Wi-Fi устройства с помощью DevicePolicyManager.getWifiMacAddress() . Если Wi-Fi никогда не был включен на устройстве, этот метод возвращает значение null .
  • Параметр «Рабочий режим» контролирует доступ к рабочим приложениям. Когда рабочий режим выключен, системная панель запуска указывает, что рабочие приложения недоступны, выделяя их серым цветом. Повторное включение рабочего режима восстанавливает нормальное поведение.
  • При установке файла PKCS #12, содержащего цепочку сертификатов клиента и соответствующий закрытый ключ из пользовательского интерфейса настроек, сертификат CA в цепочке больше не устанавливается в доверенное хранилище учетных данных. Это не влияет на результат KeyChain.getCertificateChain() когда приложения позже попытаются получить цепочку сертификатов клиента. При необходимости сертификат CA следует установить в доверенное хранилище учетных данных через пользовательский интерфейс настроек отдельно в формате, закодированном DER, с расширением файла .crt или .cer.
  • Начиная с Android 7.0, регистрация и хранение отпечатков пальцев управляются для каждого пользователя. Если клиент политики устройства (DPC) владельца профиля нацелен на уровень API 23 (или ниже) на устройстве под управлением Android 7.0 (уровень API 24), пользователь по-прежнему может установить отпечаток пальца на устройстве, но рабочие приложения не могут получить доступ к отпечатку пальца устройства. Если ЦОД нацелен на уровень API 24 и выше, пользователь может установить отпечаток пальца специально для рабочего профиля, выбрав «Настройки» > «Безопасность» > «Безопасность рабочего профиля» .
  • Новый статус шифрования ENCRYPTION_STATUS_ACTIVE_PER_USER возвращается DevicePolicyManager.getStorageEncryptionStatus() , чтобы указать, что шифрование активно и ключ шифрования привязан к пользователю. Новый статус возвращается только в том случае, если DPC нацелен на уровень API 24 и выше. Для приложений, ориентированных на более ранние уровни API, возвращается ENCRYPTION_STATUS_ACTIVE , даже если ключ шифрования специфичен для пользователя или профиля.
  • В Android 7.0 некоторые методы, которые обычно влияют на все устройство, ведут себя по-другому, если на устройстве установлен рабочий профиль с отдельной рабочей задачей. Эти методы не затрагивают все устройство, а применяются только к рабочему профилю. (Полный список таких методов можно найти в документации DevicePolicyManager.getParentProfileInstance() .) Например, DevicePolicyManager.lockNow() блокирует только рабочий профиль, а не все устройство. Для каждого из этих методов вы можете получить старое поведение, вызвав метод родительского экземпляра DevicePolicyManager ; вы можете получить этого родителя, вызвав DevicePolicyManager.getParentProfileInstance() . Так, например, если вы вызываете метод lockNow() родительского экземпляра, все устройство блокируется.

Сохранение аннотаций

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

  • VISIBILITY_BUILD : предназначен для просмотра только во время сборки.
  • VISIBILITY_SYSTEM : предназначен для видимости во время выполнения, но только для базовой системы.

Если ваше приложение использует такое поведение, добавьте политику хранения к аннотациям, которые должны быть доступны во время выполнения. Это можно сделать с помощью @Retention(RetentionPolicy.RUNTIME) .

Изменения конфигурации TLS/SSL по умолчанию

Android 7.0 вносит следующие изменения в конфигурацию TLS/SSL по умолчанию, используемую приложениями для HTTPS и другого трафика TLS/SSL:

  • Наборы шифров RC4 теперь отключены.
  • Наборы шифров CHACHA20-POLY1305 теперь включены.

Отключение RC4 по умолчанию может привести к сбоям в подключении HTTPS или TLS/SSL, если сервер не согласовывает современные наборы шифров. Предпочтительным решением является улучшение конфигурации сервера для включения более надежных и современных наборов шифров и протоколов. В идеале должны быть включены TLSv1.2 и AES-GCM, а наборы шифров прямой секретности (ECDHE) должны быть включены и предпочтительны.

Альтернативой является изменение приложения для использования пользовательского SSLSocketFactory для связи с сервером. Фабрика должна быть спроектирована так, чтобы создавать экземпляры SSLSocket , в которых включены некоторые наборы шифров, необходимые серверу, в дополнение к наборам шифров по умолчанию.

Примечание. Эти изменения не относятся к WebView .

Приложения для Android 7.0

Эти изменения поведения применяются исключительно к приложениям, ориентированным на Android 7.0 (уровень API 24) или более поздних версий. Приложения, которые компилируются для Android 7.0 или устанавливают для targetSdkVersion значение Android 7.0 или более поздней версии, должны изменить свои приложения для правильной поддержки такого поведения, если это применимо к приложению.

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

В Android 7.0 (уровень API 24) исправлена ​​ошибка при вычислении значения SerialVersionUID по умолчанию, из-за которого он не соответствовал спецификации.

Классы, реализующие Serializable и не указывающие явное поле serialVersionUID могут увидеть изменение в их серийном идентификаторе SerialVersionUID по умолчанию, что приведет к выдаче исключения при попытке десериализации экземпляров класса, которые были сериализованы в более ранней версии или сериализованы приложением, предназначенным для более ранняя версия. Сообщение об ошибке будет выглядеть примерно так:

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

Для устранения этих проблем необходимо добавить поле serialVersionUID в любой затронутый класс со значением stream classdesc serialVersionUID из сообщения об ошибке, например 1234 в данном случае. Это изменение соответствует всем передовым рекомендациям по написанию кода сериализации и будет работать на всех версиях Android.

Конкретная исправленная ошибка была связана с наличием статических методов инициализации, то есть <clinit> . Согласно спецификации, наличие или отсутствие статического метода инициализации в классе повлияет на серийныйVersionUID по умолчанию, рассчитанный для этого класса. До исправления ошибки вычисление также проверяло суперкласс на наличие статического инициализатора, если у класса его не было.

Уточним: это изменение не затрагивает приложения, ориентированные на уровни API 23 или ниже, классы, имеющие поле serialVersionUID , или классы, имеющие статический метод инициализации.

Другие важные моменты

  • Когда приложение работает на Android 7.0, но нацелено на более низкий уровень API, а пользователь меняет размер экрана, процесс приложения завершается. Приложение должно иметь возможность корректно обрабатывать этот сценарий. В противном случае произойдет сбой, когда пользователь восстановит его из «Недавних».

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

    Приложения, предназначенные для Android 7.0 (уровень API 24) и выше, не отключаются автоматически при изменении плотности; однако они все равно могут плохо реагировать на изменения конфигурации.

  • Приложения на Android 7.0 должны корректно обрабатывать изменения конфигурации и не должны вызывать сбои при последующих запусках. Вы можете проверить поведение приложения, изменив размер шрифта ( Настройки > Дисплей > Размер шрифта ), а затем восстановив приложение из списка «Недавние».
  • Из-за ошибки в предыдущих версиях Android система не помечала запись в сокет TCP в основном потоке как нарушение строгого режима. Android 7.0 исправляет эту ошибку. Приложения, демонстрирующие такое поведение, теперь вызывают исключение android.os.NetworkOnMainThreadException . Как правило, выполнение сетевых операций в основном потоке — плохая идея, поскольку эти операции обычно имеют высокую задержку, вызывающую ошибки ANR и зависания.
  • Семейство методов Debug.startMethodTracing() теперь по умолчанию сохраняет выходные данные в каталоге вашего пакета в общем хранилище, а не на верхнем уровне SD-карты. Это означает, что приложениям больше не нужно запрашивать разрешение WRITE_EXTERNAL_STORAGE для использования этих API.
  • Многие API-интерфейсы платформы теперь начали проверять большие полезные данные, отправляемые через транзакции Binder , и система теперь повторно генерирует TransactionTooLargeExceptions как RuntimeExceptions вместо того, чтобы автоматически регистрировать или подавлять их. Одним из распространенных примеров является хранение слишком большого количества данных в Activity.onSaveInstanceState() , что приводит к тому, что ActivityThread.StopInfo генерирует исключение RuntimeException , когда ваше приложение ориентировано на Android 7.0.
  • Если приложение отправляет задачи Runnable в View , а View не прикреплено к окну, система ставит задачу Runnable в очередь с View ; Задача Runnable не выполняется до тех пор, пока View не будет прикреплено к окну. Такое поведение исправляет следующие ошибки:
    • Если приложение опубликовано в View из потока, отличного от потока пользовательского интерфейса предполагаемого окна, в результате Runnable может работать не в том потоке.
    • Если задача Runnable была опубликована из потока, отличного от потока цикла, приложение может предоставить задачу Runnable .
  • Если приложение на Android 7.0 с разрешением DELETE_PACKAGES пытается удалить пакет, но этот пакет установило другое приложение, системе потребуется подтверждение пользователя. В этом сценарии приложения должны ожидать STATUS_PENDING_USER_ACTION в качестве статуса возврата при вызове PackageInstaller.uninstall() .
  • Поставщик JCA под названием Crypto устарел, поскольку его единственный алгоритм SHA1PRNG криптографически слаб. Приложения больше не могут использовать SHA1PRNG для (небезопасного) получения ключей, поскольку этот поставщик больше недоступен. Дополнительную информацию см. в записи блога . Поставщик безопасности «Crypto» устарел в Android N.
,

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

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

Батарея и память

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

Дремать

Представленный в Android 6.0 (уровень API 23), Doze увеличивает время автономной работы, откладывая работу ЦП и сети, когда пользователь оставляет устройство отключенным, неподвижным и с выключенным экраном. Android 7.0 вносит дополнительные улучшения в Doze, применяя подмножество ограничений ЦП и сети, когда устройство отключено от сети с выключенным экраном, но не обязательно неподвижно, например, когда телефон находится в кармане пользователя.

Иллюстрация того, как Doze применяет первый уровень ограничения активности системы для увеличения срока службы батареи.

Рисунок 1. Иллюстрация того, как Doze применяет первый уровень ограничения активности системы для увеличения срока службы батареи.

Когда устройство работает от аккумулятора и экран выключен в течение определенного времени, устройство переходит в режим сна и применяет первый подмножество ограничений: оно отключает доступ приложения к сети, а также откладывает задания и синхронизацию. Если устройство находится в неподвижном состоянии в течение определенного времени после входа в режим Doze, система применяет остальные ограничения режима Doze к PowerManager.WakeLock , сигналам тревоги AlarmManager , GPS и сканированию Wi-Fi. Независимо от того, применяются ли некоторые или все ограничения Doze, система выводит устройство из спящего режима на короткие окна обслуживания, во время которых приложениям разрешен доступ к сети и они могут выполнять любые отложенные задания/синхронизацию.

Иллюстрация того, как Doze применяет второй уровень ограничения активности системы после того, как устройство находится в неподвижном состоянии в течение определенного времени

Рисунок 2. Иллюстрация того, как Doze применяет второй уровень ограничения активности системы после того, как устройство находится в неподвижном состоянии в течение определенного времени.

Обратите внимание, что активация экрана или подключение устройства приводит к выходу из Doze и снятию ограничений обработки. Дополнительное поведение не влияет на рекомендации и рекомендации по адаптации вашего приложения к предыдущей версии Doze, представленной в Android 6.0 (уровень API 23), как описано в разделе «Оптимизация для Doze и режима ожидания приложения» . Вам по-прежнему следует следовать этим рекомендациям, например использовать Firebase Cloud Messaging (FCM) для отправки и получения сообщений, а также начать планировать обновления, чтобы учесть дополнительное поведение Doze.

Проект Svelte: фоновая оптимизация

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

На мобильных устройствах часто происходят изменения в подключении, например при переходе между Wi-Fi и мобильными данными. В настоящее время приложения могут отслеживать изменения в подключении, регистрируя получателя неявной трансляции CONNECTIVITY_ACTION в своем манифесте. Поскольку многие приложения регистрируются для получения этой трансляции, один сетевой коммутатор может заставить их всех проснуться и обработать трансляцию одновременно.

Аналогично, в предыдущих версиях Android приложения могли регистрироваться для получения неявных трансляций ACTION_NEW_PICTURE и ACTION_NEW_VIDEO от других приложений, таких как Камера. Когда пользователь делает снимок с помощью приложения «Камера», эти приложения активизируются для обработки трансляции.

Чтобы решить эти проблемы, Android 7.0 применяет следующие оптимизации:

  • Приложения, предназначенные для Android 7.0 (уровень API 24) и более поздних версий, не получают широковещательные сообщения CONNECTIVITY_ACTION , если они объявляют свой получатель широковещательных сообщений в манифесте. Приложения по-прежнему будут получать широковещательные сообщения CONNECTIVITY_ACTION , если они зарегистрируют свой BroadcastReceiver с помощью Context.registerReceiver() и этот контекст все еще действителен.
  • Система больше не отправляет трансляции ACTION_NEW_PICTURE или ACTION_NEW_VIDEO . Эта оптимизация затрагивает все приложения, а не только те, которые ориентированы на Android 7.0.

Если ваше приложение использует какое -либо из этих намерений, вы должны удалить от них зависимости как можно скорее, чтобы вы могли правильно ориентироваться на устройства Android 7.0. Android Framework предоставляет несколько решений для смягчения необходимости этих неявных трансляций. Например, API JobScheduler предоставляет надежный механизм планирования сетевых операций, когда выполняются указанные условия, такие как подключение к незамеченной сети. Вы даже можете использовать JobScheduler , чтобы отреагировать на изменения поставщиков контента.

Для получения дополнительной информации об оптимизации фона в Android 7.0 (API -уровне 24) и о том, как адаптировать ваше приложение, см. Фоновые оптимизации .

Изменения разрешений

Android 7.0 включает изменения в разрешения, которые могут повлиять на ваше приложение.

Изменения разрешений на файловой системе

Чтобы улучшить безопасность частных файлов, частный каталог приложений, нацеленных на Android 7.0 или выше, имеет ограниченный доступ ( 0700 ). Этот параметр предотвращает утечку метаданных частных файлов, таких как их размер или существование. Это изменение разрешения имеет несколько побочных эффектов:

  • Разрешения на файлы частных файлов больше не должны быть расслаблены владельцем, и попытка сделать это с использованием MODE_WORLD_READABLE и/или MODE_WORLD_WRITEABLE , запустит SecurityException .

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

  • Передача file:// uris вне домена пакета может покинуть приемник с недоступным пути. Следовательно, попытки передать file:// URI запускает FileUriExposedException . Рекомендуемый способ поделиться содержанием частного файла - это использование FileProvider .
  • DownloadManager больше не может делиться в частном хранимых файлах по имени файла. Устаревшие приложения могут получить недоступный путь при доступе к COLUMN_LOCAL_FILENAME . Приложения, нацеленные на Android 7.0 или выше, запускают SecurityException при попытке получить доступ к COLUMN_LOCAL_FILENAME . Установившиеся приложения, которые устанавливают местоположение загрузки в общедоступное место с использованием DownloadManager.Request.setDestinationInExternalFilesDir() или DownloadManager.Request.setDestinationInExternalPublicDir() могут добраться до пути в COLUMN_LOCAL_FILENAME , однако, этот метод сильно расурит. Предпочтительным способом доступа к файлу, обнаруженному DownloadManager , является использование ContentResolver.openFileDescriptor() .

Обмен файлами между приложениями

Для приложений, нацеленных на Android 7.0, Android Framework обеспечивает соблюдение политики API StrictMode , которая запрещает выявление file:// uris вне вашего приложения. Если намерение, содержащее файловое URI, покидает ваше приложение, приложение не удается с исключением FileUriExposedException .

Чтобы обмениваться файлами между приложениями, вы должны отправить content:// URI и предоставить временное разрешение на доступ на URI. Самый простой способ предоставить это разрешение - использовать класс FileProvider . Для получения дополнительной информации о разрешениях и файлах обмена, см. Обмен файлами .

Улучшения доступности

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

Увеличение экрана

Android 7.0 позволяет пользователям устанавливать размер дисплея , который увеличивает или уменьшает все элементы на экране, тем самым улучшая доступность устройства для пользователей с низким зрением. Пользователи не могут увеличить экран мимо минимальной ширины экрана SW320DP , которая является шириной Nexus 4, общего телефона среднего размера.

Экран показывает размер размер дисплея, работающий на системе Android 7.0
Экран, показывающий эффект увеличения размера отображения устройства, работающего в системе Android 7.0

Рисунок 3. Экран справа показывает эффект увеличения размера дисплея устройства, работающего в системе Android 7.0.

Когда плотность устройства изменяется, система уведомляет запуска приложения следующими способами:

  • Если приложение нацелено на уровень API 23 или ниже, система автоматически убивает все свои фоновые процессы. Это означает, что если пользователь отключается от такого приложения, чтобы открыть экран «Настройки» и изменит настройку размера дисплея , система убивает приложение так же, как и в ситуации с низкой памяти. Если в приложении есть какие -либо процессы переднего плана, система уведомляет об этом процессе изменения конфигурации, как описано при обработке изменений времени выполнения , как если бы ориентация устройства изменилась.
  • Если приложение предназначено для Android 7.0, все его процессы (передний план и фон) уведомляются об изменении конфигурации, как описано при обработке изменений времени выполнения .

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

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

    ПРИМЕЧАНИЕ. Если вы кэшируете данные, зависящие от конфигурации, рекомендуется включить соответствующие метаданные, такие как соответствующий размер экрана или плотность пикселей для этих данных. Сохранение этих метаданных позволяет вам решить, нужно ли вам обновить кэшированные данные после изменения конфигурации.

  • Избегайте указания размеров с единицами PX, поскольку они не масштабируются с плотностью экрана. Вместо этого укажите размеры с единицами , независимыми от плотности пикселей ( dp ).

Настройки зрения в мастере настройки

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

Приложения NDK, ссылаясь на библиотеки платформ

Начиная с Android 7.0, система предотвращает динамическое связывание приложений с библиотеками без NDK, что может привести к сбою вашего приложения. Это изменение в поведении направлено на создание последовательного опыта приложений в разных обновлениях платформы и различных устройств. Несмотря на то, что ваш код может не ссылаться на частные библиотеки, возможно, что сторонняя статическая библиотека в вашем приложении может сделать это. Поэтому все разработчики должны проверить, чтобы убедиться, что их приложения не сбоятся на устройствах под управлением Android 7.0. Если в вашем приложении используется собственный код, вы должны использовать только публичные API NDK .

Есть три способа, которыми ваше приложение может пытаться получить доступ к API частной платформы:

  • Ваше приложение напрямую обращается к библиотекам частной платформы. Вы должны обновить свое приложение, чтобы включить собственную копию этих библиотек или использовать публичные API NDK .
  • Ваше приложение использует стороннюю библиотеку, которая обращается к библиотекам частной платформы. Даже если вы уверены, что ваше приложение не обращается к частным библиотекам напрямую, вам все равно следует проверить свое приложение для этого сценария.
  • Ваше приложение ссылается на библиотеку, которая не включена в его APK. Например, это может произойти, если вы попытаетесь использовать свою собственную копию OpenSSL, но забыли объединить ее с помощью APK вашего приложения. Приложение может нормально работать на версиях платформы Android, которая включает в себя libcrypto.so . Тем не менее, приложение может сбое на более поздних версиях Android, которые не включают эту библиотеку (например, Android 6.0 и позже). Чтобы исправить это, убедитесь, что вы объединяете все свои библиотеки NDK с помощью вашего APK.

Приложения не должны использовать собственные библиотеки, которые не включены в NDK, поскольку они могут меняться или удалять между различными версиями Android. Переключение от OpenSSL на BoringsSL является примером такого изменения. Кроме того, поскольку нет требований к совместимости для библиотек платформ, не включенных в NDK, разные устройства могут предлагать различные уровни совместимости.

Чтобы уменьшить влияние, которое это ограничение может оказать на выпущенные в настоящее время приложения, набор библиотек, которые видят значительное использование, например, как libandroid_runtime.so , libcutils.so , libcrypto.so и libssl.so - временно доступны на Android 7.0. (Уровень API 24) для приложений, нацеленных на уровень API 23 или ниже. Если ваше приложение загружает одну из этих библиотек, LogCat генерирует предупреждение, и на целевом устройстве появляется тост, чтобы уведомить вас. Если вы видите эти предупреждения, вы должны обновить свое приложение, чтобы либо включить его собственную копию этих библиотек, либо использовать только публичные API NDK. Будущие выпуски платформы Android могут вообще ограничить использование частных библиотек и привести к сбою вашего приложения.

Все приложения генерируют ошибку времени выполнения, когда они вызывают API, который не является ни общедоступным, ни временно доступным. Результатом является то, что System.loadLibrary и dlopen(3) оба возвращают NULL и могут привести к сбою вашего приложения. Вы должны просмотреть код приложения для удаления использования API частной платформы и тщательно протестировать ваши приложения, используя устройство или эмулятор под управлением Android 7.0 (уровень API 24). Если вы не уверены, использует ли ваше приложение частные библиотеки, вы можете проверить LogCat, чтобы определить ошибку времени выполнения.

В следующей таблице описывается поведение, которое вы должны ожидать от приложения в зависимости от его использования частных местных библиотек и его целевого уровня API ( android:targetSdkVersion ).

Библиотеки Целевой уровень API Доступ к времени выполнения через динамический линкер Android 7.0 (API -уровень 24) поведение Будущее поведение платформы Android
NDK Public Любой Доступный Работает, как и ожидалось Работает, как и ожидалось
Частные (временно доступные частные библиотеки) 23 или ниже Временно доступен Работает, как и ожидалось, но вы получаете предупреждение Logcat. Ошибка времени выполнения
Частные (временно доступные частные библиотеки) 24 или выше Ограниченный Ошибка времени выполнения Ошибка времени выполнения
Частный (другой) Любой Ограниченный Ошибка времени выполнения Ошибка времени выполнения

Проверьте, использует ли ваше приложение частные библиотеки

Чтобы помочь вам определить проблемы, загружающие частные библиотеки, LogCat может генерировать предупреждение или ошибку времени выполнения. Например, если ваше приложение предназначено для API -уровня 23 или ниже, и пытается получить доступ к частной библиотеке на устройстве под управлением Android 7.0, вы можете увидеть предупреждение, аналогичное следующему:

03-21 17:07:51.502 31234 31234 W linker  : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120

Эти предупреждения Logcat говорят вам, какая библиотека пытается получить доступ к API частной платформы, но не приведет к сбою вашего приложения. Если приложение нацелен на уровень API 24 или выше, однако, logCat генерирует следующую ошибку времени выполнения, и ваше приложение может сбое:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by
"/system/lib/libnativeloader.so" is not accessible for the namespace
"classloader-namespace"
  at java.lang.Runtime.loadLibrary0(Runtime.java:977)
  at java.lang.System.loadLibrary(System.java:1602)

Вы также можете увидеть эти выходы LogCat, если ваше приложение использует сторонние библиотеки, которые динамически связаны с API частной платформы. Инструмент Readelf в Android 7.0DK позволяет создать список всех динамически связанных общих библиотек данного файла .so , выполнив следующую команду:

aarch64-linux-android-readelf -dW libMyLibrary.so

Обновите свое приложение

Вот несколько шагов, которые вы можете предпринять, чтобы исправить эти типы ошибок и убедиться, что ваше приложение не сбои в будущих обновлениях платформы:

  • Если в вашем приложении используются библиотеки частной платформы, вы должны обновить его, чтобы включить собственную копию этих библиотек или использовать публичные API NDK .
  • Если ваше приложение использует стороннюю библиотеку, которая обращается к частным символам, свяжитесь с автором библиотеки, чтобы обновить библиотеку.
  • Убедитесь, что вы упаковываете все свои не NDK библиотеки с помощью вашего APK.
  • Используйте стандартные функции JNI вместо getJavaVM и getJNIEnv от libandroid_runtime.so :
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • Используйте __system_property_get вместо символа Private property_get от libcutils.so . Для этого используйте __system_property_get со следующим образом:
    #include <sys/system_properties.h>
    

    ПРИМЕЧАНИЕ. Доступность и содержание свойств системы не проверены через CTS. Лучшим исправлением было бы вообще избежать использования этих свойств.

  • Используйте локальную версию символа SSL_ctrl от libcrypto.so . Например, вы должны статически связать libcyrpto.a в вашем файле .so или включить динамически связанную версию libcrypto.so от boringssl/openssl и упаковать ее в свой APK.

Android для работы

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

  • Вы должны установить делегированный установщик сертификата, прежде чем DPC сможет его установить. Как для профиля, так и для приложений владельца устройств, нацеленных на Android 7.0 (API-уровень 24), вы должны установить делегированный установщик сертификата, прежде чем контроллер политики устройства (DPC) вызывает DevicePolicyManager.setCertInstallerPackage() . Если установщик еще не установлен, система бросает IllegalArgumentException .
  • Сбросить ограничения пароля для администраторов устройства теперь применяются к владельцам профиля. Администраторы устройств больше не могут использовать DevicePolicyManager.resetPassword() для очистки паролей или изменений, которые уже установлены. Администраторы устройства все еще могут устанавливать пароль, но только тогда, когда у устройства нет пароля, вывода или шаблона.
  • Владельцы устройств и профилей могут управлять учетными записями, даже если устанавливаются ограничения. Владельцы устройств и владельцы профилей могут позвонить в API управления учетной записью, даже если в наличии ограничения пользователей DISALLOW_MODIFY_ACCOUNTS .
  • Владельцы устройств могут легче управлять вторичными пользователями. Когда устройство работает в режиме владельца устройства, ограничение DISALLOW_ADD_USER автоматически устанавливается. Это мешает пользователям создавать неуправляемые вторичные пользователи. Кроме того, методы CreateUser() и createAndInitializeUser() устарели; Новый метод DevicePolicyManager.createAndManageUser() заменяет их.
  • Владельцы устройств могут получить доступ к идентификаторам устройства. Владелец устройства может получить доступ к MAC-адресу Wi-Fi устройства, используя DevicePolicyManager.getWifiMacAddress() . Если Wi-Fi никогда не был включен на устройство, этот метод возвращает значение null .
  • Настройка рабочего режима управляет доступом к рабочим приложениям. Когда рабочая режим не выходит за рамки системы запуска, показывают, что рабочие приложения недоступны, посылая их. Включение рабочего режима снова восстанавливает нормальное поведение.
  • При установке файла PKCS #12, содержащего цепочку сертификатов клиента, и соответствующий закрытый ключ из пользовательского интерфейса настроек, сертификат CA в цепочке больше не устанавливается на хранилище доверенных учетных данных. Это не влияет на результат KeyChain.getCertificateChain() когда приложения пытаются получить цепочку сертификатов клиента позже. При необходимости сертификат CA должен быть установлен в хранилище доверенных учетных данных через пользовательский интерфейс настройки отдельно, с форматом кодируемого DER в рамках расширения файла .crt или .cer.
  • Начиная с Android 7.0, регистрация отпечатков пальцев и хранение управляется на каждого пользователя. Если клиент политики устройства владельца владельца (DPC) нацелен на уровень API 23 (или ниже) на устройстве под управлением Android 7.0 (уровень API 24), пользователь по -прежнему может установить отпечаток пальца на устройстве, но рабочие приложения не могут получить доступ к отпечаткам устройства. Когда DPC нацелен на уровень API 24 и выше, пользователь может установить отпечаток пальца специально для профиля работы, перейдя в настройки> Security> Security Profile Security .
  • Новый статус шифрования ENCRYPTION_STATUS_ACTIVE_PER_USER возвращается DevicePolicyManager.getStorageEncryptionStatus() , чтобы указать, что шифрование активно и ключ шифрования привязана к пользователю. Новый статус возвращается только в том случае, если DPC нацелен на уровень API 24 и выше. Для приложений, нацеленных на более ранние уровни API, возвращается ENCRYPTION_STATUS_ACTIVE , даже если ключ шифрования является специфической для пользователя или профиля.
  • В Android 7.0 несколько методов, которые обычно влияют на все устройство, ведут себя по -разному, если у устройства установлен профиль рабочего, с отдельной рабочей задачей. Вместо того, чтобы влиять на все устройство, эти методы применяются только к рабочему профилю. (Полный список таких методов заключается в документации DevicePolicyManager.getParentProfileInstance() .) Например, DevicePolicyManager.lockNow() блокирует только рабочий профиль, вместо того, чтобы блокировать все устройство. Для каждого из этих методов вы можете получить старое поведение, вызывая метод на родительском экземпляре DevicePolicyManager ; Вы можете получить этого родителя, позвонив в DevicePolicyManager.getParentProfileInstance() . Так, например, если вы называете метод lockNow() родительского экземпляра, все устройство заблокировано.

Аннотации удержание

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

  • VISIBILITY_BUILD : предназначен для того, чтобы быть видимым только во время сборки.
  • VISIBILITY_SYSTEM : предназначен для того, чтобы быть видимым во время выполнения, но только для базовой системы.

Если ваше приложение полагалось на это поведение, добавьте политику удержания в аннотации, которые должны быть доступны во время выполнения. Вы делаете это, используя @Retention(RetentionPolicy.RUNTIME) .

Изменения конфигурации TLS/SSL по умолчанию

Android 7.0 вносит следующие изменения в конфигурации TLS/SSL по умолчанию, используемой приложениями для HTTPS и другого трафика TLS/SSL:

  • RC4 Sipher Suites теперь отключены.
  • Chacha20-Poly1305 Sipher Suites теперь включены.

RC4 отключен по умолчанию может привести к разрыву в подключении HTTPS или TLS/SSL, когда сервер не обсуждает современные комплекты шифров. Предпочтительным исправлением является улучшение конфигурации сервера, чтобы включить более сильные и современные шифры и протоколы. В идеале, TLSV1.2 и AES-GCM должны быть включены, а накладные Scipher Suites (ECDHE) вперед должны быть включены и предпочтительнее.

Альтернативой является изменение приложения для использования пользовательского SSLSocketFactory для связи с сервером. Фабрика должна быть разработана для создания экземпляров SSLSocket , в которых некоторые наборы шифров, необходимые для сервера, включенных в дополнение к комплектам по умолчанию.

Примечание. Эти изменения не относятся к WebView .

Приложения, нацеленные на Android 7.0

Эти изменения поведения применяются исключительно к приложениям, которые нацелены на Android 7.0 (уровень API 24) или выше. Приложения, которые компилируются против Android 7.0 или устанавливают targetSdkVersion на Android 7.0 или выше, должны изменить свои приложения для правильной поддержки этого поведения, где это применимо.

Сериализация изменяется

Android 7.0 (API -уровень 24) исправил ошибку в расчете серийного выхода по умолчанию, где он не соответствовал спецификации.

Классы, которые реализуют Serializable и не указывают явное поле serialVersionUID , может увидеть изменение в их серийном по умолчании, которое вызовет исключение при попытке десериализации экземпляров класса, которые были сериализованы на более ранней версии или сериализованы приложением, нацеленным на приложение более ранняя версия. Сообщение об ошибке будет выглядеть примерно так:

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

Исправление этих проблем требует добавления поля serialVersionUID в любой затронутый класс со значением stream classdesc serialVersionUID из сообщения об ошибке, например, 1234 в данном случае. Это изменение придерживается всех правильных рекомендаций по практике для написания кода сериализации и будет работать над всеми версиями Android.

Конкретная ошибка, которая была исправлена, была связана с наличием статических методов инициализатора, т. Е. <clinit> . В соответствии с спецификацией наличие или отсутствие метода статического инициализатора в классе повлияет на SerialVersionUID по умолчанию, рассчитанную для этого класса. Перед исправлением ошибки расчет также проверил бы супер класс для статического инициализатора, если у класса его не было.

Чтобы прояснить, это изменение не влияет на приложения, которые нацелены на уровни API 23 или ниже, классы, которые имеют поле serialVersionUID или классы, которые имеют статический метод инициализатора.

Другие важные моменты

  • Когда приложение работает на Android 7.0, но нацелено на более низкий уровень API, и пользователь изменяет размер отображения, процесс приложения убит. Приложение должно быть в состоянии изящно обрабатывать этот сценарий. В противном случае он сбои, когда пользователь восстанавливает его из Recents.

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

    Приложения, нацеленные на Android 7.0 (уровень API 24) и выше, не автоматически убиты при изменениях плотности; Тем не менее, они все еще могут плохо реагировать на изменения конфигурации.

  • Приложения на Android 7.0 должны иметь возможность изящно обрабатывать изменения конфигурации и не должны сбой при последующих запусках. Вы можете проверить поведение приложений, изменяя размер шрифта ( настройка > Дисплей > Размер шрифта ), а затем восстановив приложение из Recents.
  • Из-за ошибки в предыдущих версиях Android система не помечала написание в гнездо TCP в основном потоке как нарушение строгого режима. Android 7.0 исправляет эту ошибку. Приложения, которые демонстрируют это поведение, теперь бросают android.os.NetworkOnMainThreadException . Как правило, выполнение сетевых операций в основной теме - плохая идея, потому что эти операции обычно имеют высокую задержку, которая вызывает ANRS и Jank.
  • Семейство методов Debug.startMethodTracing() теперь по умолчанию по умолчанию хранения выводов в вашем каталоге с конкретным пакетом в общем хранилище, а не на верхнем уровне SD-карты. Это означает, что приложениям больше не нужно запросить разрешение WRITE_EXTERNAL_STORAGE для использования этих API.
  • Многие API платформы теперь начали проверять на большие полезные нагрузки, отправляемые через транзакции Binder , и теперь система пересматривает TransactionTooLargeExceptions как RuntimeExceptions , вместо того, чтобы молча вести или подавлять их. Одним из распространенных примеров является хранение слишком большого количества данных в Activity.onSaveInstanceState() , что заставляет ActivityThread.StopInfo для выброса RuntimeException , когда ваше приложение нацелено на Android 7.0.
  • Если приложение публикует Runnable задачи к View , а View не прикреплено к окну, система очередиется за Runnable задачу с View ; Runnable задача не выполняется до тех пор, пока View не будет прикреплено к окну. Такое поведение исправляет следующие ошибки:
    • Если приложение, размещенное в View из потока, отличного от поток пользовательского интерфейса Windended Window, в результате Runnable на неправильном потоке.
    • Если Runnable задание была опубликована из потока, отличного от потока, приложение может разоблачить Runnable .
  • Если приложение на Android 7.0 с разрешением DELETE_PACKAGES пытается удалить пакет, но в этом пакете было установлено другое приложение, система требует подтверждения пользователя. В этом сценарии приложения должны ожидать STATUS_PENDING_USER_ACTION в качестве статуса возврата, когда они вызывают PackageInstaller.uninstall() .
  • Поставщик JCA под названием Crypto устарел, потому что его единственный алгоритм Sha1prng, криптографически слаб. Приложения больше не могут использовать sha1prng для (небезопасно) вывода клавиш, потому что этот поставщик больше не доступен. Для получения дополнительной информации см. Поставщик «Crypto» в блоге «Crypto», устаревший в Android N.