Ограничения для интерфейсов, не относящихся к SDK

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

Различия между интерфейсами с SDK и без него

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

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

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

С каждым выпуском Android ограничивается доступ к дополнительным интерфейсам, не относящимся к 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, упрощающие тестирование с помощью Compatibility Test Suite (CTS). Тестовые API не входят в SDK. Начиная с Android 11 (уровень API 30), тестовые API включены в черный список, поэтому приложения не могут использовать их независимо от целевого уровня API. Все тестовые API не поддерживаются и могут быть изменены без уведомления, независимо от уровня API платформы.

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

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

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

Android 16

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

Файл: hiddenapi-flags.csv

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

Подробнее об изменениях в списке API, не входящих в SDK, в Android 16…

Android 15

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

Файл: hiddenapi-flags.csv

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

Подробнее об изменениях в списке API, не входящих в SDK, в Android 15…

Android 14

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

Файл: hiddenapi-flags.csv

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

Подробнее об изменениях в списке API, не относящихся к SDK, в Android 14…

Android 13

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

Файл: hiddenapi-flags.csv

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

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

Android 12

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

Файл: hiddenapi-flags.csv

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

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

Android 11

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

Файл: hiddenapi-flags.csv

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

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

Android 10

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

Файл: hiddenapi-flags.csv

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

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

Android 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 Runtime).
  • Способ доступа: связывание, рефлексия или 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, а вложенная трассировка стека предоставляет контекст использования.

Тестирование с помощью инструмента lint в Android Studio

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

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

Тестирование в Play Console

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

Подробную информацию вы найдете в разделе "Совместимость с Android" статьи Как выявить проблемы с помощью отчета о тестировании.

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

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

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

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

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

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

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

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

Как Google может быть уверен, что сможет зафиксировать потребности всех приложений через Issue Tracker?

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

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

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

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

Вы можете разрешить доступ к интерфейсам, не относящимся к SDK, на устройствах для разработки, используя команды adb для изменения принципов контроля за соблюдением правил API. Команды, которые вы используете, различаются в зависимости от уровня API. Для выполнения этих команд не требуется устройство с настроенным root-доступом.

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, и вы не сможете тестировать приложение с помощью API StrictMode. Мы не рекомендуем использовать этот параметр.
  • 1 – разрешить доступ ко всем интерфейсам, не относящимся к SDK, но выводить сообщения в журнале с предупреждениями об использовании любых интерфейсов, не относящихся к SDK. Этот параметр также позволяет протестировать приложение с помощью StrictMode API.
  • 2 – запретить использование интерфейсов, не относящихся к SDK, которые занесены в черный список или условно заблокированы для вашего целевого уровня API.

Вопросы о списках интерфейсов, не входящих в SDK

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

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

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

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

Есть ли ограничения на использование интерфейсов, не относящихся к NDK, в нативном коде?

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

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

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

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

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

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

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