Od Androida 9 (poziom API 28) platforma ogranicza interfejsy spoza SDK, z których może korzystać aplikacja. Te ograniczenia obowiązują zawsze, gdy aplikacja odwołuje się do interfejsu innego niż SDK lub próbuje uzyskać jego uchwyt za pomocą odbicia lub JNI. Te ograniczenia zostały wprowadzone, aby poprawić komfort użytkowników i deweloperów oraz zmniejszyć ryzyko awarii i wdrażania awaryjnego. Więcej informacji o tej decyzji znajdziesz w artykule Poprawa stabilności przez ograniczenie użycia interfejsów innych niż 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 innych niż SDK jest szczegółem implementacji, który jest abstrahowany przez interfejs API, więc te interfejsy mogą ulec zmianie bez powiadomienia.
Aby uniknąć awarii i nieoczekiwanych zachowań, 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 odbicie nie należy uzyskiwać dostępu do metod ani pól, które nie są wymienione w pakiecie SDK.
Listy interfejsów API spoza pakietu SDK
Z każdą wersją Androida ograniczana jest liczba interfejsów innych niż SDK. Wiemy, że te ograniczenia mogą wpłynąć na Twój proces publikowania, dlatego chcemy Ci zapewnić narzędzia do wykrywania użycia interfejsów innych niż SDK, możliwość przesłania nam opinii oraz czas na zaplanowanie i dostosowanie się do nowych zasad.
Aby zminimalizować wpływ ograniczeń dotyczących interfejsów spoza SDK na proces programowania, interfejsy spoza SDK 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. Tabela poniżej zawiera opis poszczególnych list:
Lista | Tagi kodu | Opis |
---|---|---|
Lista zablokowanych |
|
Interfejsy spoza SDK, których nie możesz 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 zgłosi błąd. |
Warunkowo zablokowany |
|
Od Androida 9 (poziom API 28) każdy poziom API ma interfejsy spoza 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 na docelowym poziomie interfejsu API, system zachowuje się tak, jakby interfejs API był częścią listy zablokowanych interfejsów. |
Nieobsługiwane |
|
Interfejsy inne niż SDK, które nie są objęte ograniczeniami i których Twoja aplikacja może używać. Pamiętaj jednak, że te interfejsy są nieobsługiwane i mogą ulec zmianie bez powiadomienia. W przyszłych wersjach Androida te interfejsy będą warunkowo blokowane na max-target-x liście. |
Pakiet SDK |
|
Interfejsy, z których można swobodnie korzystać i które są teraz obsługiwane w ramach oficjalnie udokumentowanego frameworka Androida, indeks pakietów. |
Testowanie interfejsów API |
|
Interfejsy używane do testowania systemów wewnętrznych, np. interfejsy API, które ułatwiają testowanie za pomocą pakietu CTS (Compatibility Test Suite). Interfejsy API testów nie są częścią pakietu SDK. Od Androida 11 (poziom API 30) interfejsy API testów są uwzględniane na liście zablokowanych, więc aplikacje nie mogą ich używać niezależnie od docelowego poziomu interfejsu API. Wszystkie testowe interfejsy API są nieobsługiwane i mogą ulec zmianie bez powiadomienia, niezależnie od poziomu interfejsu API platformy. |
Chociaż możesz używać niektórych interfejsów spoza SDK (w zależności od docelowego poziomu interfejsu API aplikacji), korzystanie z dowolnej metody lub pola spoza SDK zawsze wiąże się z wysokim ryzykiem awarii aplikacji. Jeśli Twoja aplikacja korzysta z interfejsów spoza SDK, zacznij planować przejście na interfejsy SDK lub inne rozwiązania. Jeśli nie możesz znaleźć alternatywy dla używania interfejsu innego niż 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 SDK są tworzone w ramach platformy. Informacje o poszczególnych wersjach Androida znajdziesz w sekcjach poniżej.
Android 16
W przypadku Androida 16 (poziom API 36) możesz pobrać ten plik, który zawiera opis wszystkich interfejsów innych niż SDK i odpowiadających im list:
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 zawiera opis wszystkich interfejsów innych niż SDK i odpowiadających im list:
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 Aktualizacje ograniczeń 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 zawiera opis wszystkich interfejsów spoza SDK i odpowiadających im list:
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 zawiera opis wszystkich interfejsów innych niż SDK i odpowiadających im list:
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 sugerowane publiczne interfejsy API jako alternatywy dla interfejsów API warunkowo blokowanych w Androidzie 13, znajdziesz w artykule Zmiany w ograniczeniach dotyczących interfejsów spoza pakietu SDK w Androidzie 13.
Android 12
W przypadku Androida 12 (poziom API 31) możesz pobrać ten plik, który zawiera opis wszystkich interfejsów spoza SDK i odpowiadających im list:
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 sugerowane publiczne alternatywy 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 zawiera opis wszystkich interfejsów innych niż SDK i odpowiadających im list:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56
Więcej informacji o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 11, w tym sugerowane publiczne alternatywy dla interfejsów API, które są warunkowo blokowane w Androidzie 11, znajdziesz w artykule Zmiany na liście w Androidzie 11.
Android 10
W przypadku Androida 10 (poziom API 29) możesz pobrać ten plik, który zawiera opis wszystkich interfejsów innych niż SDK i odpowiadających im list:
Plik: hiddenapi-flags.csv
Suma kontrolna SHA-256:f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb
Więcej informacji o zmianach na liście interfejsów API spoza pakietu SDK w Androidzie 10, w tym sugerowanych publicznych alternatywach dla interfejsów API warunkowo blokowanych w Androidzie 10, znajdziesz w artykule Zmiany na liście w Androidzie 10.
Android 9
W przypadku Androida 9 (poziom 28 interfejsu API) poniższy plik tekstowy zawiera listę interfejsów API spoza pakietu SDK, które nie są ograniczone (znajdują się na szarej liście):hiddenapi-light-greylist.txt
Lista zablokowanych interfejsów API (blacklist
) i lista interfejsów API warunkowo zablokowanych (ciemnoszara lista) są tworzone w czasie kompilacji.
Generowanie list z AOSP
Podczas pracy z AOSP możesz wygenerować plik hiddenapi-flags.csv
, który zawiera wszystkie interfejsy spoza SDK i odpowiadające im listy. Aby to zrobić, pobierz źródło AOSP, a potem uruchom to polecenie:
m out/soong/hiddenapi/hiddenapi-flags.csv
Plik znajdziesz w tej lokalizacji:
out/soong/hiddenapi/hiddenapi-flags.csv
Oczekiwane działanie w przypadku dostępu do interfejsów innych niż SDK objętych ograniczeniami
Tabela poniżej zawiera opis zachowania, którego możesz się spodziewać, jeśli Twoja aplikacja spróbuje uzyskać dostęp do interfejsu innego niż SDK, który znajduje się na liście zablokowanych.
Środki dostępu | Wynik |
---|---|
Instrukcja Dalvik odwołująca się do pola | NoSuchFieldError rzucono |
Instrukcja Dalvik odwołująca się do metody | NoSuchMethodError rzucono |
Odbicie za pomocą Class.getDeclaredField() lub Class.getField() |
NoSuchFieldException rzucono |
Odbicie z użyciem Class.getDeclaredMethod() , Class.getMethod() |
NoSuchMethodException rzucono |
Odbicie z użyciem Class.getDeclaredFields() , Class.getFields() |
Użytkownicy spoza pakietu SDK nie są uwzględniani w wynikach |
Odbicie z użyciem Class.getDeclaredMethods() , Class.getMethods() |
Użytkownicy spoza pakietu SDK nie są uwzględniani w wynikach |
JNI przy użyciu env->GetFieldID() |
NULL zwrócono, NoSuchFieldError wyrzucono |
JNI przy użyciu env->GetMethodID() |
NULL zwrócono, NoSuchMethodError wyrzucono |
Testowanie aplikacji pod kątem interfejsów innych niż SDK
Istnieje kilka metod, za pomocą których możesz sprawdzić, czy w Twojej aplikacji nie ma interfejsów innych niż SDK.
Testowanie za pomocą aplikacji z możliwością debugowania
Interfejsy spoza SDK możesz przetestować, 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, jest zgodny z docelowym poziomem interfejsu API aplikacji.
Podczas testowania aplikacji system wyświetla komunikat w dzienniku, jeśli aplikacja uzyskuje dostęp do określonych interfejsów innych niż SDK. Możesz sprawdzić komunikaty dziennika aplikacji, aby znaleźć te szczegóły:
- Klasa deklarująca, nazwa i typ (w formacie używanym przez środowisko wykonawcze Androida).
- Sposób dostępu: linkowanie, odbicie lub JNI.
- Lista, do której należy interfejs inny niż SDK.
Aby uzyskać dostęp do tych komunikatów logu, kliknij adb logcat
. Pojawią się one pod identyfikatorem PID uruchomionej aplikacji. Przykładowy 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
Interfejsy inne niż SDK możesz też testować za pomocą interfejsu API StrictMode
. Aby to zrobić, użyj metody detectNonSdkApiUsage
. Po włączeniu interfejsu APIStrictMode
możesz otrzymywać wywołanie zwrotne dla każdego użycia interfejsu spoza pakietu SDKStrictMode
za pomocą penaltyListener
, w którym możesz wdrożyć niestandardową obsługę. Obiekt Violation
podany w wywołaniu zwrotnym pochodzi z Throwable
, a dołączony ślad stosu zawiera kontekst użycia.
Testowanie za pomocą narzędzia veridex
Możesz też uruchomić na pliku APK narzędzie do analizy statycznej veridex. Narzędzie veridex skanuje cały kod APK, w tym biblioteki innych firm, i zgłasza wszelkie wykryte użycia interfejsów spoza SDK.
Ograniczenia narzędzia Veridex obejmują:
- Nie może wykrywać wywołań przez JNI.
- Za pomocą refleksji może wykryć tylko podzbiór wywołań.
- Analiza nieaktywnych ścieżek kodu jest ograniczona do sprawdzania poziomu interfejsu API.
- Można go uruchamiać tylko na maszynach obsługujących instrukcje SSE4.2 i POPCNT.
Windows
Natywne pliki binarne systemu Windows nie są udostępniane, ale możesz uruchomić narzędzie veridex w systemie Windows, wykonując pliki binarne systemu Linux za pomocą Podsystemu Windows dla systemu Linux (WSL). Zanim wykonasz czynności opisane w tej sekcji, zainstaluj WSL i wybierz Ubuntu jako dystrybucję Linuksa.
Po zainstalowaniu Ubuntu uruchom terminal Ubuntu i wykonaj te czynności:
- Pobierz narzędzie veridex z repozytorium wstępnie skompilowanych plików środowiska wykonawczego Androida.
- Wyodrębnij zawartość pliku
appcompat.tar.gz
. - W wyodrębnionym folderze znajdź plik
veridex-linux.zip
i go wyodrębnij. Otwórz rozpakowany folder, a następnie 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:
- Pobierz narzędzie veridex z repozytorium wstępnie skompilowanych plików środowiska wykonawczego Androida.
- Wyodrębnij zawartość pliku
appcompat.tar.gz
. - W wyodrębnionym folderze znajdź plik
veridex-mac.zip
i go wyodrębnij. Otwórz rozpakowany folder, a potem uruchom to polecenie, gdzie
/path-from-root/your-app.apk
to ścieżka do pliku APK, który chcesz przetestować, zaczynając 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:
- Pobierz narzędzie veridex z repozytorium wstępnie skompilowanych plików środowiska wykonawczego Androida.
- Wyodrębnij zawartość pliku
appcompat.tar.gz
. - W wyodrębnionym folderze znajdź plik
veridex-linux.zip
i go wyodrębnij. Otwórz rozpakowany folder, a następnie 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 w Androidzie Studio
Za każdym razem, gdy kompilujesz aplikację w Android Studio, narzędzie lint sprawdza kod pod kątem potencjalnych problemów. Jeśli Twoja aplikacja korzysta z interfejsów spoza SDK, możesz zobaczyć błędy lub ostrzeżenia kompilacji w zależności od tego, do której listy należą te interfejsy.
Możesz też uruchomić narzędzie lint z poziomu wiersza poleceń lub ręcznie przeprowadzić inspekcje w określonym projekcie, folderze 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 spoza SDK, w raporcie przed opublikowaniem pojawi się błąd lub ostrzeżenie w zależności od tego, do której listy należą 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 używania interfejsu spoza pakietu SDK w przypadku funkcji w aplikacji, możesz poprosić o nowy publiczny interfejs API, tworząc prośbę o funkcję w naszym narzędziu do śledzenia problemów.
Podczas tworzenia prośby o funkcję podaj te informacje:
- Którego nieobsługiwanego interfejsu API używasz, w tym pełny deskryptor widoczny w
Accessing hidden ...
komunikacie logcat. - Wyjaśnienie, dlaczego musisz używać tych interfejsów API, w tym szczegółowe informacje o funkcji wysokiego poziomu, do której są one niezbędne, a nie tylko szczegóły niskiego poziomu.
- wyjaśnienie, dlaczego powiązane publiczne interfejsy API pakietu SDK są niewystarczające do Twoich celów;
- inne alternatywy, które zostały przez Ciebie wypróbowane, i wyjaśnienie, dlaczego nie przyniosły oczekiwanych rezultatów;
Jeśli podasz te szczegóły w prośbie o nową funkcję, zwiększysz prawdopodobieństwo przyznania dostępu do nowego publicznego interfejsu API.
Inne pytania
W tej sekcji znajdziesz odpowiedzi na inne pytania, które deweloperzy często zadają:
Pytania ogólne
Jak Google może mieć pewność, że za pomocą narzędzia do śledzenia problemów może uwzględnić potrzeby wszystkich aplikacji?
Początkowe listy dla Androida 9 (poziom interfejsu API 28) zostały utworzone na podstawie statycznej analizy aplikacji, która została uzupełniona za pomocą tych metod:
- ręczne testowanie najlepszych aplikacji z Google Play i innych źródeł;
- raporty wewnętrzne,
- automatyczne zbieranie danych od użytkowników wewnętrznych,
- raporty z wersji przedpremierowej dla deweloperów,
- dodatkową analizę statyczną, która została zaprojektowana tak, aby uwzględniać więcej fałszywych alarmów;
Podczas oceny list w przypadku każdej nowej wersji bierzemy pod uwagę wykorzystanie interfejsu API, a także opinie deweloperów zgłaszane w narzędziu do śledzenia problemów.
Jak włączyć dostęp do interfejsów innych niż SDK?
Dostęp do interfejsów spoza SDK na urządzeniach deweloperskich możesz włączyć za pomocą poleceń adb, aby zmienić zasady egzekwowania 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 29 interfejsu API) lub nowszy
Aby włączyć dostęp, użyj tego polecenia adb:
polecenie:
adb shell settings put global hidden_api_policy 1
Aby przywrócić domyślne ustawienia 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 1
adb shell settings put global hidden_api_policy_p_apps 1
Aby zresetować zasady egzekwowania 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
W zasadach egzekwowania interfejsu API możesz ustawić liczbę całkowitą na jedną z tych wartości:
- 0: wyłącza wykrywanie wszystkich interfejsów innych niż SDK. Wyłączenie tego ustawienia spowoduje wyłączenie wszystkich komunikatów dziennika dotyczących użycia interfejsu innego niż SDK i uniemożliwi testowanie aplikacji za pomocą interfejsu
StrictMode
API. Nie zalecamy tego ustawienia. - 1. Włącz dostęp do wszystkich interfejsów innych niż SDK, ale wyświetlaj komunikaty dziennika z ostrzeżeniami o użyciu dowolnego interfejsu innego niż SDK. To ustawienie umożliwia też testowanie aplikacji za pomocą interfejsu
StrictMode
API. - 2. Zabroń używania interfejsów spoza SDK, które znajdują się na liście zablokowanych lub są warunkowo blokowane na docelowym poziomie interfejsu API.
Pytania dotyczące list interfejsów innych niż SDK
Gdzie w obrazie systemu znajdę listy interfejsów API innych niż 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łby 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 blokowanych (czarnej listy), ale nie mogą usuwać interfejsów z list interfejsów API spoza 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 w kodzie natywnym obowiązują jakieś ograniczenia dotyczące interfejsów innych niż NDK?
Pakiet Android SDK zawiera interfejsy Java. Platforma zaczęła ograniczać dostęp do interfejsów spoza NDK w przypadku natywnego kodu C/C++ w Androidzie 7 (poziom 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 dotyczącym prywatnych symboli C/C++ w Androidzie N).
Czy planujesz ograniczyć manipulowanie plikami dex2oat lub DEX?
Nie planujemy obecnie ograniczenia dostępu do pliku binarnego dex2oat, ale nie zamierzamy, aby format pliku DEX był stabilny lub stanowił interfejs publiczny poza częściami, które są publicznie określone w formacie wykonywalnym Dalvik. Zastrzegamy sobie prawo do modyfikowania lub usuwania dex2oat i nieokreślonych części formatu DEX w dowolnym momencie. Pamiętaj też, że pliki pochodne wygenerowane przez dex2oat, takie jak ODEX (znany też jako OAT), VDEX i CDEX, mają nieokreślony format.
Co zrobić, jeśli kluczowy pakiet SDK innej firmy (np. zaciemniacz) nie może uniknąć używania interfejsów spoza SDK, ale zobowiązuje się do zachowania zgodności z przyszłymi wersjami Androida? Czy w takim przypadku Android może odstąpić od wymagań dotyczących zgodności?
Nie planujemy rezygnować z wymagań dotyczących zgodności w przypadku poszczególnych pakietów SDK. Jeśli deweloper pakietu SDK może zachować zgodność tylko przez korzystanie z interfejsów z nieobsługiwanych (wcześniej szarych) list, powinien rozpocząć planowanie migracji do interfejsów pakietu SDK lub innych rozwiązań i poprosić o nowy publiczny interfejs API, gdy nie może znaleźć alternatywy dla użycia interfejsu innego niż SDK.
Czy ograniczenia interfejsu innego niż SDK dotyczą wszystkich aplikacji, w tym systemowych i własnych, a nie tylko aplikacji innych firm?
Tak, ale zwalniamy z tego obowiązku aplikacje podpisane kluczem platformy i niektóre aplikacje 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 na podstawie prywatnych interfejsów API platformy, a nie interfejsów API pakietu SDK (gdzie LOCAL_PRIVATE_PLATFORM_APIS := true
).