Come bypassare la lista nera delle API nascoste su Android 9+

Google ha introdotto restrizioni in Android 9 sulle quali gli sviluppatori possono accedere alle API. Ecco come aggirare le restrizioni API nascoste.

Nel lontano 2018, Google ha rilasciato Android Pie. Tra le modifiche all'interfaccia utente e le nuove funzionalità, sono state apportate anche alcune modifiche da parte degli sviluppatori. Tali modifiche includevano nuove API, correzioni di bug per le API esistenti e anche restrizioni sull'accesso alle API nascoste.

Fortunatamente, però, ci sono modi per aggirare queste restrizioni. Prima di spiegare come aggirare le restrizioni, dovrei spiegare un po' cosa sono le API nascoste, perché sono state limitate e perché potresti voler accedervi.

Le API nascoste sono le API in Android che gli sviluppatori di app normalmente non possono vedere. Se dai un'occhiata al codice di AOSP, vedrai un sacco di classi, variabili e metodi che hanno un @hide annotazione all'interno di un blocco di commenti sopra di loro.

Questa annotazione indica a qualsiasi strumento utilizzato da Google durante la compilazione dell'SDK di escludere l'elemento al di sotto di esso. L'SDK viene quindi distribuito agli sviluppatori all'interno degli SDK scaricati tramite Android Studio. A meno che non utilizzi un SDK modificato, Android Studio penserà che nessuno di questi elementi nascosti semplicemente non esista. Se provi a usarne uno direttamente, lo mostrerà in rosso e si rifiuterà di compilare.

Esistono molti motivi per cui un'API potrebbe essere nascosta. Alcune cose sono pensate per essere utilizzate solo da app interne o di sistema e non funzioneranno se utilizzate da un'app di terze parti. Altri sono sperimentali o instabili e potrebbero essere rimossi o modificati in futuro. Alcuni sono addirittura semplicemente API a cui Google non vuole applicare il normale ciclo di deprecazione se mai venissero rimossi.

Mentre l'SDK Android standard ha un file quantità in esso, a volte non è sufficiente. A volte c'è qualcosa che vuoi fare che esiste già in Android, ma non è esposto pubblicamente.

Ad esempio, molte delle app che realizzo, incluso Sintonizzatore SystemUI E Widget della schermata di blocco, utilizza una serie di diverse API nascoste. SystemUI Tuner deve accedere ad alcuni per monitorare, modificare e ripristinare correttamente le opzioni. I widget Lockscreen ne utilizzano alcuni per mostrare lo sfondo sottostante, tra le altre cose.

La maggior parte degli sviluppatori non ha bisogno di accedere alle API nascoste, ma a volte possono essere piuttosto utili.

Con il rilascio di Android 9 (Pie), Google ha introdotto la lista nera delle API nascoste. Non tutte le API nascoste erano incluse ed esistevano diversi livelli di elenchi. Chiunque può accedere alle API nascoste nella whitelist. È possibile accedere alle API nascoste nella light greylist da qualsiasi app, ma potrebbero essere inaccessibili nelle versioni future di Android. Tutto ciò che si trova nella dark-greylist era accessibile solo da app destinate a livelli API precedenti a Pie (ovvero prima del livello API 28). Alle app destinate a Pie e versioni successive verrebbe negato l'accesso. Infine, non è possibile accedere alle API nascoste nella lista nera da alcuna app non di sistema (o non inclusa nella lista bianca), indipendentemente dall'API di destinazione.

Android 10 ha cambiato il modo in cui erano organizzati gli elenchi e li ha semplificati leggermente, ma l'idea è rimasta la stessa. Alcune API nascoste potevano essere accessibili dalle app mentre altre venivano bloccate. Androide 11 rafforzato il rilevamento degli accessi A bloccare una tangenziale utilizzato per Pie e 10.

In tutte le versioni di Android, ogni volta che un'app di terze parti tenta di accedere a un'API nascosta nella lista nera, Android genererà l'errore appropriato "non trovato".

In realtà ci sono diversi modi per superare la lista nera delle API nascoste. A seconda delle tue esigenze, puoi scegliere quelli che funzionano per tutte le versioni di Android, quelli che funzionano solo per Android 9 e 10, quelli che utilizzano codice C++ nativo e quelli che sono completamente basati su Java. Esiste anche una soluzione alternativa solo per lo sviluppo utilizzando ADB.

Soluzione ADB

Se sul tuo dispositivo è in esecuzione Android Pie, esegui i due comandi ADB seguenti per abilitare l'accesso all'API nascosta.

adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1

Se sul tuo dispositivo è installato Android 10 o versioni successive, esegui il seguente comando ADB per abilitare l'accesso API nascosto.

adb shell settings put global hidden_api_policy 1

Per ripristinare il comportamento predefinito, basta sostituire put con delete e rimuovere il 1.

Ovviamente questi comandi non sono esattamente utili per un'app di produzione. Posso dirti in prima persona che istruire adeguatamente gli utenti su come utilizzare ADB è incredibilmente difficile. Ma possono tornare utili se hai bisogno di aggiornare una vecchia app per adeguarla alle nuove restrizioni.

Soluzione nativa/JNI

Esistono due modi per ignorare la lista nera delle API nascoste utilizzando JNI nella tua app Android. Uno funziona per Android 9 e 10 e l'altro funziona per Android 9 e versioni successive.

Android 9 e 10

Se disponi già di una parte nativa della tua app, questa sarà facile da implementare. Basta usare il JNI_OnLoad() funzione.

arte statica:: Runtime* runtime = nullptr;

extern "C"jint JNI_OnLoad(JavaVM *vm, void *reserved){
...
runtime = reinterpret_cast<: javavmext>(vm)->GetRuntime();
runtime->SetHiddenApiEnforcementPolicy(art:: hiddenapi:: EnforcementPolicy:: kNoChecks);
...
}

Tieni presente che questo metodo funziona solo su Android 9 e 10.

Android 9 e versioni successive

Per qualsiasi versione di Android, puoi scegliere tra due librerie per aggirare la restrizione dell'API nascosta: FreeReflection e RestrictionBypass.

Entrambi sono facili da implementare e utilizzare.

Per implementare FreeReflection, aggiungi la dipendenza al tuo build.gradle a livello di modulo.

implementation 'me.weishu: free_reflection: 3.0.1'

Quindi sovrascrivi attachBaseContext() nella tua classe Applicazione.

@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}

Se non hai una classe Application, puoi aggiungerla abbastanza facilmente. Crea una nuova classe che si estende Application e quindi selezionalo nel tuo AndroidManifest.xml.

Esempio:

publicclassAppextendsApplication{
...
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);

Reflection.unseal(base);
}
}

<manifest>
...
...
name=".App">
...
application>
manifest>

Per implementare RestrictionBypass, aggiungi il repository JitPack al tuo build.gradle a livello di progetto.

allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}

Quindi aggiungi la dipendenza al tuo build.gradle a livello di modulo.

implementation 'com.github.ChickenHook: RestrictionBypass: 2.2'

E questo è tutto. Questa libreria rimuove automaticamente le restrizioni della lista nera.

Soluzione Java

Sebbene le soluzioni JNI siano efficaci, a volte potresti non voler utilizzare il codice nativo. Se non stai già eseguendo operazioni in C++, è possibile che vengano aggiunte dimensioni non necessarie e limitazioni della piattaforma alla tua app. Fortunatamente, ci sono modi per aggirare la lista nera delle API nascoste utilizzando solo Java.

Android 9 e 10

In Android 9 e 10, puoi utilizzare quella che può essere chiamata doppia riflessione o meta-riflessione per aggirare la lista nera delle API nascoste. Poiché il sistema controlla solo quali app di terze parti stanno chiamando, la doppia riflessione lo induce a pensare che il sistema stia effettuando chiamate API nascoste.

Questo trucco può essere utilizzato per chiamare un metodo per fornire alla tua app esenzioni API nascoste, dal nome appropriato setHiddenApiExemptions(). Aggiungi semplicemente il seguente codice da qualche parte all'inizio del ciclo di vita della tua app (come Application's onCreate() metodo) e gestirà il bypass della lista nera.

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" } });

Se la tua app è compatibile con versioni di Android precedenti alla 9, ricordati di includerla in un controllo della versione.

Android 9 e versioni successive

Per aggirare la lista nera delle API nascoste su Android 9 e qualsiasi versione successiva, puoi utilizzare la libreria di LSPosed. Questa libreria utilizza l'API Unsafe di Java, quindi è improbabile che si rompa mai.

Per implementarlo, basta aggiungere la dipendenza al build.gradle a livello di modulo.

implementation 'org.lsposed.hiddenapibypass: hiddenapibypass: 2.0'

Quindi usalo per bypassare la lista nera.

HiddenApiBypass.addHiddenApiExemptions("L");

Se la tua app è compatibile con versioni di Android precedenti alla 9, ricordati di includerla in un controllo della versione.

Conclusione e ulteriori informazioni

Esistono molte opzioni per aggirare la lista nera delle API nascoste su Android, indipendentemente dalla versione della piattaforma scelta o utilizzata. Se sei curioso di saperne di più su come funzionano questi metodi e librerie, assicurati di controllare i seguenti collegamenti.

  • Domande e risposte sul mio stack overflow.
  • Libreria Hidden API Bypass di LSposed su GitHub.
  • Libreria RestrictionBypass di ChickenHook su GitHub.
  • La libreria FreeReflection di tiann su GitHub.
  • La documentazione di Google sulla lista nera delle API nascoste.