Изменения в поведении 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.