גוגל הציגה הגבלות באנדרואיד 9 שבהן מפתחים יכולים לגשת לממשקי API. הנה איך לעקוף את הגבלות ה-API הנסתרות.
עוד בשנת 2018, גוגל הוציאה את Android Pie. בין השינויים בממשק המשתמש והתכונות החדשות, היו גם כמה שינויים בצד המפתח. שינויים אלה כללו ממשקי API חדשים, תיקוני באגים עבור ממשקי API קיימים, וכן הגבלות על גישה לממשקי API נסתרים.
למרבה המזל, יש דרכים לעקוף את ההגבלות הללו. לפני שאתחיל כיצד לעקוף את ההגבלות, עלי להסביר מעט מה הם ממשקי API נסתרים, מדוע הם הוגבלו מלכתחילה, ולמה אולי תרצה לגשת אליהם.
ממשקי API מוסתרים הם ממשקי API באנדרואיד שמפתחי אפליקציות בדרך כלל לא יכולים לראות. אם תסתכל על הקוד של AOSP, תראה חבורה שלמה של מחלקות, משתנים ושיטות שיש להם @hide
הערה בתוך בלוק הערה מעליהם.
הערה זו מורה לכל כלי שגוגל משתמשת בו בעת הידור ה-SDK לא לכלול את הפריט תחתיו. ה-SDK הזה מופץ לאחר מכן למפתחים בתוך ה-SDKs שהורדו דרך Android Studio. אלא אם כן אתה משתמש ב-SDK שונה, Android Studio יחשוב שכל אחד מהפריטים המוסתרים האלה פשוט לא קיים. אם תנסה להשתמש באחד ישירות, הוא יראה אותו באדום ויסרב לבצע קומפילציה.
יש הרבה סיבות מדוע API עשוי להיות מוסתר. חלק מהדברים מיועדים לשימוש רק על ידי אפליקציות פנימיות או מערכתיות ולא יפעלו אם משתמשים באפליקציה של צד שלישי. אחרים הם ניסויים או לא יציבים, ועשויים להיות מוסרים או ישתנו בעתיד. חלקם אפילו רק ממשקי API שגוגל פשוט לא רוצה ליישם את מחזור ההוצאה הרגיל אליו אם הם יוסרו אי פעם.
בעוד של-SDK הסטנדרטי של אנדרואיד יש א מִגרָשׁ בו, לפעמים זה לא מספיק. לפעמים יש משהו שאתה רוצה לעשות שכבר קיים באנדרואיד, אבל פשוט לא נחשף בפומבי.
למשל, הרבה מהאפליקציות שאני מייצר, כולל מקלט SystemUI ו ווידג'טים של מסך נעילה, השתמש בחבורה של ממשקי API נסתרים שונים. SystemUI Tuner צריך לגשת לכמה כדי לעקוב, לשנות ולאפס אפשרויות כראוי. ווידג'טים של מסך נעילה משתמשים בחלקם כדי להציג את הטפט מתחתיו, בין היתר.
רוב המפתחים לא צריכים לגשת לממשקי API נסתרים, אבל לפעמים הם יכולים להיות שימושיים למדי.
עם שחרורו של אנדרואיד 9 (Pie), גוגל הציגה את רשימת ה-API השחורה הנסתרת. לא כל API מוסתר נכלל, והיו רמות שונות של רשימות. כל אחד יכול לגשת לממשקי API מוסתרים ברשימת ההיתרים. ניתן לגשת אל ממשקי API מוסתרים ברשימה האפורה הבהירה מכל אפליקציה, אך ייתכן שלא יהיו נגישים בגרסאות עתידיות של אנדרואיד. לכל דבר ברשימה האפורה הכהה ניתן לגשת רק לאפליקציות המתמקדות ברמות API לפני פאי (כלומר, לפני רמת API 28). גישה לאפליקציות הממוקדות ל-Pae ואילך תישלל. לבסוף, ממשקי API מוסתרים ברשימה השחורה לא הייתה ניתנת לגישה על ידי אף אפליקציה שאינה מערכת (או שאינה רשומה לבנה), ללא קשר ל-API היעד.
אנדרואיד 10 שינתה את אופן ארגון הרשימות ופשטה אותן מעט, אבל הרעיון נשאר זהה. יישומים יכולים לגשת אל ממשקי API נסתרים מסוימים בעוד שאחרים נחסמו. אנדרואיד 11 חיזק את זיהוי הגישה ל לחסום מעקף משמש עבור פאי ו-10.
בכל גרסאות אנדרואיד, בכל פעם שאפליקציה של צד שלישי תנסה לגשת ל-API מוסתר ברשימה השחורה, אנדרואיד תציג את השגיאה המתאימה "לא נמצא".
למעשה ישנן לא מעט דרכים לעבור את הרשימה השחורה של ה-API הנסתרת. בהתאם לצרכים שלך, אתה יכול לבחור כאלה שעובדים עבור כל גרסאות אנדרואיד, כאלה שעובדות רק עבור אנדרואיד 9 ו-10, כאלה שמשתמשות בקוד C++ מקורי, וכאלה שמבוססות ג'אווה לחלוטין. יש אפילו פתרון לפיתוח בלבד באמצעות 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
אם במכשיר שלך פועל אנדרואיד 10 ואילך, הפעל את פקודת ה-ADB הבאה כדי לאפשר גישת API נסתרת.
adb shell settings put global hidden_api_policy 1
כדי לחזור להתנהגות ברירת המחדל, פשוט החלף put
עם delete
ולהסיר את 1
.
ברור שהפקודות האלה לא בדיוק שימושיות עבור אפליקציית ייצור. אני יכול להגיד לך ממקור ראשון שלהדריך נכון למשתמשים כיצד להשתמש ב-ADB הוא קשה להפליא. אבל הם יכולים להיות שימושיים אם אתה צריך לעדכן אפליקציה ישנה כדי לעמוד בהגבלות החדשות.
עקיפה של מקורית/JNI
ישנן שתי דרכים בהן תוכל לעקוף את רשימת ה-API השחורה הנסתרת באמצעות JNI באפליקציית Android שלך. אחד עובד עבור אנדרואיד 9 ו-10, והשני עובד עבור אנדרואיד 9 ואילך.
אנדרואיד 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);
...
}
שים לב ששיטה זו פועלת רק על אנדרואיד 9 ו-10.
אנדרואיד 9 ואילך
עבור כל גרסה של אנדרואיד, יש לך בחירה בין שתי ספריות כדי לעקוף את מגבלת ה-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'
וזה הכל. ספרייה זו מסירה אוטומטית את הגבלות הרשימה השחורה.
עקיפת ג'אווה
בעוד שפתרונות JNI יעילים, יש פעמים שאולי לא תרצה להשתמש בקוד מקורי. אם אתה עדיין לא עושה דברים ב-C++, זה יכול להוסיף גודל מיותר, יחד עם הגבלות פלטפורמה, לאפליקציה שלך. למרבה המזל, יש דרכים לעקוף את רשימת ה-API השחורה הנסתרת באמצעות Java בלבד.
אנדרואיד 9 ו-10
באנדרואיד 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" } });
אם האפליקציה שלך תואמת לגרסאות אנדרואיד נמוכות מ-9, זכור לעטוף זאת בבדיקת גרסאות.
אנדרואיד 9 ואילך
כדי לעקוף את רשימת ה-API השחורה הנסתרת באנדרואיד 9 ובכל גרסה מאוחרת יותר, אתה יכול להשתמש בספרייה של LSPosed. ספרייה זו משתמשת ב-API Unsafe של Java, כך שלא סביר שהיא תישבר אי פעם.
כדי ליישם את זה, פשוט הוסף את התלות ל-build.gradle שלך ברמת המודול.
implementation 'org.lsposed.hiddenapibypass: hiddenapibypass: 2.0'
לאחר מכן השתמש בו כדי לעקוף את הרשימה השחורה.
HiddenApiBypass.addHiddenApiExemptions("L");
אם האפליקציה שלך תואמת לגרסאות אנדרואיד נמוכות מ-9, זכור לעטוף זאת בבדיקת גרסאות.
מסקנה ומידע נוסף
יש הרבה אפשרויות לעקוף את רשימת ה-API השחורה הנסתרת באנדרואיד, לא משנה באיזו גרסת פלטפורמה אתה ממקד או משתמש. אם אתה סקרן ללמוד עוד על אופן הפעולה של שיטות וספריות אלה, הקפד לבדוק את הקישורים הבאים.
- My Stack Overflow שאלות ותשובות.
- ספריית Hidden API Bypass של LSposed ב-GitHub.
- ספריית RestrictionBypass של ChickenHook ב-GitHub.
- ספריית FreeReflection של tiann ב-GitHub.
- התיעוד של גוגל על הרשימה השחורה המוסתרת של ממשק API.