Изменения в Android 7.0

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

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

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

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

спящий режим

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

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

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

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

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

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

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

Project 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. Однако мы настоятельно не рекомендуем ослаблять разрешения для частного каталога.

  • Передача URI file:// за пределы домена пакета может привести к тому, что получатель не сможет получить доступ к пути. Поэтому попытки передать URI 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 применяет правила API StrictMode, которые запрещают использовать URI file:// за пределами приложения. Если намерение, содержащее URI файла, покидает приложение, возникает исключение FileUriExposedException.

Чтобы обмениваться файлами между приложениями, отправьте URI content:// и предоставьте временное разрешение на доступ к нему. Проще всего предоставить это разрешение с помощью класса 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 в будущем
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.0 NDK позволяет создать список всех динамически связанных общих библиотек для определенного файла .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 вместо закрытого символа 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 for Work

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

  • Прежде чем контроллер политик на устройствах сможет задать установщик делегированных сертификатов, его необходимо установить. Для приложений, предназначенных для Android 7.0 (уровень API 24) и работающих в режиме владельца профиля или устройства, необходимо установить делегированный установщик сертификатов до того, как контроллер политик на устройствах вызовет метод DevicePolicyManager.setCertInstallerPackage(). Если установщик не установлен, система выдает ошибку IllegalArgumentException.
  • Ограничения на сброс пароля для администраторов устройств теперь применяются к владельцам профилей. Администраторы устройств больше не могут использовать DevicePolicyManager.resetPassword(), чтобы удалять пароли или менять уже заданные. Администраторы устройств по-прежнему могут задавать пароль, но только если на устройстве не установлен пароль, PIN-код или графический ключ.
  • Владельцы устройств и профилей могут управлять аккаунтами, даже если установлены ограничения. Владельцы устройств и профилей могут вызывать Account Management API, даже если действуют ограничения для пользователей DISALLOW_MODIFY_ACCOUNTS.
  • Владельцы устройств могут управлять дополнительными пользователями. Если устройство работает в режиме владельца, ограничение DISALLOW_ADD_USER устанавливается автоматически. Это не позволит пользователям создавать неуправляемые дополнительные профили. Кроме того, методы CreateUser() и createAndInitializeUser() больше не поддерживаются. Вместо них используется метод DevicePolicyManager.createAndManageUser().
  • Владельцы устройств могут получать доступ к идентификаторам устройств. Владелец устройства может получить доступ к MAC-адресу Wi-Fi устройства с помощью DevicePolicyManager.getWifiMacAddress(). Если Wi-Fi никогда не включался на устройстве, этот метод возвращает значение null.
  • Настройка "Рабочий режим" управляет доступом к рабочим приложениям. Когда рабочий режим отключен, системный лаунчер показывает, что рабочие приложения недоступны, выделяя их серым цветом. Если включить рабочий режим снова, все вернется в норму.
  • При установке файла PKCS #12, содержащего цепочку сертификатов клиента и соответствующий закрытый ключ, из интерфейса настроек сертификат ЦС в цепочке больше не устанавливается в хранилище доверенных учетных данных. Это не влияет на результат KeyChain.getCertificateChain(), когда приложения пытаются получить цепочку сертификатов клиента позже. При необходимости сертификат ЦС следует установить в хранилище доверенных учетных данных отдельно, используя интерфейс настроек. Он должен быть в формате DER с расширением имени файла CRT или CER.
  • Начиная с Android 7.0 регистрация и хранение отпечатков пальцев управляются на уровне пользователя. Если контроллер политик на устройствах (DPC) владельца профиля предназначен для API уровня 23 (или ниже) на устройстве с Android 7.0 (API уровня 24), пользователь по-прежнему может настроить отпечаток пальца на устройстве, но рабочие приложения не смогут получить доступ к отпечатку пальца устройства. Если контроллер политик на устройствах предназначен для целевого уровня API 24 и выше, пользователь может настроить отпечаток пальца специально для рабочего профиля. Для этого нужно выбрать Настройки > Безопасность > Безопасность рабочего профиля.
  • DevicePolicyManager.getStorageEncryptionStatus() возвращает новый статус шифрования ENCRYPTION_STATUS_ACTIVE_PER_USER, который указывает, что шифрование активно и ключ шифрования привязан к пользователю. Новый статус возвращается, только если контроллер политик на устройствах предназначен для целевого уровня 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>. Согласно спецификации, наличие или отсутствие статического метода инициализации в классе влияет на значение serialVersionUID, вычисляемое для этого класса по умолчанию. До исправления ошибки при вычислении также проверялся суперкласс на наличие статического инициализатора, если у класса его не было.

Это изменение не влияет на приложения, целевой уровень 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() хранится слишком много данных, то при запуске приложения на устройстве с Android 7.0 ActivityThread.StopInfo выдаст ошибку RuntimeException.
  • Если приложение публикует задачи Runnable в View, а View не прикреплен к окну, система ставит задачу Runnable в очередь с View. Задача Runnable не выполняется, пока View не будет прикреплен к окну. Это изменение устраняет следующие ошибки:
    • Если приложение отправляет сообщение в View из потока, отличного от потока UI целевого окна, Runnable может выполняться в неправильном потоке.
    • Если задача Runnable была опубликована не из потока Looper, приложение может раскрыть задачу Runnable.
  • Если приложение на устройстве с Android 7.0 и разрешением DELETE_PACKAGES пытается удалить пакет, установленный другим приложением, система запрашивает подтверждение пользователя. В этом случае при вызове PackageInstaller.uninstall() приложения должны ожидать статус возврата STATUS_PENDING_USER_ACTION.
  • Поставщик JCA под названием Crypto больше не поддерживается, поскольку его единственный алгоритм SHA1PRNG криптографически слаб. Приложения больше не могут использовать SHA1PRNG для небезопасного получения ключей, поскольку этот поставщик больше не доступен. Дополнительную информацию можно найти в записи блога Security "Crypto" provider deprecated in Android N (Поддержка поставщика Crypto прекращена в Android N).