Ограничения на интерфейсы, отличные от SDK

Начиная с Android 9 (уровень API 28), платформа ограничивает интерфейсы, не относящиеся к SDK, которые может использовать ваше приложение. Эти ограничения применяются всякий раз, когда приложение ссылается на интерфейс, отличный от SDK, или пытается получить его дескриптор с помощью отражения или JNI. Эти ограничения были введены, чтобы помочь улучшить работу пользователей и разработчиков и снизить риски сбоев для пользователей и экстренного развертывания для разработчиков. Дополнительные сведения об этом решении см. в разделе Улучшение стабильности за счет сокращения использования интерфейсов, отличных от SDK .

Различие между интерфейсами SDK и не-SDK

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

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

Списки API, не входящих в SDK

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

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

Список Теги кода Описание
Черный список
  • blocked
  • Устарело: blacklist
Интерфейсы, не относящиеся к SDK, которые вы не можете использовать независимо от целевого уровня API вашего приложения. Если ваше приложение попытается получить доступ к одному из этих интерфейсов, система выдаст ошибку .
Условно заблокировано
  • max-target-x
  • Устарело: greylist-max-x

Начиная с Android 9 (уровень API 28), каждый уровень API имеет интерфейсы, отличные от SDK, которые ограничены, когда приложение нацелено на этот уровень API.

Эти списки помечены максимальным уровнем API ( max-target-x ), на который приложение может ориентироваться, прежде чем приложение больше не сможет получить доступ к интерфейсам, не относящимся к SDK, в этом списке. Например, интерфейс без SDK, который не был заблокирован в Android Pie, но теперь заблокирован в Android 10, является частью списка max-target-p ( greylist-max-p ), где «p» означает Pie или Android 9. (уровень API 28).

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

Не поддерживается
  • unsupported
  • Устарело: greylist
Интерфейсы, не относящиеся к SDK, которые не имеют ограничений и могут использоваться вашим приложением. Однако обратите внимание, что эти интерфейсы не поддерживаются и могут быть изменены без предварительного уведомления. Ожидайте, что эти интерфейсы будут условно заблокированы в будущих версиях Android в списке max-target-x .
SDK
  • И public-api , и sdk
  • Устарело: как public-api , так и whitelist
Интерфейсы, которые можно свободно использовать и которые теперь поддерживаются как часть официально документированного индекса пакетов платформы Android.
Тестовые API
  • test-api
Интерфейсы, используемые для внутреннего тестирования системы, например API-интерфейсы, упрощающие тестирование с помощью набора тестов совместимости (CTS). Тестовые API не являются частью SDK. Начиная с Android 11 (уровень API 30) , тестовые API включаются в черный список, поэтому приложениям не разрешается использовать их независимо от целевого уровня API. Все тестовые API не поддерживаются и могут быть изменены без предварительного уведомления независимо от уровня API платформы.

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

Определить, к какому списку принадлежит интерфейс

Списки интерфейсов, отличных от SDK, создаются как часть платформы. Дополнительные сведения о каждой версии Android см. в следующих разделах.

Андроид 15

Для Android 15 (уровень API 35) вы можете скачать следующий файл, описывающий все интерфейсы, не входящие в SDK, и их соответствующие списки:

Файл: hiddenapi-flags.csv

Контрольная сумма SHA-256: 40134e205e58922a708c453726b279a296e6a1f34a988abd90cec0f3432ea5a9

Дополнительные сведения об изменениях в списке API, не входящих в SDK, в Android 15 см. в разделе Обновления ограничений интерфейса, не входящих в SDK, в Android 15 .

Андроид 14

Для Android 14 (уровень API 34) вы можете скачать следующий файл, описывающий все интерфейсы, не входящие в SDK, и их соответствующие списки:

Файл: hiddenapi-flags.csv

Контрольная сумма SHA-256: 7e00db074cbe51c51ff4b411f7b48e98692951395c5c17d069c822cc1d0eae0f

Дополнительные сведения об изменениях в списке API, не входящих в SDK, в Android 14 см. в разделе Обновления ограничений интерфейса, не входящих в SDK, в Android 14 .

Андроид 13

Для Android 13 (уровень API 33) вы можете скачать следующий файл, описывающий все интерфейсы, не входящие в SDK, и их соответствующие списки:

Файл: hiddenapi-flags.csv

Контрольная сумма SHA-256: 233a277aa8ac475b6df61bffd95665d86aac6eb2ad187b90bf42a98f5f2a11a3

Чтобы узнать больше об изменениях в списке API, не входящих в SDK, в Android 13, включая предлагаемые общедоступные альтернативы API для API, которые условно заблокированы в Android 13, см. раздел Обновления ограничений интерфейса, не входящих в SDK, в Android 13 .

Андроид 12

Для Android 12 (уровень API 31) вы можете скачать следующий файл, описывающий все интерфейсы, не входящие в SDK, и их соответствующие списки:

Файл: hiddenapi-flags.csv

Контрольная сумма SHA-256: 40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761

Чтобы узнать больше об изменениях в списке API, не входящих в SDK, в Android 12, включая предлагаемые общедоступные альтернативы API для API, которые условно заблокированы в Android 12, см. раздел Изменения списка для Android 12 .

Андроид 11

Для Android 11 (уровень API 30) вы можете скачать следующий файл, описывающий все интерфейсы, не входящие в SDK, и их соответствующие списки:

Файл: hiddenapi-flags.csv

Контрольная сумма SHA-256: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56

Чтобы узнать больше об изменениях в списке API, не входящих в SDK, в Android 11, включая предлагаемые общедоступные альтернативы API для API, которые условно заблокированы в Android 11, см. раздел Изменения списка для Android 11 .

Андроид 10

Для Android 10 (уровень API 29) вы можете скачать следующий файл, описывающий все интерфейсы, не входящие в SDK, и их соответствующие списки:

Файл: hiddenapi-flags.csv

Контрольная сумма SHA-256: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb

Чтобы узнать больше об изменениях в списке API, не входящих в SDK, в Android 10, включая предлагаемые общедоступные альтернативы API для API, которые условно заблокированы в Android 10, см. раздел Изменения списка для Android 10 .

Андроид 9

Для Android 9 (уровень API 28) следующий текстовый файл содержит список API-интерфейсов, не входящих в SDK, которые не ограничены (внесены в серый список): hiddenapi-light-greylist.txt .

Черный список ( blacklist ) и список условно заблокированных API (темно-серый список) создаются во время сборки.

Генерировать списки из AOSP

При работе с AOSP вы можете создать файл hiddenapi-flags.csv , содержащий все интерфейсы, не входящие в SDK, и соответствующие им списки. Для этого загрузите исходный код AOSP и затем выполните следующую команду:

m out/soong/hiddenapi/hiddenapi-flags.csv

Затем вы сможете найти файл в следующем месте:

out/soong/hiddenapi/hiddenapi-flags.csv

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

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

Средства доступа Результат
Инструкция Dalvik, ссылающаяся на поле Выброшена ошибка NoSuchFieldError .
Инструкция Dalvik, ссылающаяся на метод Выброшена NoSuchMethodError .
Отражение с использованием Class.getDeclaredField() или Class.getField() Выброшено исключение NoSuchFieldException
Отражение с использованием Class.getDeclaredMethod() , Class.getMethod() Выброшено исключение NoSuchMethodException
Отражение с использованием Class.getDeclaredFields() , Class.getFields() Не члены SDK не в результатах
Отражение с использованием Class.getDeclaredMethods() , Class.getMethods() Не члены SDK не в результатах
JNI с использованием env->GetFieldID() Возвращается NULL , выдается NoSuchFieldError .
JNI с использованием env->GetMethodID() Возвращается NULL , выдается NoSuchMethodError .

Проверьте свое приложение на наличие интерфейсов, отличных от SDK.

Существует несколько методов, которые вы можете использовать для проверки интерфейсов, отличных от SDK, в вашем приложении.

Тестирование с помощью отлаживаемого приложения

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

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

  • Объявляющий класс, имя и тип (в формате, который используется средой выполнения Android).
  • Средства доступа: либо связывание, либо использование отражения, либо использование JNI.
  • К какому списку принадлежит интерфейс, отличный от SDK.

Вы можете использовать adb logcat для доступа к этим сообщениям журнала, которые отображаются под PID работающего приложения. Например, запись в журнале может выглядеть следующим образом:

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)

Тестирование с использованием StrictMode API

Вы также можете протестировать интерфейсы, отличные от SDK, с помощью API StrictMode . Чтобы включить это, используйте detectNonSdkApiUsage . После включения API StrictMode вы можете получать обратный вызов для каждого использования интерфейса, отличного от SDK, с помощью penaltyListener , где вы можете реализовать пользовательскую обработку. Объект Violation , предоставленный в обратном вызове, является производным от Throwable , а вложенная трассировка стека предоставляет контекст использования.

Протестируйте с помощью инструмента veridex

Вы также можете запустить инструмент статического анализа veridex в своем APK. Инструмент veridex сканирует всю кодовую базу APK, включая любые сторонние библиотеки, и сообщает о любом обнаруженном использовании интерфейсов, отличных от SDK.

Ограничения инструмента veridex включают следующее:

  • Он не может обнаружить вызовы через JNI.
  • Он может обнаружить только подмножество вызовов посредством отражения.
  • Его анализ неактивных путей кода ограничивается проверками на уровне API.
  • Его можно запускать только на машинах, поддерживающих инструкции SSE4.2 и POPCNT.

Окна

Собственные двоичные файлы Windows не предоставляются, но вы можете запустить инструмент veridex в Windows, запустив двоичные файлы Linux с помощью подсистемы Windows для Linux (WSL). Прежде чем выполнять действия, описанные в этом разделе, установите WSL и выберите Ubuntu в качестве дистрибутива Linux.

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

  1. Загрузите инструмент veridex из репозитория готовых сборок среды выполнения Android.
  2. Извлеките содержимое файла appcompat.tar.gz .
  3. В извлеченной папке найдите файл veridex-linux.zip и распакуйте его.
  4. Перейдите в разархивированную папку и выполните следующую команду, где your-app.apk — это APK, который вы хотите протестировать:

    ./appcompat.sh --dex-file=your-app.apk
    

macOS

Чтобы запустить инструмент veridex в macOS, выполните следующие действия:

  1. Загрузите инструмент veridex из репозитория готовых сборок среды выполнения Android.
  2. Извлеките содержимое файла appcompat.tar.gz .
  3. В извлеченной папке найдите файл veridex-mac.zip и извлеките его.
  4. Перейдите в разархивированную папку и выполните следующую команду, где /path-from-root/your-app.apk — это путь к APK, который вы хотите протестировать, начиная с корневого каталога вашей системы:

    ./appcompat.sh --dex-file=/path-from-root/your-app.apk
    

Линукс

Чтобы запустить инструмент veridex в Linux, выполните следующие действия:

  1. Загрузите инструмент veridex из репозитория готовых сборок среды выполнения Android.
  2. Извлеките содержимое файла appcompat.tar.gz .
  3. В извлеченной папке найдите файл veridex-linux.zip и распакуйте его.
  4. Перейдите в разархивированную папку и выполните следующую команду, где your-app.apk — это APK, который вы хотите протестировать:

    ./appcompat.sh --dex-file=your-app.apk
    

Протестируйте с помощью инструмента Android Studio lint.

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

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

Тестирование с помощью Play Console

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

Дополнительную информацию см. в разделе «Совместимость Android» статьи «Использование отчетов о тестировании для выявления проблем» .

Запросить новый общедоступный API

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

При создании запроса на функцию предоставьте следующую информацию:

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

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

Другие вопросы

В этом разделе приведены некоторые ответы на другие вопросы, которые часто задают разработчики:

Общие вопросы

Как Google может быть уверен, что сможет отслеживать потребности всех приложений с помощью системы отслеживания ошибок?

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

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

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

Как я могу включить доступ к интерфейсам, отличным от SDK?

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

Android 10 (уровень API 29) или выше

Чтобы включить доступ, используйте следующий adb

команда:

adb shell settings put global hidden_api_policy  1

Чтобы сбросить политику применения API к настройкам по умолчанию, используйте следующую команду:

adb shell settings delete global hidden_api_policy
Android 9 (уровень API 28)

Чтобы включить доступ, используйте следующие команды adb:

adb shell settings put global hidden_api_policy_pre_p_apps  1
adb shell settings put global hidden_api_policy_p_apps 1

Чтобы сбросить политику применения API к настройкам по умолчанию, используйте следующие команды:

adb shell settings delete global hidden_api_policy_pre_p_apps
adb shell settings delete global hidden_api_policy_p_apps

В политике принудительного применения API можно установить одно из следующих значений:

  • 0: отключить все обнаружения интерфейсов, отличных от SDK. Использование этого параметра отключает все сообщения журнала об использовании интерфейса, отличного от SDK, и не позволяет вам тестировать приложение с помощью StrictMode API . Эта настройка не рекомендуется.
  • 1: разрешить доступ ко всем интерфейсам, не относящимся к SDK, но печатать сообщения журнала с предупреждениями для любого использования интерфейса, не относящегося к SDK. Использование этого параметра также позволяет протестировать ваше приложение с помощью StrictMode API .
  • 2: Запретить использование интерфейсов, отличных от SDK, которые входят в черный список или условно заблокированы для вашего целевого уровня API .

Вопросы о списках интерфейсов, отличных от SDK

Где я могу найти списки API, не входящих в SDK, в образе системы?

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

Одинаковы ли списки API, не входящих в SDK, на разных OEM-устройствах с одинаковыми версиями Android?

OEM-производители могут добавлять свои собственные интерфейсы в черный список (черный список), но не могут удалять интерфейсы из списков API AOSP, не входящих в SDK. CDD предотвращает такие изменения, а тесты CTS гарантируют, что среда выполнения Android соблюдает этот список.

Есть ли какие-либо ограничения на интерфейсы, отличные от NDK, в собственном коде?

Android SDK включает интерфейсы Java. Платформа начала ограничивать доступ к интерфейсам, отличным от NDK, для собственного кода C/C++ в Android 7 (уровень API 26). Дополнительные сведения см. в разделе Повышение стабильности с помощью частных ограничений символов C/C++ в Android N.

Есть ли какой-либо план по ограничению манипуляций с файлами dex2oat или DEX?

У нас нет активных планов по ограничению доступа к двоичному файлу dex2oat, но мы не хотим, чтобы формат файла DEX был стабильным или общедоступным интерфейсом за пределами частей, которые публично указаны в формате исполняемого файла Dalvik . Мы оставляем за собой право изменять или удалять dex2oat и неуказанные части формата DEX в любое время. Также обратите внимание, что производные файлы, созданные dex2oat, такие как ODEX (также известный как OAT), VDEX и CDEX, представляют собой неуказанные форматы.

Что, если важный сторонний SDK (например, обфускатор) не сможет избежать использования интерфейсов, отличных от SDK, но обязуется поддерживать совместимость с будущими версиями Android? Может ли Android в этом случае отказаться от требований совместимости?

У нас нет планов отказываться от требований совместимости для каждого SDK. Если разработчик SDK может поддерживать совместимость только с помощью интерфейсов из неподдерживаемых (ранее серых) списков, ему следует начать планировать переход на интерфейсы SDK или другие альтернативы и запрашивать новый общедоступный API всякий раз, когда он не может найти альтернативу использованию неподдерживаемых интерфейсов SDK. -Интерфейс SDK.

Применяются ли ограничения интерфейса, не связанные с SDK, ко всем приложениям, включая системные и сторонние приложения, а не только к сторонним приложениям?

Да, однако мы освобождаем от ответственности приложения, подписанные с помощью ключа платформы, и некоторые приложения из образа системы. Обратите внимание, что эти исключения применяются только к приложениям, которые являются частью образа системы (или обновленных приложений образа системы). Список предназначен только для приложений, созданных на основе API частной платформы, а не API SDK (где LOCAL_PRIVATE_PLATFORM_APIS := true ).