Od Androida 9 (poziom API 28) platforma ogranicza interfejsy spoza pakietu SDK, których może używać aplikacja. Te ograniczenia obowiązują zawsze, gdy aplikacja odwołuje się do interfejsu spoza pakietu SDK lub próbuje uzyskać jego uchwyt za pomocą refleksji lub JNI. Wprowadziliśmy te ograniczenia, aby poprawić wrażenia użytkowników i deweloperów oraz zmniejszyć ryzyko awarii u użytkowników i konieczności wdrażania awaryjnego u deweloperów. Więcej informacji o tej decyzji znajdziesz w artykule Improving Stability by Reducing Usage of non-SDK Interfaces (Poprawa stabilności dzięki ograniczeniu korzystania z interfejsów spoza pakietu SDK).
Rozróżnianie interfejsów SDK i innych niż SDK
Ogólnie rzecz biorąc, publiczne interfejsy SDK to te, które są udokumentowane w indeksie pakietów platformy Androida. Obsługa interfejsów spoza pakietu SDK to szczegół implementacji, który jest ukryty przez interfejs API, więc te interfejsy mogą ulec zmianie bez powiadomienia.
Aby uniknąć awarii i nieoczekiwanego działania, aplikacje powinny używać tylko oficjalnie udokumentowanych części klas w pakiecie SDK. Oznacza to też, że nie należy uzyskiwać dostępu do metod ani pól, które nie są wymienione w pakiecie SDK, gdy wchodzisz w interakcję z klasą za pomocą mechanizmów takich jak refleksja.
Listy interfejsów API spoza pakietu SDK
W każdej wersji Androida ograniczane są dodatkowe interfejsy spoza pakietu SDK. Wiemy, że te ograniczenia mogą wpłynąć na proces publikowania aplikacji, dlatego chcemy mieć pewność, że masz narzędzia do wykrywania użycia interfejsów innych niż SDK, możliwość przekazania nam opinii oraz czas na zaplanowanie i wprowadzenie zmian zgodnie z nowymi zasadami.
Aby zminimalizować wpływ ograniczeń dotyczących interfejsów innych niż SDK na proces programowania, interfejsy te są podzielone na listy, które określają, jak ściśle ograniczone jest ich użycie, w zależności od docelowego poziomu interfejsu API. W tabeli poniżej opisano każdą z tych list:
| Lista | Tagi kodu | Opis |
|---|---|---|
| Lista zablokowanych |
|
Interfejsy spoza pakietu SDK, których nie można używać niezależnie od docelowego poziomu interfejsu API aplikacji. Jeśli aplikacja spróbuje uzyskać dostęp do jednego z tych interfejsów, system wygeneruje błąd. |
| Blokowanie warunkowe |
|
Począwszy od Androida 9 (poziom API 28), każdy poziom API ma interfejsy inne niż SDK, które są ograniczone, gdy aplikacja jest kierowana na ten poziom API. Listy te są oznaczone maksymalnym poziomem interfejsu API ( Jeśli aplikacja próbuje uzyskać dostęp do interfejsu, który jest ograniczony dla docelowego poziomu interfejsu API, system zachowuje się tak, jakby interfejs API był częścią listy zablokowanych. |
| Nieobsługiwany |
|
Interfejsy inne niż SDK, które nie są ograniczone i mogą być używane przez aplikację. Pamiętaj jednak, że te interfejsy są nieobsługiwane i mogą ulec zmianie bez powiadomienia. Te interfejsy mogą być warunkowo blokowane w przyszłych wersjach Androida na liście max-target-x. |
| SDK |
|
Interfejsy, których można swobodnie używać i które są teraz obsługiwane w ramach oficjalnie udokumentowanego indeksu pakietów platformy Android. |
| Testowanie interfejsów API |
|
Interfejsy używane do testowania systemu wewnętrznego, takie jak interfejsy API, które ułatwiają testowanie za pomocą pakietu Compatibility Test Suite (CTS). Interfejsy API do testowania nie są częścią pakietu SDK. Od Androida 11 (poziom API 30) testowe interfejsy API są uwzględniane na liście zablokowanych, więc aplikacje nie mogą ich używać niezależnie od docelowego poziomu interfejsu API. Wszystkie interfejsy API do testowania są nieobsługiwane i mogą ulec zmianie bez powiadomienia, niezależnie od poziomu interfejsu API platformy. |
Możesz używać niektórych interfejsów spoza pakietu SDK (w zależności od docelowego poziomu interfejsu API aplikacji), ale użycie dowolnej metody lub pola spoza pakietu SDK zawsze wiąże się z dużym ryzykiem uszkodzenia aplikacji. Jeśli Twoja aplikacja korzysta z interfejsów spoza pakietu SDK, zacznij planować migrację do interfejsów pakietu SDK lub innych rozwiązań. Jeśli nie możesz znaleźć alternatywy dla interfejsu spoza pakietu SDK w przypadku funkcji w aplikacji, poproś o nowy publiczny interfejs API.
Określanie, do której listy należy interfejs
Listy interfejsów spoza pakietu SDK są tworzone w ramach platformy. Informacje o poszczególnych wersjach Androida znajdziesz w sekcjach poniżej.
Android 16
W przypadku Androida 16 (poziom interfejsu API 36) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:
9102af02fe6ab68b92464bdff5e5b09f3bd62c65d1130aaf85d3296f17d38074
Więcej informacji o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 16 znajdziesz w artykule Aktualizacje ograniczeń interfejsów spoza pakietu SDK w Androidzie 16.
Android 15
W przypadku Androida 15 (poziom API 35) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:
40134e205e58922a708c453726b279a296e6a1f34a988abd90cec0f3432ea5a9
Więcej informacji o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 15 znajdziesz w artykule Zmiany w ograniczeniach interfejsów spoza pakietu SDK w Androidzie 15.
Android 14
W przypadku Androida 14 (API na poziomie 34) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:
7e00db074cbe51c51ff4b411f7b48e98692951395c5c17d069c822cc1d0eae0f
Więcej informacji o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 14 znajdziesz w artykule Aktualizacje ograniczeń interfejsów spoza pakietu SDK w Androidzie 14.
Android 13
W przypadku Androida 13 (API na poziomie 33) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:
233a277aa8ac475b6df61bffd95665d86aac6eb2ad187b90bf42a98f5f2a11a3
Więcej informacji o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 13, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są warunkowo blokowane w Androidzie 13, znajdziesz w artykule o zmianach w ograniczeniach interfejsów spoza pakietu SDK w Androidzie 13.
Android 12
W przypadku Androida 12 (poziom API 31) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:
40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761
Więcej informacji o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 12, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są warunkowo blokowane w Androidzie 12, znajdziesz w artykule Zmiany na liście w Androidzie 12.
Android 11
W przypadku Androida 11 (poziom API 30) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:
a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56
Aby dowiedzieć się więcej o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 11, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są warunkowo blokowane w Androidzie 11, przeczytaj artykuł o zmianach na liście w Androidzie 11.
Android 10
W przypadku Androida 10 (interfejs API na poziomie 29) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:
f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb
Aby dowiedzieć się więcej o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 10, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są warunkowo blokowane w Androidzie 10, przeczytaj artykuł Zmiany na liście w Androidzie 10.
Android 9
W przypadku Androida 9 (poziom interfejsu API 28) ten plik tekstowy zawiera listę interfejsów API spoza pakietu SDK, które nie są objęte ograniczeniami (znajdują się na szarej liście): hiddenapi-light-greylist.txt.
Lista zablokowanych (blacklist) i lista warunkowo zablokowanych interfejsów API (ciemnoszara lista) są tworzone podczas kompilacji.
Generowanie list z AOSP
Podczas pracy z AOSP możesz wygenerować plik hiddenapi-flags.csv, który zawiera wszystkie interfejsy spoza pakietu SDK i odpowiadające im listy. Aby to zrobić, pobierz źródło AOSP, a następnie uruchom to polecenie:
m out/soong/hiddenapi/hiddenapi-flags.csv
Plik znajdziesz w tej lokalizacji:
out/soong/hiddenapi/hiddenapi-flags.csv
Oczekiwane zachowanie w przypadku dostępu do ograniczonych interfejsów innych niż SDK
Tabela poniżej opisuje zachowanie, którego możesz się spodziewać, jeśli Twoja aplikacja spróbuje uzyskać dostęp do interfejsu spoza pakietu SDK, który znajduje się na liście zablokowanych.
| Sposób dostępu | Wynik |
|---|---|
| Instrukcja Dalvik odwołująca się do pola | Rzucono: NoSuchFieldError |
| Instrukcja Dalvik odwołująca się do metody | Rzucono: NoSuchMethodError |
Odbicie za pomocą Class.getDeclaredField() lub Class.getField() |
Rzucono: NoSuchFieldException |
Odbicie przy użyciu: Class.getDeclaredMethod(), Class.getMethod() |
Rzucono: NoSuchMethodException |
Odbicie przy użyciu: Class.getDeclaredFields(), Class.getFields() |
Brak w wynikach członków spoza pakietu SDK |
Odbicie przy użyciu: Class.getDeclaredMethods(), Class.getMethods() |
Brak w wynikach członków spoza pakietu SDK |
JNI z użyciem env->GetFieldID() |
Zwrócono: NULL, zgłoszono: NoSuchFieldError |
JNI z użyciem env->GetMethodID() |
Zwrócono: NULL, rzucono: NoSuchMethodError |
Testowanie aplikacji pod kątem interfejsów innych niż SDK
Istnieje kilka metod, których możesz użyć do przetestowania interfejsów spoza pakietu SDK w aplikacji.
Testowanie za pomocą aplikacji z możliwością debugowania
Możesz przetestować interfejsy inne niż SDK, tworząc i uruchamiając aplikację z możliwością debugowania na urządzeniu lub emulatorze z Androidem 9 (poziom API 28) lub nowszym. Upewnij się, że urządzenie lub emulator, którego używasz, odpowiada docelowemu poziomowi interfejsu API aplikacji.
Podczas testowania aplikacji system wyświetla komunikat logu, jeśli aplikacja uzyskuje dostęp do niektórych interfejsów spoza pakietu SDK. Możesz sprawdzić komunikaty logu aplikacji, aby znaleźć te informacje:
- klasę deklarującą, nazwę i typ (w formacie używanym przez środowisko wykonawcze Androida);
- Sposób dostępu: linkowanie, użycie refleksji lub JNI.
- Lista, do której należy interfejs niebędący częścią pakietu SDK.
Aby uzyskać dostęp do tych komunikatów logu, które pojawiają się pod identyfikatorem PID uruchomionej aplikacji, możesz użyć adb logcat. Na przykład wpis w logu może wyglądać tak:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
Testowanie za pomocą interfejsu StrictMode API
Możesz też przetestować interfejsy inne niż SDK za pomocą interfejsu API StrictMode. Aby to zrobić, użyj metody detectNonSdkApiUsage. Po włączeniu interfejsu API StrictMode możesz otrzymywać wywołania zwrotne przy każdym użyciu interfejsu spoza pakietu SDK, korzystając z penaltyListener, gdzie możesz wdrożyć niestandardową obsługę. Obiekt Violation podany w wywołaniu zwrotnym pochodzi z Throwable, a dołączony zrzut stosu zawiera kontekst użycia.
Testowanie za pomocą narzędzia lint w Android Studio
Za każdym razem, gdy tworzysz aplikację w Android Studio, narzędzie Lint sprawdza kod pod kątem potencjalnych problemów. Jeśli aplikacja używa interfejsów spoza pakietu SDK, mogą pojawić się błędy lub ostrzeżenia dotyczące kompilacji, w zależności od tego, na której liście znajdują się te interfejsy.
Możesz też uruchomić narzędzie lint z wiersza poleceń lub ręcznie przeprowadzić inspekcje w konkretnym projekcie, folderze lub pliku.
Testowanie za pomocą Konsoli Play
Gdy prześlesz aplikację na ścieżkę testów w Konsoli Play, zostanie ona automatycznie przetestowana pod kątem potencjalnych problemów i wygenerowany zostanie raport przed opublikowaniem. Jeśli aplikacja używa interfejsów spoza pakietu SDK, w raporcie przed opublikowaniem wyświetli się błąd lub ostrzeżenie, w zależności od tego, na której liście znajdują się te interfejsy.
Więcej informacji znajdziesz w sekcji Zgodność z Androidem w artykule Używanie raportów przed opublikowaniem do identyfikowania problemów.
Prośba o nowy publiczny interfejs API
Jeśli nie możesz znaleźć alternatywy dla interfejsu spoza pakietu SDK w przypadku funkcji w aplikacji, możesz poprosić o nowy publiczny interfejs API, tworząc prośbę o dodanie funkcji w naszym narzędziu do śledzenia błędów.
Podczas tworzenia prośby o dodanie funkcji podaj te informacje:
- Którego nieobsługiwanego interfejsu API używasz (podaj pełny deskryptor widoczny w komunikacie logcat
Accessing hidden ...). - Dlaczego musisz używać tych interfejsów API, w tym szczegółowe informacje o funkcji wysokiego poziomu, do której interfejs API jest niezbędny, a nie tylko szczegóły niskiego poziomu.
- dlaczego powiązane publiczne interfejsy API pakietu SDK są niewystarczające do Twoich celów.
- inne wypróbowane rozwiązania i powody, dla których się nie sprawdziły.
Podanie tych informacji w prośbie o dodanie funkcji zwiększa prawdopodobieństwo, że nowy publiczny interfejs API zostanie udostępniony.
Inne pytania
W tej sekcji znajdziesz odpowiedzi na inne pytania, które deweloperzy często zadają:
Pytania ogólne
How can Google be sure they can capture the needs of all apps through the issuetracker?
Początkowe listy dla Androida 9 (poziom interfejsu API 28) utworzyliśmy na podstawie analizy statycznej aplikacji, którą uzupełniliśmy za pomocą tych metod:
- ręczne testowanie najpopularniejszych aplikacji ze Sklepu Play i spoza niego,
- raporty wewnętrzne
- automatyczne zbieranie danych od użytkowników wewnętrznych,
- raporty z wersji przedpremierowej dla programistów
- dodatkową analizę statyczną, która została zaprojektowana tak, aby uwzględniać więcej wyników fałszywie dodatnich.
Podczas oceny list pod kątem każdej nowej wersji bierzemy pod uwagę wykorzystanie interfejsu API oraz opinie deweloperów przekazywane za pomocą narzędzia Issue Tracker.
Jak mogę włączyć dostęp do interfejsów innych niż SDK?
Możesz włączyć dostęp do interfejsów innych niż pakiet SDK na urządzeniach deweloperskich, używając poleceń narzędzia adb do zmiany procesu egzekwowania zasad interfejsów API. Używane polecenia różnią się w zależności od poziomu interfejsu API. Te polecenia nie wymagają urządzenia z dostępem do roota.
- Android 10 (poziom 29 interfejsu API) lub nowszy
Aby włączyć dostęp, użyj tego polecenia adb:
command:
adb shell settings put global hidden_api_policy 1
Aby przywrócić ustawienia domyślne zasad egzekwowania interfejsu API, użyj tego polecenia:
adb shell settings delete global hidden_api_policy
- Android 9 (poziom 28 interfejsu API)
Aby włączyć dostęp, użyj tych poleceń adb:
adb shell settings put global hidden_api_policy_pre_p_apps 1adb shell settings put global hidden_api_policy_p_apps 1Aby przywrócić domyślne ustawienia zasad egzekwowania interfejsu API, użyj tych poleceń:
adb shell settings delete global hidden_api_policy_pre_p_appsadb shell settings delete global hidden_api_policy_p_apps
W procesie egzekwowania zasad interfejsu API możesz ustawić liczbę całkowitą na jedną z tych wartości:
- 0: wyłącz wykrywanie wszystkich interfejsów innych niż SDK. Użycie tego ustawienia wyłącza wszystkie komunikaty logu dotyczące korzystania z interfejsów innych niż SDK i uniemożliwia testowanie aplikacji za pomocą interfejsu API
StrictMode. Nie zalecamy tego ustawienia. - 1: włącz dostęp do wszystkich interfejsów spoza pakietu SDK, ale wyświetlaj komunikaty logu z ostrzeżeniami o użyciu interfejsu spoza pakietu SDK. To ustawienie umożliwia też testowanie aplikacji za pomocą interfejsu API
StrictMode. - 2: zabraniaj używania interfejsów innych niż SDK, które znajdują się na liście zablokowanych lub są warunkowo blokowane na docelowym poziomie interfejsu API.
Pytania dotyczące list interfejsów spoza pakietu SDK
Gdzie w obrazie systemu znajdę listy interfejsów API spoza pakietu SDK?
Są one zakodowane w bitach flag dostępu do pól i metod w plikach dex platformy. W obrazie systemu nie ma osobnego pliku, który zawiera te listy.
Czy listy interfejsów API spoza pakietu SDK są takie same na różnych urządzeniach OEM z tymi samymi wersjami Androida?
Producenci OEM mogą dodawać własne interfejsy do listy zablokowanych, ale nie mogą usuwać interfejsów z list interfejsów API innych niż SDK w AOSP. Dokument CDD zapobiega takim zmianom, a testy CTS zapewniają, że środowisko wykonawcze Androida egzekwuje listę.
Pytania dotyczące zgodności powiązanych aplikacji
Czy istnieją jakieś ograniczenia dotyczące interfejsów innych niż NDK w kodzie natywnym?
Pakiet Android SDK zawiera interfejsy Java. Platforma zaczęła ograniczać dostęp do interfejsów innych niż NDK w przypadku natywnego kodu C/C++ w Androidzie 7 (poziom interfejsu API 26). Więcej informacji znajdziesz w artykule Improving Stability with Private C/C++ Symbol Restrictions in Android N (Poprawa stabilności dzięki ograniczeniom prywatnych symboli C/C++ w Androidzie N).
Czy planujecie ograniczyć manipulowanie plikami dex2oat lub DEX?
Nie planujemy obecnie ograniczać dostępu do pliku binarnego dex2oat, ale nie zamierzamy dbać o stabilność formatu pliku DEX ani o to, aby był on interfejsem publicznym, poza częściami, które są publicznie określone w formacie Dalvik Executable. Zastrzegamy sobie prawo do modyfikowania lub usuwania dex2oat i nieokreślonych części formatu DEX w dowolnym momencie. Pamiętaj też, że pliki pochodne generowane przez dex2oat, takie jak ODEX (znany też jako OAT), VDEX i CDEX, są nieokreślonymi formatami.
Co zrobić, jeśli kluczowy pakiet SDK innej firmy (np. zaciemniacz) nie może uniknąć używania interfejsów spoza pakietu SDK, ale zobowiązuje się do zachowania zgodności z przyszłymi wersjami Androida? Czy w tym przypadku Android może odstąpić od wymagań dotyczących zgodności?
Nie planujemy odstępować od wymagań dotyczących zgodności w przypadku poszczególnych pakietów SDK. Jeśli deweloper pakietu SDK może zachować zgodność tylko przez poleganie na interfejsach z nieobsługiwanych list (dawniej szarych), powinien zacząć planować migrację do interfejsów SDK lub innych alternatyw i poprosić o nowy publiczny interfejs API, gdy nie może znaleźć alternatywy dla interfejsu innego niż SDK.
Czy ograniczenia dotyczące interfejsów innych niż SDK dotyczą wszystkich aplikacji, w tym aplikacji systemowych i własnych, a nie tylko aplikacji innych firm?
Tak, ale nie dotyczy to aplikacji podpisanych kluczem platformy i niektórych aplikacji z obrazu systemu. Pamiętaj, że te wyjątki dotyczą tylko aplikacji, które są częścią obrazu systemu (lub zaktualizowanych aplikacji obrazu systemu). Lista jest przeznaczona tylko dla aplikacji, które są tworzone przy użyciu interfejsów API platformy prywatnej, a nie interfejsów API pakietu SDK (gdzie LOCAL_PRIVATE_PLATFORM_APIS := true).