Google indførte begrænsninger i Android 9, for hvilke API'er udviklere kan få adgang til. Sådan omgår du de skjulte API-begrænsninger.
Helt tilbage i 2018 udgav Google Android Pie. Blandt UI-ændringerne og nye funktioner var der også nogle ændringer på udviklersiden. Disse ændringer inkluderede nye API'er, fejlrettelser til eksisterende API'er og også begrænsninger for adgang til skjulte API'er.
Heldigvis er der dog måder at omgå disse begrænsninger på. Før jeg kommer ind på, hvordan man omgår begrænsningerne, bør jeg forklare lidt om, hvad skjulte API'er er, hvorfor de blev begrænset i første omgang, og hvorfor du måske ønsker at få adgang til dem.
Skjulte API'er er de API'er i Android, som appudviklere normalt ikke kan se. Hvis du tager et kig på AOSP's kode, vil du se en hel masse klasser, variabler og metoder, der har en @hide
anmærkning i en kommentarblok over dem.
Denne annotation instruerer, uanset hvilket værktøj Google bruger, når SDK'et kompileres, om at ekskludere varen under den. Det SDK distribueres derefter til udviklere inde i SDK'erne, der er downloadet via Android Studio. Medmindre du bruger en modificeret SDK, vil Android Studio tro, at nogen af disse skjulte elementer bare ikke eksisterer. Hvis du prøver at bruge en direkte, vil den vise den med rødt og nægte at kompilere.
Der er mange grunde til, at en API kan være skjult. Nogle ting er kun beregnet til at blive brugt af interne eller systemapps og vil ikke fungere, hvis de bruges af en tredjepartsapp. Andre er eksperimentelle eller ustabile og kan blive fjernet eller ændret i fremtiden. Nogle er endda bare API'er, som Google bare ikke ønsker at anvende den normale afskrivningscyklus til, hvis de nogensinde bliver fjernet.
Mens standard Android SDK har en masse i det, nogle gange er det ikke nok. Nogle gange er der noget, du vil gøre, som allerede findes i Android, men som bare ikke er offentligt eksponeret.
For eksempel mange af de apps, jeg laver, inklusiv SystemUI Tuner og Låseskærm-widgets, gør brug af en masse forskellige skjulte API'er. SystemUI Tuner skal have adgang til nogle for korrekt at spore, ændre og nulstille muligheder. Lockscreen Widgets bruger nogle til blandt andet at vise tapetet under det.
De fleste udviklere behøver ikke at få adgang til skjulte API'er, men nogle gange kan de være ret nyttige.
Med udgivelsen af Android 9 (Pie) introducerede Google den skjulte API-sortliste. Ikke alle skjulte API var inkluderet, og der var forskellige niveauer af lister. Skjulte API'er på hvidlisten kunne tilgås af alle. Skjulte API'er på lysgrålisten kan tilgås af enhver app, men kan være utilgængelige i fremtidige versioner af Android. Alt på den mørkegrå liste kunne kun tilgås af apps, der målrettede API-niveauer før Pie (dvs. før API-niveau 28). Apps, der er målrettet mod Pie og senere, vil blive nægtet adgang. Endelig kunne skjulte API'er på sortlisten ikke tilgås af nogen ikke-system- (eller ikke-hvidlistet) app, uanset mål-API'en.
Android 10 ændrede, hvordan listerne var organiseret, og forenklede dem lidt, men ideen forblev den samme. Visse skjulte API'er kunne tilgås af apps, mens andre blev blokeret. Android 11 styrket adgangsdetekteringen til blokere en bypass brugt til Pie og 10.
I alle Android-versioner, hver gang en tredjepartsapp forsøger at få adgang til en sortlistet skjult API, vil Android give den relevante "ikke fundet"-fejl.
Der er faktisk en del måder at komme forbi den skjulte API-sortliste. Afhængigt af dine behov kan du vælge dem, der virker til alle Android-versioner, dem, der kun virker til Android 9 og 10, dem, der bruger indbygget C++-kode, og dem, der er fuldt Java-baserede. Der er endda en løsning, der kun er udviklet ved hjælp af ADB.
ADB-løsning
Hvis din enhed kører Android Pie, skal du køre følgende to ADB-kommandoer for at aktivere skjult API-adgang.
adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1
Hvis din enhed kører Android 10 eller nyere, skal du køre følgende ADB-kommando for at aktivere skjult API-adgang.
adb shell settings put global hidden_api_policy 1
For at vende tilbage til standardadfærden skal du bare udskifte put
med delete
og fjern 1
.
Det er klart, at disse kommandoer ikke ligefrem er nyttige for en produktionsapp. Jeg kan fortælle dig på egen hånd, at det er utroligt svært at instruere brugerne korrekt i, hvordan man bruger ADB. Men de kan være nyttige, hvis du skal opdatere en gammel app for at overholde de nye begrænsninger.
Native/JNI-løsning
Der er to måder, du kan omgå den skjulte API-sortliste ved hjælp af JNI i din Android-app. Den ene fungerer til Android 9 og 10, og den anden fungerer til Android 9 og nyere.
Android 9 og 10
Hvis du allerede har en indbygget del af din app, vil dette være nemt at implementere. Brug blot JNI_OnLoad()
fungere.
static art:: Runtime* runtime = nullptr;
extern "C"jint JNI_OnLoad(JavaVM *vm, void *reserved){
...
runtime = reinterpret_cast<: javavmext>(vm)->GetRuntime();
runtime->SetHiddenApiEnforcementPolicy(art:: hiddenapi:: EnforcementPolicy:: kNoChecks);
...
}
Vær opmærksom på, at denne metode kun virker på Android 9 og 10.
Android 9 og nyere
For enhver version af Android har du dit valg af to biblioteker til at omgå den skjulte API-begrænsning: FreeReflection og RestrictionBypass.
Begge er nemme at implementere og bruge.
At implementere FreeReflection, tilføj afhængigheden til din build.gradle på modulniveau.
implementation 'me.weishu: free_reflection: 3.0.1'
Tilsidesæt derefter attachBaseContext()
i din ansøgningsklasse.
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}
Hvis du ikke har en applikationsklasse, kan du tilføje den ret nemt. Opret en ny klasse, der strækker sig Application
og peg derefter på det i din AndroidManifest.xml.
Eksempel:
publicclassAppextendsApplication{
...
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}
}
<manifest>
...
...
name=".App">
...
application>
manifest>
At implementere RestrictionBypass, føj JitPack-lageret til din build.gradle på projektniveau.
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
Tilføj derefter afhængigheden til din build.gradle på modulniveau.
implementation 'com.github.ChickenHook: RestrictionBypass: 2.2'
Og det er det. Dette bibliotek fjerner automatisk blackliste-begrænsningerne.
Java-løsning
Selvom JNI-løsningerne er effektive, er der tidspunkter, hvor du måske ikke ønsker at bruge indbygget kode. Hvis du ikke allerede gør ting i C++, kan det tilføje unødvendig størrelse sammen med platformsbegrænsninger til din app. Heldigvis er der måder at omgå den skjulte API-sortliste ved kun at bruge Java.
Android 9 og 10
I Android 9 og 10 kan du bruge det, man kan kalde dobbelt-refleksion eller meta-refleksion til at omgå den skjulte API-sortliste. Fordi systemet kun tjekker, hvad tredjepartsapps kalder, narrer dobbeltreflektion det til at tro, at systemet foretager de skjulte API-kald.
Dette trick kan bruges til at kalde en metode til at give din app skjulte API-undtagelser, passende navngivet setHiddenApiExemptions()
. Du skal blot tilføje følgende kode et sted tidligt i din apps livscyklus (såsom applikationens onCreate()
metode), og den håndterer omgåelse af sortlisten.
Method forName = Class.class.getDeclaredMethod("forName", String.class);
Method getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);Class vmRuntimeClass = (Class) forName.invoke(null, "dalvik.system.VMRuntime");
Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null);
Method setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", newClass[] { String[].class} );
Object vmRuntime = getRuntime.invoke(null);
setHiddenApiExemptions.invoke(vmRuntime, newString[][] { newString[] { "L" } });
Hvis din app er kompatibel med versioner af Android lavere end 9, så husk at pakke dette ind i et versionstjek.
Android 9 og nyere
For at omgå den skjulte API-sortliste på Android 9 og enhver senere version kan du bruge LSPoseds bibliotek. Dette bibliotek bruger Javas Unsafe API, så det er usandsynligt, at det nogensinde går i stykker.
For at implementere det, skal du blot tilføje afhængigheden til din build.gradle på modulniveau.
implementation 'org.lsposed.hiddenapibypass: hiddenapibypass: 2.0'
Brug den derefter til at omgå sortlisten.
HiddenApiBypass.addHiddenApiExemptions("L");
Hvis din app er kompatibel med versioner af Android lavere end 9, så husk at pakke dette ind i et versionstjek.
Konklusion og mere info
Der er masser af muligheder for at omgå den skjulte API-sortliste på Android, uanset hvilken platformsversion du målretter mod eller bruger. Hvis du er nysgerrig efter at lære mere om, hvordan disse metoder og biblioteker fungerer, skal du sørge for at tjekke følgende links.
- My Stack Overflow Q&A.
- LSposeds Hidden API Bypass-bibliotek på GitHub.
- ChickenHooks RestrictionBypass-bibliotek på GitHub.
- tianns FreeReflection-bibliotek på GitHub.
- Googles dokumentation på den skjulte API-sortliste.