Hogyan lehet megkerülni a rejtett API feketelistát Android 9+ rendszeren

A Google korlátozásokat vezetett be az Android 9-ben, amelyen a fejlesztők hozzáférhetnek az API-khoz. A rejtett API-korlátozások megkerülésének módja a következő.

Még 2018-ban a Google kiadta az Android Pie-t. A felhasználói felület változásai és az új funkciók között volt néhány fejlesztői oldali változás is. Ezek a változtatások új API-kat, hibajavításokat tartalmaztak a meglévő API-khoz, és szintén a rejtett API-khoz való hozzáférés korlátozása.

Szerencsére azonban vannak módok a korlátozások megkerülésére. Mielőtt rátérnék a korlátozások megkerülésére, el kell magyaráznom egy kicsit, hogy mik azok a rejtett API-k, miért korlátozták őket először, és miért érdemes elérni őket.

A rejtett API-k azok az API-k az Androidban, amelyeket az alkalmazásfejlesztők általában nem láthatnak. Ha megnézi az AOSP kódját, egy csomó osztályt, változót és metódust fog látni, amelyek @hide megjegyzést a felettük lévő megjegyzésblokkban.

Ez a kommentár arra utasítja a Google által az SDK fordításakor használt eszközt, hogy kizárja az alatta lévő elemet. Ezt az SDK-t ezután az Android Studión keresztül letöltött SDK-kon belül továbbítják a fejlesztőknek. Hacsak nem használ módosított SDK-t, az Android Studio úgy gondolja, hogy ezek a rejtett elemek egyszerűen nem léteznek. Ha közvetlenül megpróbálja használni az egyiket, akkor az piros színnel jelzi, és nem hajlandó lefordítani.

Számos oka lehet annak, hogy egy API el van rejtve. Egyes dolgokat csak belső vagy rendszeralkalmazások használhatnak, és nem működnek, ha harmadik féltől származó alkalmazás használja. Mások kísérleti jellegűek vagy instabilok, és a jövőben eltávolíthatók vagy módosíthatók. Némelyikük még csak API-k, amelyekre a Google nem akarja alkalmazni a szokásos elavulási ciklust, ha valaha is eltávolítják őket.

Míg a szabványos Android SDK rendelkezik a sok benne néha nem elég. Néha van valami, amit el szeretne végezni, ami már létezik az Androidban, de nincs nyilvánosan elérhető.

Például sok általam készített alkalmazás, köztük SystemUI Tuner és Lockscreen widgetek, használjon egy csomó különböző rejtett API-t. A SystemUI Tunernek hozzá kell férnie néhányhoz a beállítások megfelelő követéséhez, módosításához és visszaállításához. A Lockscreen Widgets többek között néhányat használ az alatta lévő háttérkép megjelenítésére.

A legtöbb fejlesztőnek nem kell hozzáférnie a rejtett API-khoz, de néha nagyon hasznosak lehetnek.

Az Android 9 (Pie) megjelenésével a Google bevezette a rejtett API feketelistát. Nem minden rejtett API volt benne, és különböző szintű listák voltak. Az engedélyezőlistán szereplő rejtett API-kat bárki elérheti. A világosszürke listán lévő rejtett API-k bármelyik alkalmazáshoz hozzáférhetnek, de előfordulhat, hogy az Android jövőbeli verzióiban nem lesznek elérhetők. A sötétszürke listán szereplő elemekhez csak a Pie előtti API-szinteket célzó alkalmazások (azaz a 28-as API-szint előtt) férhettek hozzá. A Pie-t és újabbakat célzó alkalmazások hozzáférését megtagadják. Végül, a feketelistán lévő rejtett API-khoz nem férhet hozzá egyetlen rendszeren kívüli (vagy nem engedélyezőlistán szereplő) alkalmazás, a cél API-tól függetlenül.

Az Android 10 megváltoztatta a listák rendszerezését, és kissé leegyszerűsítette őket, de az ötlet ugyanaz maradt. Egyes rejtett API-khoz az alkalmazások hozzáfértek, míg másokat blokkoltak. Android 11 megerősítette a hozzáférés észlelését nak nek blokkoljon egy elkerülőt a Pie-hez és a 10-hez használják.

Minden Android-verzióban, amikor egy harmadik féltől származó alkalmazás megpróbál hozzáférni egy feketelistán szereplő rejtett API-hoz, az Android a megfelelő „nem található” hibát dobja ki.

Valójában jó néhány módszer létezik a rejtett API feketelistán való túljutásra. Igényeitől függően választhat olyanokat, amelyek az összes Android-verzióhoz működnek, olyanokat, amelyek csak az Android 9 és 10 rendszeren működnek, olyanokat, amelyek natív C++ kódot használnak, és olyanokat, amelyek teljesen Java-alapúak. Van még egy csak fejlesztési megoldás is az ADB használatával.

ADB megoldás

Ha az eszközön Android Pie fut, futtassa a következő két ADB-parancsot a rejtett API-hozzáférés engedélyezéséhez.

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

Ha eszközén Android 10 vagy újabb rendszer fut, futtassa a következő ADB-parancsot a rejtett API-hozzáférés engedélyezéséhez.

adb shell settings put global hidden_api_policy 1

Az alapértelmezett viselkedéshez való visszatéréshez egyszerűen cserélje ki put val vel delete és távolítsa el a 1.

Nyilvánvaló, hogy ezek a parancsok nem éppen hasznosak egy éles alkalmazásoknál. Első kézből elmondhatom, hogy hihetetlenül nehéz megfelelő utasításokat adni a felhasználóknak az ADB használatára. De hasznosak lehetnek, ha frissítenie kell egy régi alkalmazást, hogy megfeleljen az új korlátozásoknak.

Natív/JNI megoldás

Kétféleképpen kerülheti meg a rejtett API feketelistát a JNI használatával az Android-alkalmazásában. Az egyik Android 9 és 10, a másik pedig Android 9 és újabb verziókhoz működik.

Android 9 és 10

Ha már rendelkezik az alkalmazás natív részével, akkor ez könnyen megvalósítható. Csak használja a JNI_OnLoad() funkció.

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

Ne feledje, hogy ez a módszer csak az Android 9 és 10 rendszeren működik.

Android 9 és újabb

Az Android bármely verziója esetén két könyvtár közül választhat a rejtett API-korlátozás megkerüléséhez: FreeReflection és RestrictionBypass.

Mindkettő könnyen megvalósítható és használható.

A FreeReflection megvalósításához, adja hozzá a függőséget a modulszintű build.gradle-hez.

implementation 'me.weishu: free_reflection: 3.0.1'

Ezután felülbírálja attachBaseContext() az alkalmazás osztályában.

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

Ha nincs Alkalmazás osztálya, könnyen hozzáadhatja. Hozzon létre egy új osztályt, amely kiterjeszti Application majd mutasson rá az AndroidManifest.xml fájlban.

Példa:

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

Reflection.unseal(base);
}
}

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

A RestrictionBypass megvalósításához, adja hozzá a JitPack-tárat a projektszintű build.gradle-hez.

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

Ezután adja hozzá a függőséget a modulszintű build.gradle fájlhoz.

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

És ez az. Ez a könyvtár automatikusan eltávolítja a tiltólistára vonatkozó korlátozásokat.

Java megoldás

Bár a JNI-megoldások hatékonyak, előfordulhat, hogy nem kívánja használni a natív kódot. Ha még nem csinál valamit a C++ nyelven, akkor szükségtelen méretet és platformkorlátozást adhat az alkalmazáshoz. Szerencsére vannak módok a rejtett API feketelista megkerülésére csak Java használatával.

Android 9 és 10

Az Android 9 és 10 rendszerben az úgynevezett kettős tükrözés vagy meta-reflexió segítségével megkerülheti a rejtett API feketelistát. Mivel a rendszer csak azt ellenőrzi, hogy a harmadik féltől származó alkalmazások mely alkalmazásokat hívják meg, a kettős tükrözés arra készteti, hogy a rendszer a rejtett API-hívásokat indítsa el.

Ezzel a trükkel olyan módszert hívhatunk meg, amellyel az alkalmazásnak találóan elnevezett rejtett API-mentességet ad setHiddenApiExemptions(). Egyszerűen adja hozzá a következő kódot az alkalmazás életciklusának korai szakaszában (például az Alkalmazásé onCreate() módszer), és megoldja a feketelista megkerülését.

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

Ha alkalmazása kompatibilis az Android 9-nél régebbi verzióival, ne felejtse el becsomagolni ezt a verzióellenőrzésbe.

Android 9 és újabb

A rejtett API feketelistájának megkerüléséhez Android 9 és bármely újabb verzió esetén használhatja az LSPosed könyvtárát. Ez a könyvtár a Java Unsafe API-ját használja, így nem valószínű, hogy valaha is tönkremegy.

A megvalósításhoz csak adja hozzá a függőséget a modulszintű build.gradle fájlhoz.

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

Ezután használja a feketelista megkerülésére.

HiddenApiBypass.addHiddenApiExemptions("L");

Ha alkalmazása kompatibilis az Android 9-nél régebbi verzióival, ne felejtse el becsomagolni ezt a verzióellenőrzésbe.

Következtetés és további információ

Rengeteg lehetőség van a rejtett API feketelista megkerülésére Androidon, függetlenül attól, hogy melyik platformverziót célozza meg vagy használja. Ha többet szeretne megtudni ezeknek a módszereknek és könyvtárak működéséről, feltétlenül tekintse meg a következő hivatkozásokat.

  • My Stack Overflow Q&A.
  • Az LSposed Hidden API Bypass könyvtára a GitHubon.
  • ChickenHook RestrictionBypass könyvtára a GitHubon.
  • tiann FreeReflection könyvtárát a GitHubon.
  • A Google dokumentációja a rejtett API feketelistáról.