Начиная с Android 9 (уровень API 28), платформа ограничивает использование вашим приложением интерфейсов, не относящихся к SDK. Эти ограничения применяются всякий раз, когда приложение ссылается на интерфейс, не относящийся к SDK, или пытается получить его дескриптор с помощью рефлексии или JNI. Эти ограничения были введены для улучшения пользовательского и разработческого опыта, а также для снижения рисков сбоев для пользователей и экстренного развертывания для разработчиков. Для получения дополнительной информации об этом решении см. раздел «Повышение стабильности за счет сокращения использования интерфейсов, не относящихся к SDK» .
Различайте интерфейсы, использующие SDK, и интерфейсы, не использующие SDK.
В общем, общедоступными интерфейсами SDK считаются те, которые описаны в индексе пакетов фреймворка Android. Обработка интерфейсов, не относящихся к SDK, является деталью реализации, которую API абстрагирует, поэтому эти интерфейсы могут изменяться без предварительного уведомления.
Во избежание сбоев и непредвиденного поведения приложениям следует использовать только официально документированные части классов из SDK. Это также означает, что при взаимодействии с классом с помощью таких механизмов, как рефлексия, не следует обращаться к методам или полям, не указанным в SDK.
Списки API, не относящихся к SDK
С каждым новым релизом Android вводятся ограничения на использование дополнительных интерфейсов, не относящихся к SDK. Мы понимаем, что эти ограничения могут повлиять на ваш рабочий процесс выпуска, и хотим убедиться, что у вас есть инструменты для обнаружения использования интерфейсов, не относящихся к SDK, возможность оставить нам отзыв и время для планирования и адаптации к новым правилам.
Чтобы минимизировать влияние ограничений, не связанных с SDK, на ваш рабочий процесс разработки, интерфейсы, не относящиеся к SDK, разделены на списки, определяющие степень ограничения их использования в зависимости от целевого уровня API. В следующей таблице описан каждый из этих списков:
| Список | Кодовые метки | Описание |
|---|---|---|
| Черный список |
| Интерфейсы, не относящиеся к SDK, которые нельзя использовать независимо от целевого уровня API вашего приложения. Если ваше приложение попытается получить доступ к одному из таких интерфейсов, система выдаст ошибку . |
| Условно заблокировано |
| Начиная с Android 9 (уровень API 28), каждый уровень API имеет интерфейсы, не относящиеся к SDK, которые ограничены, если приложение ориентировано на этот уровень API. Эти списки помечены максимальным уровнем API ( Если ваше приложение попытается получить доступ к интерфейсу, доступ к которому ограничен для целевого уровня API, система будет вести себя так, как если бы этот API был включен в черный список . |
| Неподдерживаемый |
| Интерфейсы, не относящиеся к SDK, которые не имеют ограничений и могут использоваться вашим приложением. Однако обратите внимание, что эти интерфейсы не поддерживаются и могут быть изменены без предварительного уведомления. Ожидайте, что в будущих версиях Android эти интерфейсы будут условно заблокированы в списке max-target-x . |
| SDK |
| Интерфейсы, которые можно свободно использовать и которые теперь поддерживаются в рамках официально документированного фреймворка Android — Package Index . |
| Тестирование API |
| Интерфейсы, используемые для внутреннего тестирования системы, такие как API, облегчающие тестирование с помощью набора тестов совместимости (CTS). Тестовые API не являются частью SDK. Начиная с Android 11 (уровень API 30) , тестовые API включены в черный список, поэтому приложениям не разрешается использовать их независимо от целевого уровня API. Все тестовые API не поддерживаются и могут быть изменены без предварительного уведомления, независимо от уровня API платформы. |
Хотя вы можете использовать некоторые интерфейсы, не относящиеся к SDK (в зависимости от целевого уровня API вашего приложения), использование любого метода или поля, не относящегося к SDK, всегда сопряжено с высоким риском поломки вашего приложения. Если ваше приложение зависит от интерфейсов, не относящихся к SDK, вам следует начать планировать миграцию на интерфейсы SDK или другие альтернативы. Если вы не можете найти альтернативу использованию интерфейса, не относящегося к SDK, для какой-либо функции в вашем приложении, вам следует запросить новый публичный API .
Определите, к какому списку относится интерфейс.
Списки интерфейсов, не входящих в состав SDK, формируются как часть платформы. Информацию о каждом выпуске Android см. в следующих разделах.
Android 16
Для Android 16 (уровень API 36) вы можете загрузить следующий файл, в котором описаны все интерфейсы, не входящие в SDK, и соответствующие им списки:
Файл: hiddenapi-flags.csv
Контрольная сумма SHA-256: 9102af02fe6ab68b92464bdff5e5b09f3bd62c65d1130aaf85d3296f17d38074
Чтобы узнать больше об изменениях в списке API, не относящихся к SDK, в Android 16, см. раздел «Обновления ограничений интерфейса, не относящегося к SDK, в Android 16» .
Android 15
Для Android 15 (уровень API 35) вы можете загрузить следующий файл, в котором описаны все интерфейсы, не входящие в SDK, и соответствующие им списки:
Файл: hiddenapi-flags.csv
Контрольная сумма SHA-256: 40134e205e58922a708c453726b279a296e6a1f34a988abd90cec0f3432ea5a9
Чтобы узнать больше об изменениях в списке API, не относящихся к SDK, в Android 15, см. раздел «Обновления ограничений интерфейса, не относящегося к SDK, в Android 15» .
Android 14
Для Android 14 (уровень API 34) вы можете загрузить следующий файл, в котором описаны все интерфейсы, не входящие в SDK, и соответствующие им списки:
Файл: hiddenapi-flags.csv
Контрольная сумма SHA-256: 7e00db074cbe51c51ff4b411f7b48e98692951395c5c17d069c822cc1d0eae0f
Чтобы узнать больше об изменениях в списке API, не относящихся к SDK, в Android 14, см. раздел «Обновления ограничений интерфейса, не относящегося к SDK, в Android 14» .
Android 13
Для Android 13 (уровень API 33) вы можете загрузить следующий файл, в котором описаны все интерфейсы, не входящие в SDK, и соответствующие им списки:
Файл: hiddenapi-flags.csv
Контрольная сумма SHA-256: 233a277aa8ac475b6df61bffd95665d86aac6eb2ad187b90bf42a98f5f2a11a3
Чтобы узнать больше об изменениях в списке API, не относящихся к SDK, в Android 13, включая предлагаемые альтернативы общедоступным API для 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, см. раздел «Изменения в списке API для Android 12» .
Android 11
Для Android 11 (уровень API 30) вы можете загрузить следующий файл, в котором описаны все интерфейсы, не входящие в SDK, и соответствующие им списки:
Файл: hiddenapi-flags.csv
Контрольная сумма SHA-256: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56
Чтобы узнать больше об изменениях в списке API, не входящих в SDK, в Android 11, включая предлагаемые альтернативы общедоступным API для API, которые условно заблокированы в Android 11, см. раздел «Изменения в списке API для Android 11» .
Android 10
Для Android 10 (уровень API 29) вы можете загрузить следующий файл, в котором описаны все интерфейсы, не входящие в SDK, и соответствующие им списки:
Файл: hiddenapi-flags.csv
Контрольная сумма SHA-256: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb
Чтобы узнать больше об изменениях в списке API, не входящих в SDK, в Android 10, включая предлагаемые альтернативы общедоступным API для API, которые условно заблокированы в Android 10, см. раздел «Изменения в списке API для Android 10» .
Android 9
Для Android 9 (уровень API 28) следующий текстовый файл содержит список API, не входящих в SDK, которые не ограничены (занесены в серый список): hiddenapi-light-greylist.txt .
Черный список ( blacklist ) и список API, заблокированных при определенных условиях (darkgrey list), формируются на этапе сборки.
Создание списков из AOSP
При работе с AOSP можно сгенерировать файл hiddenapi-flags.csv , содержащий все интерфейсы, не входящие в SDK, и соответствующие им списки. Для этого загрузите исходный код AOSP , а затем выполните следующую команду:
m out/soong/hiddenapi/hiddenapi-flags.csv
Затем вы сможете найти файл в следующем месте:
out/soong/hiddenapi/hiddenapi-flags.csv
Ожидаемое поведение при доступе к ограниченным интерфейсам, не относящимся к SDK.
В таблице ниже описано поведение, которое вы можете ожидать, если ваше приложение попытается получить доступ к интерфейсу, не входящему в SDK и входящему в черный список.
| Средства доступа | Результат |
|---|---|
| Инструкция Дальвика, ссылающаяся на поле | Выброшено исключение NoSuchFieldError |
| Инструкция Дальвика, ссылающаяся на метод. | Выброшено исключение 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.
Для доступа к этим сообщениям журнала, отображаемым по PID запущенного приложения, можно использовать adb logcat . Например, запись в журнале может выглядеть следующим образом:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
Протестируйте, используя API StrictMode.
Вы также можете проверять интерфейсы, не относящиеся к SDK, используя API StrictMode . Для этого используйте метод detectNonSdkApiUsage . После включения API StrictMode вы можете получать обратный вызов для каждого использования интерфейса, не относящегося к SDK, используя penaltyListener , где вы можете реализовать собственную обработку. Объект Violation , предоставляемый в обратном вызове, наследуется от Throwable , а прилагаемый трассировочный стек предоставляет контекст использования.
Протестируйте с помощью инструмента проверки кода (lint) в Android Studio.
При каждой сборке приложения в Android Studio инструмент линтинга проверяет ваш код на наличие потенциальных проблем. Если ваше приложение использует интерфейсы, не относящиеся к SDK, вы можете увидеть ошибки сборки или предупреждения, в зависимости от того, к какому списку относятся эти интерфейсы.
Вы также можете запустить инструмент проверки кода из командной строки или выполнить проверку вручную для конкретного проекта, папки или файла.
Проверьте работу с помощью консоли Play.
Когда вы загружаете свое приложение в тестовую среду в Play Console, оно автоматически тестируется на наличие потенциальных проблем, и генерируется отчет перед запуском. Если ваше приложение использует интерфейсы, отличные от SDK, в отчете перед запуском отображается ошибка или предупреждение, в зависимости от того, к какому списку относятся эти интерфейсы.
Для получения дополнительной информации см. раздел «Совместимость с Android» в документе «Использование отчетов перед запуском для выявления проблем» .
Запросить новый публичный API
Если вы не можете найти альтернативу использованию интерфейса, отличного от SDK, для какой-либо функции в вашем приложении, вы можете запросить новый публичный API, создав запрос на добавление функции в нашем трекере проблем.
При создании запроса на добавление новой функции укажите следующую информацию:
- Укажите, какой неподдерживаемый API вы используете, включая полный дескриптор, указанный в сообщении logcat "
Accessing hidden .... - Почему вам необходимо использовать эти API, включая подробности о высокоуровневых функциях, для которых необходим API, а не только о низкоуровневых деталях.
- Почему любые связанные с ними общедоступные API SDK недостаточны для ваших целей.
- Какие еще альтернативные варианты вы пробовали, и почему они не сработали?
Предоставляя эти сведения в своем запросе на добавление функции, вы повышаете вероятность того, что новый публичный API будет одобрен.
Другие вопросы
В этом разделе представлены ответы на некоторые часто задаваемые разработчиками вопросы:
Общие вопросы
Как Google может быть уверен, что сможет учесть потребности всех приложений с помощью системы отслеживания проблем?
Первоначальные списки для Android 9 (уровень API 28) были составлены на основе статического анализа приложений, дополненного следующими методами:
- ручное тестирование лучших приложений из Play Store и других платформ
- внутренние отчеты
- автоматический сбор данных от внутренних пользователей
- отчеты о предварительном просмотре для разработчиков
- дополнительный статический анализ, разработанный с целью консервативного включения большего количества ложных срабатываний
При оценке списков для каждого нового релиза мы учитываем использование 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 1adb shell settings put global hidden_api_policy_p_apps 1Чтобы сбросить политику принудительного применения API до настроек по умолчанию, используйте следующие команды:
adb shell settings delete global hidden_api_policy_pre_p_appsadb shell settings delete global hidden_api_policy_p_apps
В политике принудительного применения API вы можете установить целочисленное значение, равное одному из следующих:
- 0: Отключить обнаружение интерфейсов, не относящихся к SDK. Использование этой настройки отключает все сообщения в журнале об использовании интерфейсов, не относящихся к SDK, и не позволяет тестировать приложение с помощью API
StrictMode. Использование этой настройки не рекомендуется. - 1: Разрешить доступ ко всем интерфейсам, не входящим в SDK, но выводить в лог сообщения с предупреждениями при использовании любых интерфейсов, не входящих в SDK. Использование этой настройки также позволяет тестировать ваше приложение с помощью API
StrictMode. - 2: Запретите использование интерфейсов, не относящихся к SDK, которые включены в черный список или условно заблокированы для целевого уровня API .
Вопросы о списках интерфейсов, не относящихся к SDK.
Где в образе системы можно найти списки API, не относящихся к SDK?
Они закодированы в битах флагов доступа к полю и методу в файлах dex платформы. В образе системы нет отдельного файла, содержащего эти списки.
Списки API, не относящихся к SDK, одинаковы на устройствах разных производителей с одинаковыми версиями Android?
Производители оборудования могут добавлять свои собственные интерфейсы в черный список, но не могут удалять интерфейсы из списков API AOSP, не относящихся к SDK. CDD предотвращает такие изменения, а тесты CTS гарантируют, что среда выполнения Android соблюдает этот список.
Вопросы о совместимости связанных приложений
Существуют ли какие-либо ограничения на использование интерфейсов, не относящихся к NDK, в нативном коде?
В состав Android SDK входят Java-интерфейсы. В Android 7 (уровень API 26) платформа начала ограничивать доступ к интерфейсам, не входящим в NDK, для нативного кода C/C++. Для получения дополнительной информации см. раздел «Повышение стабильности с помощью ограничений на использование частных символов 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, на все приложения, включая системные и собственные, а не только на сторонние?
Да, однако мы исключаем из списка приложения, подписанные ключом платформы, и некоторые приложения, созданные на основе образа системы. Обратите внимание, что эти исключения применяются только к приложениям, которые являются частью образа системы (или обновленным приложениям, созданным на основе образа системы). Список предназначен только для приложений, которые собираются с использованием частных API платформы, а не API SDK (где LOCAL_PRIVATE_PLATFORM_APIS := true ).