Ograniczenia dotyczące interfejsów spoza SDK

Począwszy od Androida 9 (poziom interfejsu API 28) platforma określa, z jakich interfejsów spoza pakietu SDK może korzystać aplikacja. Te ograniczenia mają zastosowanie, gdy aplikacja odwołuje się do interfejsu innego niż SDK lub próbuje uzyskać swój nick za pomocą funkcji JNI lub odbicia. Te ograniczenia zostały wprowadzone, aby zwiększyć wygodę użytkowników i deweloperów oraz zmniejszyć ryzyko awarii u użytkowników i deweloperów. Więcej informacji na temat tej decyzji znajdziesz w artykule o zwiększaniu stabilności przez ograniczenie wykorzystania interfejsów innych niż SDK.

Rozróżnić interfejsy SDK i inne niż SDK

Ogólnie rzecz biorąc, publiczne interfejsy SDK to te, które znajdują się w indeksie pakietów platformy Android. Obsługa interfejsów innych niż SDK to szczegół implementacji, który interfejs API pomija, 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 również, że podczas interakcji z klasą za pomocą mechanizmów takich jak refleksja nie należy korzystać z metod ani pól, których nie ma w pakiecie SDK.

Listy interfejsów API spoza pakietu SDK

W każdej wersji Androida dostęp do interfejsów spoza pakietu SDK jest ograniczony. Wiemy, że te ograniczenia mogą wpływać na proces publikowania wersji, dlatego chcemy zapewnić Ci narzędzia do wykrywania korzystania z interfejsów innych niż SDK, możliwość przekazania nam opinii oraz czas na zaplanowanie i dostosowanie się do nowych zasad.

Aby zminimalizować wpływ ograniczeń na proces programowania aplikacji innych niż SDK, podzieliliśmy je na listy, które określają stopień ograniczenia ich użycia w zależności od poziomu interfejsu API, na który mają być kierowane reklamy. Poniższa tabela opisuje każdą z tych list:

Lista Tagi kodu Opis
Lista zablokowanych
  • blocked
  • Wycofane: blacklist
Interfejsów spoza 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 wyświetli błąd.
Zablokowano warunkowo
  • max-target-x
  • Wycofane: greylist-max-x

Począwszy od Androida 9 (poziom interfejsu API 28) każdy poziom interfejsu API ma interfejsy spoza pakietu SDK, które są ograniczone, gdy aplikacja jest kierowana na ten poziom API.

Listy te są oznaczone maksymalnym poziomem interfejsu API (max-target-x), na który aplikacja może kierować reklamy, zanim utraci dostęp do znajdujących się na niej interfejsów spoza pakietu SDK. Na przykład interfejs spoza SDK, który nie został zablokowany w Androidzie Pie, ale teraz jest zablokowany w Androidzie 10, znajduje się na liście max-target-p(greylist-max-p), gdzie „p” oznacza Pie lub Android 9 (poziom API 28).

Jeśli aplikacja próbuje uzyskać dostęp do interfejsu, który jest ograniczony na docelowym poziomie interfejsu API, system działa tak, jakby interfejs API znajdował się na liście zablokowanych.

Nieobsługiwane
  • unsupported
  • Wycofane: greylist
Interfejsy spoza pakietu SDK, które nie mają ograniczeń, a Twoja aplikacja może z nich korzystać. Pamiętaj jednak, że te interfejsy są nieobsługiwane i mogą ulec zmianie bez powiadomienia. Spodziewaj się, że te interfejsy będą warunkowo blokowane w przyszłych wersjach Androida na liście max-target-x.
Pakiet SDK
  • Zarówno public-api, jak i sdk
  • Wycofane: public-api i whitelist
Interfejsy, z których można korzystać bezpłatnie, a teraz obsługiwane w ramach oficjalnie udokumentowanej platformy Androida Package Index.
Testuj interfejsy API
  • test-api
Interfejsy używane do wewnętrznego testowania systemu, takie jak interfejsy API ułatwiające testowanie za pomocą pakietu Compatibility Test Suite (CTS). Testowe interfejsy API nie wchodzą w skład pakietu SDK. Od Androida 11 (poziom interfejsu API 30) testowe interfejsy API są uwzględniane na liście zablokowanych, więc aplikacje nie mogą z nich korzystać niezależnie od docelowego poziomu interfejsu API. Wszystkie testowe interfejsy API nie są obsł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 korzystanie z dowolnych metod lub pól spoza pakietu SDK zawsze wiąże się z dużym ryzykiem uszkodzenia aplikacji. Jeśli aplikacja wymaga interfejsów spoza SDK, warto zaplanować migrację do interfejsów SDK lub innych rozwiązań. Jeśli nie możesz znaleźć alternatywy dla korzystania z interfejsu spoza SDK funkcji w aplikacji, poproś o nowy publiczny interfejs API.

Określ, do której listy należy interfejs

Listy interfejsów innych niż SDK są częścią platformy. W sekcjach poniżej znajdziesz informacje o poszczególnych wersjach Androida.

Android 15 (beta)

W przypadku Androida 15 możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza SDK i odpowiadające im listy:

Plik: hiddenapi-flags.csv

Suma kontrolna SHA-256: 7aa0987aea4b25f5371b7e377c9f37375ada3b7e30465c0e2d910a5b646c10c1

Więcej informacji o zmianach dotyczących list interfejsów API innych niż SDK w Androidzie 15 znajdziesz w artykule Aktualizacje ograniczeń interfejsu innego niż SDK w Androidzie 15.

Android 14

W przypadku Androida 14 (poziom interfejsu API 34) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza SDK i odpowiadające im listy:

Plik: hiddenapi-flags.csv

Suma kontrolna SHA-256: 7e00db074cbe51c51ff4b411f7b48e98692951395c5c17d069c822cc1d0eae0f

Więcej informacji o zmianach dotyczących list interfejsów API spoza pakietu SDK w Androidzie 14 znajdziesz w artykule Aktualizacje ograniczeń interfejsu innego niż SDK w Androidzie 14.

Android 13

W przypadku Androida 13 (poziom interfejsu API 33) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza SDK i odpowiadające im listy:

Plik: hiddenapi-flags.csv

Suma kontrolna SHA-256: 233a277aa8ac475b6df61bffd95665d86aac6eb2ad187b90bf42a98f5f2a11a3

Więcej informacji o zmianach dotyczących list interfejsów API spoza pakietu SDK w Androidzie 13, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są warunkowo zablokowane w Androidzie 13, znajdziesz w tym artykule.

Android 12

W przypadku Androida 12 (poziom interfejsu API 31) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza SDK i odpowiadające im listy:

Plik: hiddenapi-flags.csv

Suma kontrolna SHA-256: 40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761

Więcej informacji o zmianach dotyczących list interfejsów API spoza pakietu SDK w Androidzie 12, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są warunkowo zablokowane w Androidzie 12, znajdziesz w artykule o zmianach w Androidzie 12.

Android 11

W przypadku Androida 11 (poziom interfejsu API 30) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza SDK i odpowiadające im listy:

Plik: hiddenapi-flags.csv

Suma kontrolna SHA-256: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56

Więcej informacji o zmianach dotyczących list interfejsów API spoza pakietu SDK w Androidzie 11, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są zablokowane warunkowo w Androidzie 11, znajdziesz w artykule Wyświetlanie listy zmian w Androidzie 11.

Android 10

W przypadku Androida 10 (poziom interfejsu API 29) możesz pobrać ten plik, który opisuje wszystkie interfejsy spoza SDK i odpowiadające im listy:

Plik: hiddenapi-flags.csv

Suma kontrolna SHA-256: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb

Więcej informacji o zmianach dotyczących list interfejsów API spoza pakietu SDK w Androidzie 10, w tym o sugerowanych publicznych alternatywach dla interfejsów API, które są zablokowane warunkowo w Androidzie 10, znajdziesz w artykule Wyświetlanie listy zmian 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 (są wyświetlane na szarej liście): hiddenapi-light-greylist.txt.

Lista zablokowanych (blacklist) i lista warunkowo zablokowanych interfejsów API (ciemnoszara lista) są odczytywane podczas kompilacji.

Wygeneruj listy z AOSP

Podczas pracy z AOSP możesz wygenerować plik hiddenapi-flags.csv, który będzie zawierał wszystkie interfejsy spoza SDK i odpowiadające im listy. Aby to zrobić, pobierz źródło AOSP i uruchom to polecenie:

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

Znajdziesz ten plik w tej lokalizacji:

out/soong/hiddenapi/hiddenapi-flags.csv

Oczekiwane działanie w przypadku uzyskania dostępu do ograniczonych interfejsów spoza pakietu SDK

W tabeli poniżej znajdziesz opis działania, którego możesz się spodziewać, gdy aplikacja próbuje uzyskać dostęp do interfejsu innego niż SDK, który znajduje się na liście zablokowanych.

Sposoby dostępu Wynik
Instrukcja Dalvika odnosząca się do pola Rzucono: NoSuchFieldError
Instrukcja Dalvika odnosząca się do metody Rzucono: NoSuchMethodError
Odbicie za pomocą obiektów Class.getDeclaredField() lub Class.getField() Rzucono: NoSuchFieldException
Odbicie: Class.getDeclaredMethod(), Class.getMethod() Rzucono: NoSuchMethodException
Odbicie: Class.getDeclaredFields(), Class.getFields() Użytkownicy spoza pakietu SDK, których nie ma w wynikach
Odbicie: Class.getDeclaredMethods(), Class.getMethods() Użytkownicy spoza pakietu SDK, których nie ma w wynikach
JNI z użyciem: env->GetFieldID() Zwrócone: NULL, rzut: NoSuchFieldError
JNI z użyciem: env->GetMethodID() Zwrócone: NULL, rzut: NoSuchMethodError

Testowanie aplikacji pod kątem interfejsów spoza pakietu SDK

Istnieje kilka metod, których możesz użyć do przetestowania interfejsów innych niż SDK w swojej aplikacji.

Testowanie za pomocą aplikacji z możliwością debugowania

Aby przetestować interfejsy spoza SDK, utwórz i uruchom aplikację z możliwością debugowania na urządzeniu lub emulatorze z Androidem 9 (poziom interfejsu API 28) lub nowszym. Sprawdź, czy urządzenie lub emulator, którego używasz, pasują do docelowego poziomu interfejsu API Twojej aplikacji.

W trakcie testów w aplikacji system wyświetla komunikat logu, jeśli aplikacja uzyskuje dostęp do interfejsów spoza pakietu SDK. Możesz przejrzeć komunikaty logu aplikacji, aby znaleźć te informacje:

  • Klasa, nazwa i typ deklaracja (w formacie używanym przez środowisko wykonawcze Androida).
  • Środki dostępu: przez połączenie, za pomocą odczucia lub za pomocą JNI.
  • Lista, do której należy interfejs inny niż SDK.

Za pomocą polecenia adb logcat możesz uzyskać dostęp do tych komunikatów logu, które są widoczne w identyfikatorze PID uruchomionej aplikacji. Wpis w dzienniku może na przykład mieć taką treść:

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

Testowanie z użyciem interfejsu StrictMode API

Możesz też przeprowadzić testy pod kątem interfejsów spoza SDK za pomocą interfejsu API StrictMode. Aby to włączyć, użyj metody detectNonSdkApiUsage. Po włączeniu interfejsu API StrictMode możesz otrzymywać wywołanie zwrotne dla każdego użycia interfejsu innego niż SDK za pomocą interfejsu penaltyListener, gdzie możesz zaimplementować niestandardową obsługę. Obiekt Violation podany w wywołaniu zwrotnym pochodzi z Throwable, a załączony zrzut stosu przedstawia kontekst użycia.

Testowanie za pomocą narzędzia veridex

Możesz też uruchomić na nim narzędzie do analizy statycznej veridex. Narzędzie veridex skanuje całą bazę kodu pliku APK, w tym wszelkie biblioteki zewnętrzne, i zgłasza wszystkie przypadki użycia znalezionych interfejsów spoza SDK.

Ograniczenia narzędzia Veridex:

  • Nie można wykrywać wywołań przez JNI.
  • Może wykrywać tylko podzbiór wywołań.
  • Jego analiza pod kątem nieaktywnych ścieżek kodu ogranicza się do kontroli na poziomie interfejsu API.
  • Można ją uruchamiać tylko na komputerach, które obsługują instrukcje SSE4.2 i POPCNT.

Windows

Natywne pliki binarne Windows nie są udostępniane, ale możesz uruchomić narzędzie veridex w systemie Windows, wykonując pliki binarne dla systemu Linux przy użyciu podsystemu Windows dla systemu Linux (WSL). Zanim wykonasz czynności opisane w tej sekcji, zainstaluj WSL i wybierz Ubuntu jako dystrybucję Linuksa.

Po zainstalowaniu systemu Ubuntu uruchom terminal, a następnie wykonaj te czynności:

  1. Pobierz narzędzie veridex z gotowego repozytorium środowiska wykonawczego Androida.
  2. Wyodrębnij zawartość pliku appcompat.tar.gz.
  3. W wyodrębnionym folderze znajdź plik veridex-linux.zip i rozpakuj go.
  4. Przejdź do rozpakowanego folderu i uruchom to polecenie, gdzie your-app.apk to plik APK, który chcesz przetestować:

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

macOS,

Aby uruchomić narzędzie veridex w systemie macOS, wykonaj te czynności:

  1. Pobierz narzędzie veridex z gotowego repozytorium środowiska wykonawczego Androida.
  2. Wyodrębnij zawartość pliku appcompat.tar.gz.
  3. W wyodrębnionym folderze znajdź plik veridex-mac.zip i rozpakuj go.
  4. Otwórz rozpakowany folder, a następnie uruchom to polecenie, gdzie /path-from-root/your-app.apk to ścieżka do pliku APK, który chcesz przetestować, począwszy od katalogu głównego systemu:

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

Linux

Aby uruchomić narzędzie veridex w systemie Linux, wykonaj te czynności:

  1. Pobierz narzędzie veridex z gotowego repozytorium środowiska wykonawczego Androida.
  2. Wyodrębnij zawartość pliku appcompat.tar.gz.
  3. W wyodrębnionym folderze znajdź plik veridex-linux.zip i rozpakuj go.
  4. Przejdź do rozpakowanego folderu i uruchom to polecenie, gdzie your-app.apk to plik APK, który chcesz przetestować:

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

Testowanie za pomocą narzędzia Lint Studio

Za każdym razem, gdy tworzysz aplikację w Android Studio, narzędzie Lint sprawdza kod pod kątem potencjalnych problemów. Jeśli Twoja aplikacja korzysta z interfejsów innych niż SDK, w zależności od listy tych interfejsów możesz zobaczyć błędy lub ostrzeżenia kompilacji.

Możesz też uruchomić narzędzie lint z poziomu wiersza poleceń lub przeprowadzić inspekcje ręcznie dla określonego projektu, folderu lub pliku.

Testowanie w 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 Twoja aplikacja korzysta z interfejsów innych niż SDK, w raporcie przed opublikowaniem wyświetli się błąd lub ostrzeżenie w zależności od listy tych interfejsów.

Więcej informacji znajdziesz w sekcji dotyczącej zgodności Androida w artykule Używanie raportów przed opublikowaniem do wykrywania problemów.

Poproś o nowy publiczny interfejs API

Jeśli nie możesz znaleźć dla danej funkcji interfejsu innego niż SDK, możesz poprosić o nowy publiczny interfejs API, tworząc żądanie funkcji w naszym narzędziu do śledzenia problemów.

Podczas tworzenia prośby o dodanie funkcji podaj te informacje:

  • Nieobsługiwany interfejs API, którego używasz, wraz z pełnym deskryptorem widocznym w komunikacie logcat Accessing hidden ....
  • Dlaczego musisz używać tych interfejsów API, w tym szczegółowe informacje na temat ogólnych funkcji, do których jest potrzebny interfejs API, a nie tylko szczegółów.
  • Dlaczego powiązane interfejsy API pakietu SDK są niewystarczające do Twoich celów.
  • Jakie inne wypróbowane alternatywy i dlaczego się nie udały?

Podając te informacje w prośbie o dodanie funkcji, zwiększasz prawdopodobieństwo przyznania nowego publicznego interfejsu API.

Inne pytania

W tej sekcji znajdziesz odpowiedzi na inne pytania, które często zadają programiści:

Pytania ogólne

W jaki sposób Google może sprawdzić, czy za pomocą narzędzia do śledzenia problemów uwzględnią potrzeby wszystkich aplikacji?

Początkowe listy aplikacji na Androida 9 (poziom interfejsu API 28) opracowaliśmy na podstawie analizy statycznej aplikacji uzupełnionej za pomocą tych metod:

  • ręczne testowanie najpopularniejszych aplikacji w Google Play i innych,
  • raporty wewnętrzne
  • automatyczne zbieranie danych od użytkowników wewnętrznych
  • raporty podglądu dla programistów
  • dodatkową analizę statyczną, która została zaprojektowana z myślą o zachowaniu ostrożności i uwzględnieniu większej liczby wyników fałszywie pozytywnych

Podczas oceny list w przypadku każdej nowej wersji bierzemy pod uwagę wykorzystanie interfejsu API, a także opinie deweloperów w narzędziu do śledzenia błędów.

Jak umożliwić dostęp do interfejsów spoza pakietu SDK?

Możesz zezwolić na dostęp do interfejsów spoza pakietu SDK na urządzeniach, dla których programujesz, za pomocą poleceń adb, aby zmienić zasady egzekwowania zasad dotyczących interfejsu 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 interfejsu API 29) lub nowszy

Aby włączyć dostęp, użyj tego narzędzia adb

polecenie:

adb shell settings put global hidden_api_policy  1

Aby zresetować zasadę wymuszania interfejsu API do ustawień domyślnych, 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  1
adb shell settings put global hidden_api_policy_p_apps 1

Aby zresetować zasadę wymuszania interfejsu API do ustawień domyślnych, użyj tych poleceń:

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

Liczbę całkowitą w zasadach egzekwowania zasad dotyczących interfejsu API możesz ustawić na jedną z tych wartości:

  • 0. Wyłącz wszystkie wykrywanie interfejsów spoza SDK. Użycie tego ustawienia powoduje wyłączenie wszystkich komunikatów logu dotyczących interfejsu innego niż SDK oraz uniemożliwia testowanie aplikacji za pomocą interfejsu StrictMode API. To ustawienie nie jest zalecane.
  • 1. Włącz dostęp do wszystkich interfejsów spoza SDK, ale drukuj komunikaty dziennika z ostrzeżeniami w przypadku korzystania z interfejsów spoza tego pakietu. To ustawienie umożliwia też testowanie aplikacji za pomocą interfejsu StrictMode API.
  • 2. Nie zezwalaj na używanie interfejsów spoza pakietu SDK, które należą do listy zablokowanych lub są warunkowo zablokowane na docelowym poziomie interfejsu API.

Pytania dotyczące list interfejsu innego niż SDK

Gdzie w obrazie systemu znajdę listy interfejsów API spoza pakietu SDK?

Są one kodowane w polach i bitach flagi dostępu do metody w plikach .dex platformy. W obrazie systemu nie ma osobnego pliku zawierającego 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 (czarnej listy), ale nie mogą usuwać interfejsów z list interfejsów AOSP innych niż SDK. CDD zapobiega takim zmianom, a testy CTS pozwalają upewnić się, że środowisko wykonawcze Androida egzekwuje listę.

Czy w kodzie natywnym są jakieś ograniczenia dotyczące interfejsów innych niż NDK?

Pakiet SDK do Androida zawiera interfejsy Java. Platforma zaczęła ograniczać dostęp do interfejsów innych niż NDK w przypadku natywnego kodu C/C++ na Androidzie 7 (poziom API 26). Więcej informacji znajdziesz w artykule o poprawianiu stabilności z wykorzystaniem ograniczeń dotyczących prywatnych symboli C/C++ na Androidzie N.

Czy jest jakiś plan ograniczenia operacji na plikach dex2oat i DEX?

Nie mamy aktywnych planów ograniczania dostępu do pliku binarnego dex2oat, ale nie zależy nam, aby jego format pliku DEX był stabilny lub publiczny poza elementami, które są określone publicznie w formacie wykonywalnym Dalvik. Zastrzegamy sobie prawo do modyfikowania lub usunięcia w dowolnym momencie pliku dex2oat i nieokreślonych części formatu DEX. Pamiętaj też, że pliki pochodne utworzone przez dex2oat, takie jak ODEX (znane też jako OAT), VDEX i CDEX, są formatami nieokreślonymi.

Co się stanie, jeśli kluczowy zewnętrzny pakiet SDK (np. zaciemniający kod) nie może uniknąć korzystania z interfejsów innych niż SDK, ale czy zapewnia zgodność z przyszłymi wersjami Androida? Czy Android może w tym przypadku zrzec się wymagań dotyczących zgodności?

Nie planujemy zrzekania się wymagań dotyczących zgodności z poszczególnymi pakietami SDK. Deweloper pakietu SDK może zachować zgodność tylko przez interfejsy na nieobsługiwanych (wcześniej szarych) listach. W takim przypadku powinien zacząć planować migrację do interfejsów SDK lub innych rozwiązań, a gdy nie może znaleźć alternatywy dla interfejsu innego niż SDK, powinien poprosić o nowy publiczny interfejs API.

Czy ograniczenia interfejsu spoza SDK mają zastosowanie do wszystkich aplikacji, w tym do aplikacji systemowych i aplikacji własnych, a nie tylko aplikacji innych firm?

Tak, ale wykluczamy aplikacje podpisane kluczem platformy i niektóre aplikacje z obrazem systemu. Pamiętaj, że te wykluczenia dotyczą tylko aplikacji, które są częścią obrazu systemu (lub zaktualizowanych aplikacji z obrazem systemu). Lista jest przeznaczona tylko dla aplikacji tworzonych w ramach prywatnych interfejsów API platformy, a nie interfejsów API pakietu SDK (gdzie LOCAL_PRIVATE_PLATFORM_APIS := true).