Η Google εισήγαγε περιορισμούς στο Android 9 στους οποίους οι προγραμματιστές μπορούν να έχουν πρόσβαση στα API. Δείτε πώς μπορείτε να παρακάμψετε αυτούς τους κρυφούς περιορισμούς API.
Πολύ πίσω το 2018, η Google κυκλοφόρησε το Android Pie. Μεταξύ των αλλαγών στη διεπαφή χρήστη και των νέων δυνατοτήτων, υπήρξαν επίσης ορισμένες αλλαγές από την πλευρά του προγραμματιστή. Αυτές οι αλλαγές περιλάμβαναν νέα API, διορθώσεις σφαλμάτων για υπάρχοντα API και επίσης περιορισμούς πρόσβασης σε κρυφά API.
Ευτυχώς όμως, υπάρχουν τρόποι να παρακάμψετε αυτούς τους περιορισμούς. Πριν ασχοληθώ με τον τρόπο παράκαμψης των περιορισμών, θα πρέπει να εξηγήσω λίγο για το τι είναι τα κρυφά API, γιατί περιορίστηκαν αρχικά και γιατί μπορεί να θέλετε να αποκτήσετε πρόσβαση σε αυτά.
Τα κρυφά API είναι τα API στο Android που συνήθως δεν μπορούν να δουν οι προγραμματιστές εφαρμογών. Αν ρίξετε μια ματιά στον κώδικα του AOSP, θα δείτε μια ολόκληρη δέσμη κλάσεων, μεταβλητών και μεθόδων που έχουν @hide
σχολιασμό μέσα σε ένα μπλοκ σχολίων πάνω από αυτά.
Αυτός ο σχολιασμός καθοδηγεί οποιοδήποτε εργαλείο χρησιμοποιεί η Google κατά τη μεταγλώττιση του SDK να εξαιρέσει το στοιχείο κάτω από αυτό. Αυτό το SDK διανέμεται στη συνέχεια στους προγραμματιστές μέσα στα SDK που έχουν ληφθεί μέσω του Android Studio. Αν δεν χρησιμοποιήσετε ένα τροποποιημένο SDK, το Android Studio θα πιστεύει ότι κάποιο από αυτά τα κρυφά στοιχεία απλώς δεν υπάρχει. Εάν προσπαθήσετε να χρησιμοποιήσετε ένα απευθείας, θα το εμφανίσει με κόκκινο χρώμα και θα αρνηθεί τη μεταγλώττιση.
Υπάρχουν πολλοί λόγοι για τους οποίους ένα API μπορεί να είναι κρυφό. Ορισμένα πράγματα προορίζονται μόνο για χρήση από εσωτερικές εφαρμογές ή εφαρμογές συστήματος και δεν θα λειτουργούν εάν χρησιμοποιούνται από μια εφαρμογή τρίτου μέρους. Άλλα είναι πειραματικά ή ασταθή και ενδέχεται να αφαιρεθούν ή να αλλάξουν στο μέλλον. Μερικά είναι απλώς API που η Google απλώς δεν θέλει να εφαρμόσει τον κανονικό κύκλο κατάργησης εάν καταργηθούν ποτέ.
Ενώ το τυπικό SDK Android έχει ένα παρτίδα σε αυτό, μερικές φορές δεν είναι αρκετό. Μερικές φορές υπάρχει κάτι που θέλετε να κάνετε και το οποίο υπάρχει ήδη στο Android, αλλά απλώς δεν εκτίθεται δημόσια.
Για παράδειγμα, πολλές από τις εφαρμογές που κάνω, συμπεριλαμβανομένων Δέκτης SystemUI και Γραφικά στοιχεία κλειδώματος οθόνης, χρησιμοποιήστε μια δέσμη διαφορετικών κρυφών API. Το SystemUI Tuner πρέπει να έχει πρόσβαση σε ορισμένα για να παρακολουθεί, να αλλάζει και να επαναφέρει σωστά τις επιλογές. Τα γραφικά στοιχεία κλειδώματος οθόνης χρησιμοποιούν μερικά για να εμφανίζουν την ταπετσαρία κάτω από αυτό, μεταξύ άλλων.
Οι περισσότεροι προγραμματιστές δεν χρειάζεται να έχουν πρόσβαση σε κρυφά API, αλλά μερικές φορές μπορεί να είναι αρκετά χρήσιμα.
Με την κυκλοφορία του Android 9 (Pie), η Google παρουσίασε τη μαύρη λίστα κρυφών API. Δεν συμπεριλήφθηκαν όλα τα κρυφά API και υπήρχαν διαφορετικά επίπεδα λιστών. Τα κρυφά API στη λίστα επιτρεπόμενων θα μπορούσαν να είναι προσβάσιμα από οποιονδήποτε. Τα κρυφά API στη λίστα ανοιχτού γκρι θα μπορούσαν να είναι προσβάσιμα από οποιαδήποτε εφαρμογή, αλλά ενδέχεται να μην είναι προσβάσιμα σε μελλοντικές εκδόσεις του Android. Οτιδήποτε στη λίστα σκούρου γκρι ήταν προσβάσιμο μόνο από εφαρμογές που στοχεύουν επίπεδα API πριν από το Pie (δηλαδή πριν από το επίπεδο API 28). Οι εφαρμογές που στοχεύουν το Pie και νεότερες εκδόσεις θα στερούνται πρόσβασης. Τέλος, δεν ήταν δυνατή η πρόσβαση στα κρυφά API στη μαύρη λίστα από καμία εφαρμογή που δεν είναι συστήματος (ή μη στη λίστα επιτρεπόμενων), ανεξάρτητα από το API-στόχο.
Το Android 10 άλλαξε τον τρόπο οργάνωσης των λιστών και τις απλοποίησε ελαφρώς, αλλά η ιδέα παρέμεινε η ίδια. Ορισμένα κρυφά API μπορούσαν να είναι προσβάσιμα από εφαρμογές ενώ άλλα ήταν αποκλεισμένα. Android 11 ενίσχυσε την ανίχνευση πρόσβασης προς την μπλοκάρετε μια παράκαμψη χρησιμοποιείται για το Pie και το 10.
Σε όλες τις εκδόσεις Android, κάθε φορά που μια εφαρμογή τρίτου κατασκευαστή επιχειρεί να αποκτήσει πρόσβαση σε ένα κρυφό API στη μαύρη λίστα, το Android θα εμφανίσει το κατάλληλο σφάλμα "δεν βρέθηκε".
Υπάρχουν στην πραγματικότητα αρκετοί τρόποι για να ξεπεράσετε την κρυφή μαύρη λίστα API. Ανάλογα με τις ανάγκες σας, μπορείτε να επιλέξετε αυτές που λειτουργούν για όλες τις εκδόσεις Android, αυτές που λειτουργούν μόνο για Android 9 και 10, αυτές που χρησιμοποιούν εγγενή κώδικα C++ και αυτές που βασίζονται πλήρως σε Java. Υπάρχει ακόμη και μια λύση μόνο για ανάπτυξη χρησιμοποιώντας το ADB.
Λύση ADB
Εάν η συσκευή σας εκτελεί Android Pie, εκτελέστε τις ακόλουθες δύο εντολές ADB για να ενεργοποιήσετε την κρυφή πρόσβαση στο API.
adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1
Εάν η συσκευή σας εκτελεί Android 10 ή νεότερη έκδοση, εκτελέστε την ακόλουθη εντολή ADB για να ενεργοποιήσετε την κρυφή πρόσβαση στο API.
adb shell settings put global hidden_api_policy 1
Για να επιστρέψετε στην προεπιλεγμένη συμπεριφορά, απλώς αντικαταστήστε put
με delete
και αφαιρέστε το 1
.
Προφανώς, αυτές οι εντολές δεν είναι ακριβώς χρήσιμες για μια εφαρμογή παραγωγής. Μπορώ να σας πω από πρώτο χέρι ότι η σωστή καθοδήγηση των χρηστών σχετικά με τον τρόπο χρήσης του ADB είναι απίστευτα δύσκολη. Ωστόσο, μπορεί να είναι χρήσιμα εάν πρέπει να ενημερώσετε μια παλιά εφαρμογή για να συμμορφωθεί με τους νέους περιορισμούς.
Λύση εγγενούς/JNI
Υπάρχουν δύο τρόποι με τους οποίους μπορείτε να παρακάμψετε την κρυφή μαύρη λίστα API χρησιμοποιώντας το JNI στην εφαρμογή σας Android. Το ένα λειτουργεί για Android 9 και 10 και το άλλο για Android 9 και νεότερες εκδόσεις.
Android 9 και 10
Εάν έχετε ήδη ένα εγγενές τμήμα της εφαρμογής σας, αυτό θα είναι εύκολο να εφαρμοστεί. Απλώς χρησιμοποιήστε το JNI_OnLoad()
λειτουργία.
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);
...
}
Λάβετε υπόψη ότι αυτή η μέθοδος λειτουργεί μόνο σε Android 9 και 10.
Android 9 και νεότερη έκδοση
Για οποιαδήποτε έκδοση του Android, έχετε την επιλογή δύο βιβλιοθηκών για να παρακάμψετε τον κρυφό περιορισμό του API: FreeReflection και RestrictionBypass.
Και οι δύο είναι εύκολο να εφαρμοστούν και να χρησιμοποιηθούν.
Για την υλοποίηση του FreeReflection, προσθέστε την εξάρτηση στο build.gradle σε επίπεδο ενότητας.
implementation 'me.weishu: free_reflection: 3.0.1'
Στη συνέχεια, παρακάμψτε attachBaseContext()
στην τάξη Εφαρμογών σας.
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}
Εάν δεν έχετε τάξη Εφαρμογών, μπορείτε να την προσθέσετε πολύ εύκολα. Δημιουργήστε μια νέα κλάση που επεκτείνεται Application
και μετά τοποθετήστε το δείκτη σε αυτό στο AndroidManifest.xml.
Παράδειγμα:
publicclassAppextendsApplication{
...
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}
}
<manifest>
...
...
name=".App">
...
application>
manifest>
Για την εφαρμογή του RestrictionBypass, προσθέστε το αποθετήριο JitPack στο build.gradle σε επίπεδο έργου.
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
Στη συνέχεια, προσθέστε την εξάρτηση στο build.gradle σε επίπεδο ενότητας.
implementation 'com.github.ChickenHook: RestrictionBypass: 2.2'
Και αυτό είναι όλο. Αυτή η βιβλιοθήκη καταργεί αυτόματα τους περιορισμούς της μαύρης λίστας.
Λύση Java
Ενώ οι λύσεις JNI είναι αποτελεσματικές, υπάρχουν φορές που μπορεί να μην θέλετε να χρησιμοποιήσετε εγγενή κώδικα. Εάν δεν κάνετε ήδη πράγματα σε C++, μπορεί να προσθέσει περιττό μέγεθος, μαζί με περιορισμούς πλατφόρμας, στην εφαρμογή σας. Ευτυχώς, υπάρχουν τρόποι για να παρακάμψετε την κρυφή μαύρη λίστα API χρησιμοποιώντας μόνο Java.
Android 9 και 10
Στο Android 9 και 10, μπορείτε να χρησιμοποιήσετε αυτό που μπορεί να ονομαστεί διπλή αντανάκλαση ή μετα-ανασκόπηση για να παρακάμψετε την κρυφή μαύρη λίστα API. Επειδή το σύστημα ελέγχει μόνο τι καλούν εφαρμογές τρίτων, η διπλή αντανάκλαση το ξεγελάει ώστε να πιστεύει ότι το σύστημα πραγματοποιεί τις κρυφές κλήσεις API.
Αυτό το τέχνασμα μπορεί να χρησιμοποιηθεί για να καλέσετε μια μέθοδο για να δώσετε στην εφαρμογή σας κρυφές εξαιρέσεις API, με εύστοχη ονομασία setHiddenApiExemptions()
. Απλώς προσθέστε τον ακόλουθο κώδικα κάπου νωρίς στον κύκλο ζωής της εφαρμογής σας (όπως της εφαρμογής onCreate()
μέθοδο) και θα χειριστεί την παράκαμψη της μαύρης λίστας.
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" } });
Εάν η εφαρμογή σας είναι συμβατή με εκδόσεις Android χαμηλότερες από 9, θυμηθείτε να το τυλίξετε σε έναν έλεγχο έκδοσης.
Android 9 και νεότερη έκδοση
Για να παρακάμψετε την κρυφή μαύρη λίστα API στο Android 9 και σε οποιαδήποτε νεότερη έκδοση, μπορείτε να χρησιμοποιήσετε τη βιβλιοθήκη του LSPosed. Αυτή η βιβλιοθήκη χρησιμοποιεί το μη ασφαλές API της Java, επομένως είναι απίθανο να χαλάσει ποτέ.
Για να το εφαρμόσετε, απλώς προσθέστε την εξάρτηση στο build.gradle σε επίπεδο ενότητας.
implementation 'org.lsposed.hiddenapibypass: hiddenapibypass: 2.0'
Στη συνέχεια χρησιμοποιήστε το για να παρακάμψετε τη μαύρη λίστα.
HiddenApiBypass.addHiddenApiExemptions("L");
Εάν η εφαρμογή σας είναι συμβατή με εκδόσεις Android χαμηλότερες από 9, θυμηθείτε να το τυλίξετε σε έναν έλεγχο έκδοσης.
Συμπέρασμα και περισσότερες πληροφορίες
Υπάρχουν πολλές επιλογές για την παράκαμψη της κρυφής μαύρης λίστας API στο Android, ανεξάρτητα από την έκδοση πλατφόρμας που στοχεύετε ή χρησιμοποιείτε. Εάν είστε περίεργοι να μάθετε περισσότερα σχετικά με τον τρόπο λειτουργίας αυτών των μεθόδων και βιβλιοθηκών, φροντίστε να ελέγξετε τους παρακάτω συνδέσμους.
- My Stack Overflow Q&A.
- Η βιβλιοθήκη Hidden API Bypass του LSposed στο GitHub.
- Η βιβλιοθήκη του ChickenHook's RestrictionBypass στο GitHub.
- tiann's FreeReflection βιβλιοθήκη στο GitHub.
- Η τεκμηρίωση της Google για την κρυφή μαύρη λίστα API.