הגבלות על ממשקים שאינם SDK

החל מ-Android 9 (רמת API‏ 28), הפלטפורמה מגבילה את השימוש בממשקים שאינם חלק מ-SDK באפליקציה. ההגבלות האלה חלות בכל פעם שאפליקציה מפנה לממשק שאינו ב-SDK או מנסה להשיג את הטיפול שלו באמצעות רפלקציה או JNI. ההגבלות האלה הוגדרו כדי לשפר את חוויית המשתמש והמפתחים, וכדי להפחית את הסיכון לקריסות בקרב המשתמשים ולפריסות חירום בקרב המפתחים. מידע נוסף על ההחלטה הזו מופיע במאמר שיפור היציבות באמצעות צמצום השימוש בממשקים שאינם SDK.

הבחנה בין ממשקי SDK לבין ממשקים שאינם SDK

באופן כללי, ממשקי SDK ציבוריים הם אלה שמתועדים באינדקס החבילות של מסגרת Android. הטיפול בממשקים שאינם SDK הוא פרט הטמעה שה-API מסתיר, ולכן הממשקים האלה כפופים לשינויים ללא הודעה מוקדמת.

כדי למנוע קריסות והתנהגות לא צפויה, האפליקציות צריכות להשתמש רק בחלקים של המחלקות ב-SDK שמתועדים באופן רשמי. המשמעות היא גם שאסור לגשת לשיטות או לשדות שלא מופיעים ב-SDK כשמבצעים אינטראקציה עם מחלקה באמצעות מנגנונים כמו רפלקציה.

רשימות של ממשקי API שאינם SDK

בכל גרסה של Android, יש עוד ממשקים שאינם ב-SDK שמוגבלים. אנחנו יודעים שההגבלות האלה יכולות להשפיע על תהליך השקת האפליקציה, ולכן אנחנו רוצים לוודא שיש לך את הכלים לזהות שימוש בממשקים שאינם SDK, הזדמנות לשלוח לנו משוב וזמן לתכנן ולהתאים את האפליקציה למדיניות החדשה.

כדי למזער את ההשפעה של ההגבלות על ממשקים שאינם SDK על תהליך העבודה של הפיתוח, הממשקים שאינם SDK מחולקים לרשימות שמגדירות את רמת ההגבלה על השימוש בהם, בהתאם לרמת ה-API שהוגדרה כיעד. בטבלה הבאה מתואר כל אחד מהרשימות האלה:

רשימה תגי קוד תיאור
רשימת חסימה
  • blocked
  • הוצא משימוש: blacklist
ממשקים שאינם ב-SDK שאסור להשתמש בהם בלי קשר לרמת ה-API לטירגוט של האפליקציה. אם האפליקציה מנסה לגשת לאחד מהממשקים האלה, המערכת מציגה שגיאה.
חסום באופן מותנה
  • max-target-x
  • הוצא משימוש: greylist-max-x

החל מ-Android 9 (רמת API‏ 28), לכל רמת API יש ממשקי non-SDK שמוגבלים כשהאפליקציה מטרגטת את רמת ה-API הזו.

הרשימות האלה מסומנות לפי רמת ה-API המקסימלית (max-target-x) שאפליקציה יכולה לטרגט לפני שהיא כבר לא יכולה לגשת לממשקי ה-non-SDK שברשימה. לדוגמה, ממשק שאינו SDK שלא נחסם ב-Android Pie אבל נחסם עכשיו ב-Android 10 הוא חלק מהרשימה max-target-p (greylist-max-p), כאשר p מייצג את Pie או Android 9 (רמת API ‏28).

אם האפליקציה מנסה לגשת לממשק שמוגבל לרמת ה-API לטירגוט, המערכת מתנהגת כאילו ה-API הוא חלק מרשימת החסימה.

לא נתמך
  • unsupported
  • הוצא משימוש: greylist
ממשקים שאינם SDK שאין הגבלה על השימוש בהם, והאפליקציה יכולה להשתמש בהם. עם זאת, חשוב לזכור שהממשקים האלה לא נתמכים ויכולים להשתנות ללא הודעה מוקדמת. צפוי שהממשקים האלה ייחסמו באופן מותנה בגרסאות עתידיות של Android ברשימה max-target-x.
SDK
  • גם public-api וגם sdk
  • הוצא משימוש: גם public-api וגם whitelist
ממשקים שאפשר להשתמש בהם באופן חופשי, ועכשיו הם נתמכים כחלק מאינדקס החבילות של מסגרת Android שמתועדת באופן רשמי.
ממשקי API לבדיקה
  • test-api
ממשקים שמשמשים לבדיקות מערכת פנימיות, כמו ממשקי API שמקלים על בדיקות באמצעות חבילת בדיקות התאימות (CTS). ממשקי ה-API לבדיקה לא נכללים ב-SDK. החל מ-Android 11 (רמת API‏ 30), ממשקי API לבדיקה נכללים ברשימת החסימה, ולכן לאפליקציות אסור להשתמש בהם, ללא קשר לרמת ה-API לטירגוט שלהן. כל ממשקי ה-API לבדיקות לא נתמכים ועשויים להשתנות ללא הודעה מוקדמת, ללא קשר לרמת ה-API של הפלטפורמה.

אפשר להשתמש בחלק מהממשקים שאינם ב-SDK (בהתאם לרמת ה-API לטירגוט של האפליקציה), אבל שימוש בשיטה או בשדה שאינם ב-SDK תמיד כרוך בסיכון גבוה לשבירת האפליקציה. אם האפליקציה שלכם מסתמכת על ממשקים שאינם ב-SDK, כדאי להתחיל לתכנן מעבר לממשקי SDK או לחלופות אחרות. אם אין לכם אפשרות להשתמש בממשק שאינו ב-SDK עבור תכונה באפליקציה, כדאי לשלוח בקשה ליצירת API ציבורי חדש.

איך קובעים לאיזו רשימה שייך ממשק

רשימות הממשקים שאינם ב-SDK נוצרות כחלק מהפלטפורמה. בקטעים הבאים מפורט מידע על כל מהדורה של Android.

Android 16

ב-Android 16 (רמת API 36), אפשר להוריד את הקובץ הבא שמתאר את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם:

קובץ: hiddenapi-flags.csv

סיכום ביקורת (checksum) של SHA-256: 9102af02fe6ab68b92464bdff5e5b09f3bd62c65d1130aaf85d3296f17d38074

מידע נוסף על השינויים ברשימת ממשקי ה-API שאינם SDK ב-Android 16 זמין במאמר עדכונים בהגבלות על ממשקי API שאינם SDK ב-Android 16.

Android 15

ב-Android 15‏ (רמת API‏ 35), אפשר להוריד את הקובץ הבא שמתאר את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם:

קובץ: hiddenapi-flags.csv

סיכום ביקורת (checksum) של SHA-256: 40134e205e58922a708c453726b279a296e6a1f34a988abd90cec0f3432ea5a9

מידע נוסף על השינויים ברשימת ממשקי ה-API שאינם SDK ב-Android 15 זמין במאמר עדכונים בהגבלות על ממשקי API שאינם SDK ב-Android 15.

Android 14

ב-Android 14 (רמת API 34), אפשר להוריד את הקובץ הבא שמתאר את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם:

קובץ: hiddenapi-flags.csv

סיכום ביקורת (checksum) של SHA-256: 7e00db074cbe51c51ff4b411f7b48e98692951395c5c17d069c822cc1d0eae0f

מידע נוסף על השינויים ברשימת ממשקי ה-API שאינם SDK ב-Android 14 זמין במאמר עדכונים בהגבלות על ממשקים שאינם SDK ב-Android 14.

Android 13

ב-Android 13 (רמת API 33), אפשר להוריד את הקובץ הבא שמתאר את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם:

קובץ: hiddenapi-flags.csv

סיכום ביקורת (checksum) של SHA-256: 233a277aa8ac475b6df61bffd95665d86aac6eb2ad187b90bf42a98f5f2a11a3

מידע נוסף על השינויים ברשימת ממשקי ה-API שאינם SDK ב-Android 13, כולל חלופות מוצעות של ממשקי API ציבוריים לממשקי API שנחסמים באופן מותנה ב-Android 13, זמין במאמר עדכונים בהגבלות על ממשקים שאינם SDK ב-Android 13.

12 ‏Android

ב-Android 12 (רמת API 31), אפשר להוריד את הקובץ הבא שמתאר את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם:

קובץ: hiddenapi-flags.csv

סיכום ביקורת (checksum) של SHA-256: 40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761

מידע נוסף על השינויים ברשימת ממשקי ה-API שאינם SDK ב-Android 12, כולל חלופות מוצעות של ממשקי API ציבוריים לממשקי API שנחסמים באופן מותנה ב-Android 12, זמין במאמר שינויים ברשימה של Android 12.

Android 11

ב-Android 11 (רמת API‏ 30), אפשר להוריד את הקובץ הבא שמתאר את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם:

קובץ: hiddenapi-flags.csv

סיכום ביקורת (checksum) של SHA-256: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56

כדי לקבל מידע נוסף על השינויים ברשימת ממשקי ה-API שאינם SDK ב-Android 11, כולל הצעות לחלופות של ממשקי API ציבוריים לממשקי API שנחסמים באופן מותנה ב-Android 11, אפשר לעיין במאמר שינויים ברשימה של Android 11.

‫Android 10

ב-Android 10 (רמת API‏ 29), אפשר להוריד את הקובץ הבא שמתאר את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם:

קובץ: hiddenapi-flags.csv

סיכום ביקורת (checksum) של SHA-256: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb

מידע נוסף על השינויים ברשימת ממשקי ה-API שאינם SDK ב-Android 10, כולל הצעות לחלופות של ממשקי API ציבוריים לממשקי API שנחסמים באופן מותנה ב-Android 10, זמין במאמר שינויים ברשימה ל-Android 10.

‫Android 9

ב-Android 9 (רמת API‏ 28), קובץ הטקסט הבא מכיל את רשימת ממשקי ה-API שאינם SDK ושאין הגבלות על השימוש בהם (רשימה אפורה): hiddenapi-light-greylist.txt.

רשימת החסימה (blacklist) ורשימת ממשקי ה-API שנחסמים בתנאים מסוימים (רשימה בצבע אפור כהה) נוצרות בזמן הבנייה.

יצירת רשימות מ-AOSP

כשעובדים עם AOSP, אפשר ליצור קובץ hiddenapi-flags.csv שמכיל את כל הממשקים שאינם SDK ואת הרשימות התואמות שלהם. כדי לעשות זאת, מורידים את המקור של AOSP ומריצים את הפקודה הבאה:

m out/soong/hiddenapi/hiddenapi-flags.csv

אחר כך תוכלו למצוא את הקובץ במיקום הבא:

out/soong/hiddenapi/hiddenapi-flags.csv

התנהגות צפויה כשניגשים לממשקים מוגבלים שאינם ב-SDK

בטבלה הבאה מתואר מה יקרה אם האפליקציה תנסה לגשת לממשק שאינו SDK שמופיע ברשימת החסימה.

אמצעי גישה תוצאה
הוראת Dalvik שמפנה לשדה NoSuchFieldError thrown
הוראת Dalvik שמתייחסת לשיטה NoSuchMethodError thrown
השתקפות באמצעות Class.getDeclaredField() או Class.getField() NoSuchFieldException thrown
השתקפות באמצעות Class.getDeclaredMethod(), Class.getMethod() NoSuchMethodException thrown
רפלקציה באמצעות Class.getDeclaredFields(), Class.getFields() חברים שלא הצטרפו דרך ה-SDK לא מופיעים בתוצאות
רפלקציה באמצעות Class.getDeclaredMethods(), Class.getMethods() חברים שלא הצטרפו דרך ה-SDK לא מופיעים בתוצאות
‫JNI באמצעות env->GetFieldID() NULL returned, NoSuchFieldError thrown
‫JNI באמצעות env->GetMethodID() NULL returned, NoSuchMethodError thrown

בדיקת האפליקציה לגבי ממשקים שאינם SDK

יש כמה שיטות שבהן אפשר להשתמש כדי לבדוק אם יש באפליקציה ממשקים שאינם SDK.

בדיקה באמצעות אפליקציה שניתנת לניפוי באגים

כדי לבדוק אם יש ממשקים שאינם SDK, צריך ליצור ולהריץ אפליקציה שאפשר לבצע בה ניפוי באגים במכשיר או באמולטור עם Android 9 (רמת API‏ 28) או גרסה מתקדמת יותר. צריך לוודא שהמכשיר או האמולטור שבהם אתם משתמשים תואמים לרמת ה-API לטירגוט של האפליקציה.

במהלך בדיקות של האפליקציה, המערכת מדפיסה הודעת יומן אם האפליקציה ניגשת לממשקים מסוימים שאינם SDK. אתם יכולים לבדוק את הודעות היומן של האפליקציה כדי למצוא את הפרטים הבאים:

  • המחלקות, השם והסוג של ההצהרה (בפורמט שבו נעשה שימוש בזמן הריצה של Android).
  • אמצעי הגישה: קישור, שימוש בהשתקפות או שימוש ב-JNI.
  • הרשימה שאליה שייך הממשק שאינו SDK.

אפשר להשתמש ב-adb logcat כדי לגשת להודעות היומן האלה, שמופיעות מתחת ל-PID של האפליקציה הפועלת. לדוגמה, רשומה ביומן יכולה להיראות כך:

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)

בדיקה באמצעות StrictMode API

אפשר גם לבדוק אם נעשה שימוש בממשקים שאינם SDK באמצעות StrictMode API. כדי להפעיל את האפשרות הזו, משתמשים בשיטה detectNonSdkApiUsage. אחרי שמפעילים את StrictMode API, אפשר לקבל קריאה חוזרת לכל שימוש בממשק שאינו SDK באמצעות penaltyListener, שבו אפשר להטמיע טיפול מותאם אישית. האובייקט Violation שמועבר בקריאה החוזרת נגזר מ-Throwable, ודוח הקריסות שמופיע בו מספק את ההקשר של השימוש.

בדיקה באמצעות כלי ה-lint של Android Studio

בכל פעם שאתם מבצעים build לאפליקציה ב-Android Studio, הכלי lint בודק את הקוד שלכם כדי לזהות בעיות פוטנציאליות. אם האפליקציה שלכם משתמשת בממשקים שאינם ב-SDK, יכול להיות שיוצגו לכם שגיאות או אזהרות ב-build, בהתאם לרשימה שאליה הממשקים האלה שייכים.

אפשר גם להריץ את כלי ה-lint משורת הפקודה או להריץ בדיקות באופן ידני בפרויקט, בתיקייה או בקובץ ספציפיים.

בדיקה באמצעות Play Console

כשמעלים אפליקציה למסלול בדיקה ב-Play Console, המערכת בודקת באופן אוטומטי אם יש באפליקציה בעיות פוטנציאליות, ויוצרת דוח טרום-השקה. אם האפליקציה שלכם משתמשת בממשקים שאינם ב-SDK, תוצג שגיאה או אזהרה בדוח טרום-השקה, בהתאם לרשימה שאליה שייכים הממשקים האלה.

מידע נוסף זמין בקטע 'תאימות ל-Android' במאמר שימוש בדוחות טרום-השקה כדי לזהות בעיות.

שליחת בקשה ל-API ציבורי חדש

אם אין לכם אפשרות להשתמש בממשק שאינו ב-SDK עבור תכונה באפליקציה, אתם יכולים להגיש בקשה להוספת תכונה בכלי שלנו לניהול בעיות כדי לבקש ממשק API ציבורי חדש.

כשמגישים בקשה להוספת תכונה, צריך לספק את הפרטים הבאים:

  • איזה API לא נתמך נמצא בשימוש, כולל המתאר המלא שמופיע בהודעה Accessing hidden ... logcat.
  • למה צריך להשתמש בממשקי ה-API האלה, כולל פרטים על התכונה ברמה גבוהה שנדרש בשבילה ה-API, ולא רק פרטים ברמה נמוכה.
  • למה ממשקי API ציבוריים קשורים של SDK לא מספיקים למטרות שלך.
  • אילו אפשרויות אחרות ניסית ולמה הן לא עבדו.

כשמספקים את הפרטים האלה בבקשה להוספת תכונה, הסיכוי לקבל API חדש שגלוי לכולם גדל.

שאלות נוספות

בקטע הזה ריכזנו תשובות לכמה שאלות נוספות שמפתחים שואלים לעיתים קרובות:

שאלות כלליות

איך Google יכולה לוודא שהיא יכולה לתעד את הצרכים של כל האפליקציות באמצעות הכלי למעקב אחר בעיות?

יצרנו את הרשימות הראשוניות ל-Android 9 (רמת API‏ 28) באמצעות ניתוח סטטי של אפליקציות, שהושלם באמצעות השיטות הבאות:

  • בדיקה ידנית של אפליקציות מובילות ב-Play ואפליקציות שלא ב-Play
  • דוחות פנימיים
  • איסוף נתונים אוטומטי ממשתמשים פנימיים
  • דוחות בתצוגה מקדימה למפתחים
  • ניתוח סטטי נוסף שנועד לכלול באופן שמרני יותר תוצאות חיוביות שגויות

במהלך הבדיקה של הרשימות לכל גרסה חדשה, אנחנו לוקחים בחשבון את השימוש ב-API ואת המשוב של המפתחים דרך הכלי למעקב אחר בעיות.

איך מאפשרים גישה לממשקים שאינם ב-SDK?

אפשר להפעיל גישה לממשקים שלא נכללים ב-SDK במכשירי פיתוח באמצעות פקודות adb כדי לשנות את מדיניות האכיפה של API. הפקודות שבהן משתמשים משתנות בהתאם לרמת ה-API. הפקודות האלה לא דורשות מכשיר עם הרשאות בסיס.

‫Android מגרסה 10 (רמת API‏ 29) ואילך

כדי להפעיל את הגישה, משתמשים בפקודת adb הבאה

פקודה:

adb shell settings put global hidden_api_policy  1

כדי לאפס את מדיניות האכיפה של ה-API להגדרות ברירת המחדל, משתמשים בפקודה הבאה:

adb shell settings delete global hidden_api_policy
‫Android 9 (רמת API‏ 28)

כדי להפעיל את הגישה, משתמשים בפקודות adb הבאות:

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

כדי לאפס את מדיניות האכיפה של ה-API להגדרות ברירת המחדל, משתמשים בפקודות הבאות:

adb shell settings delete global hidden_api_policy_pre_p_apps
adb shell settings delete global hidden_api_policy_p_apps

אפשר להגדיר את המספר השלם במדיניות האכיפה של ה-API לאחד מהערכים הבאים:

  • ‫0: השבתה של כל הזיהוי של ממשקים שאינם SDK. השימוש בהגדרה הזו משבית את כל הודעות היומן לגבי שימוש בממשק שאינו SDK, ומונע מכם לבדוק את האפליקציה באמצעות StrictMode API. ההגדרה הזו לא מומלצת.
  • ‫1: הפעלת הגישה לכל הממשקים שאינם ב-SDK, אבל הדפסת הודעות יומן עם אזהרות לגבי כל שימוש בממשק שאינו ב-SDK. ההגדרה הזו מאפשרת גם לבדוק את האפליקציה באמצעות StrictMode API.
  • ‫2: חסימת השימוש בממשקים שלא נכללים ב-SDK וששייכים לרשימת החסימה או שנחסמים באופן מותנה ברמת ה-API לטירגוט.

שאלות לגבי רשימות של ממשקים שאינם ב-SDK

איפה אפשר למצוא את רשימות ה-API שאינן SDK בקובץ אימג' של המערכת?

הם מקודדים בביטים של דגל הגישה לשדה ולשיטה בקובצי dex של הפלטפורמה. אין קובץ נפרד בקובץ אימג' של המערכת שמכיל את הרשימות האלה.

האם רשימות ה-API שאינן SDK זהות במכשירי OEM שונים עם אותן גרסאות Android?

יצרני ציוד מקורי יכולים להוסיף ממשקים משלהם לרשימת החסימה (רשימה שחורה), אבל הם לא יכולים להסיר ממשקים מרשימות ה-API שאינם SDK ב-AOSP. ה-CDD מונע שינויים כאלה, ובדיקות CTS מוודאות שסביבת זמן הריצה של Android אוכפת את הרשימה.

האם יש הגבלה כלשהי על ממשקי NDK שאינם קיימים בקוד Native?

‫Android SDK כולל ממשקי Java. הפלטפורמה התחילה להגביל את הגישה לממשקי NDK עבור קוד C/C++‎ מקורי ב-Android 7 (רמת API‏ 26). מידע נוסף זמין במאמר בנושא שיפור היציבות באמצעות הגבלות על סמלי C/C++ פרטיים ב-Android N.

יש תוכניות להגביל את dex2oat או את השימוש בקובצי DEX?

אין לנו תוכניות פעילות להגבלת הגישה לקובץ הבינארי dex2oat, אבל אנחנו לא מתכוונים שפורמט קובץ ה-DEX יהיה יציב או ממשק ציבורי מעבר לחלקים שצוינו באופן ציבורי בפורמט Dalvik Executable. אנחנו שומרים לעצמנו את הזכות לשנות או לבטל את dex2oat ואת החלקים הלא מוגדרים של פורמט DEX בכל שלב. חשוב גם לציין שקבצים נגזרים שנוצרו על ידי dex2oat, כמו ODEX (שנקרא גם OAT),‏ VDEX ו-CDEX, הם כולם פורמטים לא מוגדרים.

מה קורה אם ערכת SDK חיונית של צד שלישי (למשל, obfuscator) לא יכולה להימנע משימוש בממשקים שאינם ב-SDK, אבל מתחייבת לשמור על תאימות לגרסאות עתידיות של Android? האם אפשר לקבל פטור מדרישות התאימות של Android במקרה הזה?

אין לנו תוכניות לוותר על דרישות התאימות על בסיס כל ערכת SDK בנפרד. אם מפתח SDK יכול לשמור על תאימות רק על ידי הסתמכות על ממשקים ברשימות הלא נתמכות (לשעבר אפורות), הוא צריך להתחיל לתכנן מעבר לממשקי SDK או לחלופות אחרות, ולשלוח בקשה ל-API ציבורי חדש אם הוא לא מוצא חלופה לשימוש בממשק שאינו ב-SDK.

האם ההגבלות על ממשקים שאינם SDK חלות על כל האפליקציות, כולל אפליקציות מערכת ואפליקציות מבית Google, ולא רק על אפליקציות של צד שלישי?

כן, אבל אנחנו פוטרים מחובת החתימה אפליקציות שנחתמו באמצעות מפתח הפלטפורמה ואפליקציות מסוימות של קובץ אימג' של המערכת. חשוב לדעת שהפטורים האלה חלים רק על אפליקציות שכלולות בקובץ אימג' של המערכת (או על אפליקציות שמעדכנות את קובץ אימג' של המערכת). הרשימה מיועדת רק לאפליקציות שמבוססות על ממשקי ה-API הפרטיים של הפלטפורמה, ולא על ממשקי ה-API של ה-SDK (שבהם LOCAL_PRIVATE_PLATFORM_APIS := true).