Google a introdus restricții în Android 9 pentru care API-urile pot fi accesate de dezvoltatori. Iată cum să ocoliți restricțiile API ascunse.
În 2018, Google a lansat Android Pie. Printre modificările interfeței de utilizare și noile funcții, au existat și unele modificări la nivelul dezvoltatorului. Aceste modificări au inclus noi API-uri, remedieri de erori pentru API-urile existente și, de asemenea restricții privind accesul la API-urile ascunse.
Din fericire, totuși, există modalități de a ocoli aceste restricții. Înainte de a intra în modul de ocolire a restricțiilor, ar trebui să explic puțin despre ce sunt API-urile ascunse, de ce au fost restricționate în primul rând și de ce ați putea dori să le accesați.
API-urile ascunse sunt API-urile din Android pe care dezvoltatorii de aplicații nu le pot vedea în mod normal. Dacă aruncați o privire la codul AOSP, veți vedea o mulțime de clase, variabile și metode care au o @hide
adnotare în interiorul unui bloc de comentarii deasupra lor.
Această adnotare indică instrumentul pe care Google îl folosește la compilarea SDK-ului să excludă elementul de sub acesta. Acest SDK este apoi distribuit dezvoltatorilor în interiorul SDK-urilor descărcate prin Android Studio. Dacă nu utilizați un SDK modificat, Android Studio va crede că oricare dintre aceste elemente ascunse pur și simplu nu există. Dacă încercați să utilizați unul direct, acesta îl va afișa în roșu și va refuza compilarea.
Există o mulțime de motive pentru care un API ar putea fi ascuns. Unele lucruri sunt menite să fie folosite doar de aplicații interne sau de sistem și nu vor funcționa dacă sunt folosite de o aplicație terță parte. Altele sunt experimentale sau instabile și ar putea fi eliminate sau modificate în viitor. Unele sunt chiar doar API-uri la care Google pur și simplu nu vrea să aplice ciclul normal de depreciere dacă sunt vreodată eliminate.
În timp ce SDK-ul standard pentru Android are un lot în ea, uneori nu este suficient. Uneori există ceva ce doriți să faceți și care există deja în Android, dar pur și simplu nu este expus public.
De exemplu, multe dintre aplicațiile pe care le fac, inclusiv SystemUI Tuner și Widgeturi cu ecran de blocare, utilizați o mulțime de API-uri ascunse diferite. SystemUI Tuner trebuie să acceseze unele pentru a urmări, modifica și reseta opțiunile în mod corespunzător. Lockscreen Widgets folosește unele pentru a afișa imaginea de fundal de sub el, printre altele.
Majoritatea dezvoltatorilor nu trebuie să acceseze API-uri ascunse, dar uneori pot fi destul de utile.
Odată cu lansarea Android 9 (Pie), Google a introdus lista neagră a API-urilor ascunse. Nu toate API-urile ascunse au fost incluse și au existat diferite niveluri de liste. API-urile ascunse din lista albă pot fi accesate de oricine. API-urile ascunse din lista gri deschis ar putea fi accesate de orice aplicație, dar ar putea fi inaccesibile în versiunile viitoare de Android. Orice lucru din lista gri închisă poate fi accesat numai de aplicațiile care vizează niveluri API înainte de Pie (adică înainte de nivelul API 28). Accesul la aplicațiile care vizează Pie și mai târziu ar fi refuzat. În cele din urmă, API-urile ascunse de pe lista neagră nu au putut fi accesate de nicio aplicație care nu este de sistem (sau care nu este inclusă pe lista albă), indiferent de API-ul țintă.
Android 10 a schimbat modul în care au fost organizate listele și le-a simplificat ușor, dar ideea a rămas aceeași. Anumite API-uri ascunse puteau fi accesate de aplicații, în timp ce altele erau blocate. Android 11 a consolidat detectarea accesului la blocați un bypass folosit pentru plăcintă și 10.
În toate versiunile Android, de fiecare dată când o aplicație terță parte încearcă să acceseze un API ascuns pe lista neagră, Android va arăta eroarea corespunzătoare „negăsit”.
Există de fapt câteva moduri de a trece de lista neagră a API-urilor ascunse. În funcție de nevoile dvs., puteți alege cele care funcționează pentru toate versiunile Android, cele care funcționează numai pentru Android 9 și 10, cele care utilizează cod nativ C++ și altele care sunt complet bazate pe Java. Există chiar și o soluție numai pentru dezvoltare folosind ADB.
Soluție ADB
Dacă dispozitivul dvs. rulează Android Pie, rulați următoarele două comenzi ADB pentru a activa accesul API ascuns.
adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1
Dacă dispozitivul dvs. rulează Android 10 sau o versiune ulterioară, rulați următoarea comandă ADB pentru a activa accesul API ascuns.
adb shell settings put global hidden_api_policy 1
Pentru a reveni la comportamentul implicit, trebuie doar să înlocuiți put
cu delete
și scoateți 1
.
Evident, aceste comenzi nu sunt tocmai utile pentru o aplicație de producție. Vă pot spune direct că instruirea corectă a utilizatorilor despre cum să folosească ADB este incredibil de dificilă. Dar ele pot fi utile dacă trebuie să actualizați o aplicație veche pentru a respecta noile restricții.
Soluție nativă/JNI
Există două moduri în care puteți ocoli lista neagră API ascunsă folosind JNI în aplicația dvs. Android. Unul funcționează pentru Android 9 și 10, iar celălalt funcționează pentru Android 9 și versiuni ulterioare.
Android 9 și 10
Dacă aveți deja o parte nativă a aplicației dvs., aceasta va fi ușor de implementat. Folosește doar JNI_OnLoad()
funcţie.
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);
...
}
Rețineți că această metodă funcționează numai pe Android 9 și 10.
Android 9 și versiuni ulterioare
Pentru orice versiune de Android, aveți la dispoziție două biblioteci pentru a ocoli restricția API ascunsă: FreeReflection și RestrictionBypass.
Ambele sunt ușor de implementat și de utilizat.
Pentru a implementa FreeReflection, adăugați dependența la build.gradle la nivel de modul.
implementation 'me.weishu: free_reflection: 3.0.1'
Apoi anulați attachBaseContext()
în clasa dvs. de aplicație.
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}
Dacă nu aveți o clasă de aplicație, o puteți adăuga destul de ușor. Creați o nouă clasă care se extinde Application
și apoi indicați-l în AndroidManifest.xml.
Exemplu:
publicclassAppextendsApplication{
...
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}
}
<manifest>
...
...
name=".App">
...
application>
manifest>
Pentru a implementa RestrictionBypass, adăugați depozitul JitPack la build.gradle la nivel de proiect.
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
Apoi adăugați dependența la build.gradle la nivel de modul.
implementation 'com.github.ChickenHook: RestrictionBypass: 2.2'
Si asta e. Această bibliotecă elimină automat restricțiile listei negre.
Soluție Java
Deși soluțiile JNI sunt eficiente, există momente în care s-ar putea să nu doriți să utilizați cod nativ. Dacă nu faci deja lucruri în C++, poate adăuga dimensiuni inutile, împreună cu restricții de platformă, aplicației tale. Din fericire, există modalități de a ocoli lista neagră API ascunsă folosind numai Java.
Android 9 și 10
În Android 9 și 10, puteți folosi ceea ce se poate numi dublă reflexie sau meta-reflectare pentru a ocoli lista neagră API ascunsă. Deoarece sistemul verifică doar ce apelează aplicațiile terțe, dubla reflecție îl face să creadă că sistemul efectuează apeluri API ascunse.
Acest truc poate fi folosit pentru a apela o metodă de a acorda aplicației tale scutiri API ascunse, denumite corect setHiddenApiExemptions()
. Pur și simplu adăugați următorul cod undeva la începutul ciclului de viață al aplicației dvs. (cum ar fi cel al aplicației onCreate()
metoda), și se va ocupa de ocolirea listei negre.
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" } });
Dacă aplicația dvs. este compatibilă cu versiuni de Android mai mici de 9, nu uitați să includeți acest lucru într-o verificare a versiunii.
Android 9 și versiuni ulterioare
Pentru a ocoli lista neagră API ascunsă pe Android 9 și orice versiune ulterioară, puteți utiliza biblioteca LSPosed. Această bibliotecă folosește API-ul nesigur al Java, așa că este puțin probabil să se rupă vreodată.
Pentru a-l implementa, trebuie doar să adăugați dependența la build.gradle la nivel de modul.
implementation 'org.lsposed.hiddenapibypass: hiddenapibypass: 2.0'
Apoi folosiți-l pentru a ocoli lista neagră.
HiddenApiBypass.addHiddenApiExemptions("L");
Dacă aplicația dvs. este compatibilă cu versiuni de Android mai mici de 9, nu uitați să includeți acest lucru într-o verificare a versiunii.
Concluzie și mai multe informații
Există o mulțime de opțiuni pentru a ocoli lista neagră API ascunsă pe Android, indiferent de versiunea platformei pe care o vizați sau pe care o utilizați. Dacă sunteți curios să aflați mai multe despre cum funcționează aceste metode și biblioteci, asigurați-vă că consultați următoarele link-uri.
- My Stack Overflow Întrebări și răspunsuri.
- Biblioteca Hidden API Bypass a LSposed pe GitHub.
- Biblioteca RestrictionBypass a ChickenHook pe GitHub.
- biblioteca FreeReflection a lui tiann pe GitHub.
- Documentația Google privind lista neagră a API-urilor ascunse.