בנוסף לתכונות וליכולות החדשות, Android 7.0 כוללת מגוון שינויים בהתנהגות של המערכת ושל ה-API. במסמך הזה מודגשים כמה מהשינויים העיקריים שחשוב להבין ולהביא בחשבון באפליקציות.
אם כבר פרסמתם אפליקציה ל-Android, חשוב שתדעו שהשינויים האלה בפלטפורמה עלולים להשפיע על האפליקציה שלכם.
סוללה וזיכרון
Android 7.0 כוללת שינויים בהתנהגות המערכת שנועדו לשפר את חיי הסוללה של המכשירים ולהפחית את השימוש ב-RAM. השינויים האלה יכולים להשפיע על הגישה של האפליקציה למשאבי המערכת, וגם על האופן שבו האפליקציה יוצרת אינטראקציה עם אפליקציות אחרות באמצעות כוונות משתמעות מסוימות.
נמנום
מצב Doze, שהוצג ב-Android 6.0 (רמת API 23), מאריך את חיי הסוללה על ידי דחיית פעילויות של המעבד ופעילות ברשת כשהמשתמש משאיר את המכשיר מנותק מהחשמל, ללא תנועה ועם מסך כבוי. ב-Android 7.0 יש שיפורים נוספים למצב Doze, על ידי החלת קבוצת משנה של הגבלות על המעבד והרשת כשהמכשיר מנותק מהחשמל והמסך כבוי, אבל לא בהכרח ללא תנועה, למשל, כשהמכשיר נמצא בכיס של המשתמש.
איור 1. איור שמראה איך מצב Doze מחיל רמה ראשונה של הגבלות על פעילות המערכת כדי להאריך את חיי הסוללה.
כשהמכשיר פועל על סוללה והמסך כבוי למשך זמן מסוים, המכשיר נכנס למצב Doze ומחיל את קבוצת המשנה הראשונה של ההגבלות: הוא משבית את הגישה של האפליקציה לרשת, ודוחה משימות וסנכרונים. אם המכשיר לא זז במשך זמן מסוים אחרי הכניסה למצב Doze, המערכת מחילה את שאר ההגבלות של מצב Doze על PowerManager.WakeLock, התראות AlarmManager, GPS וסריקות Wi-Fi. לא משנה אם כל ההגבלות של מצב Doze חלות או רק חלק מהן, המערכת מעירה את המכשיר לחלונות זמן קצרים לתחזוקה, שבהם האפליקציות מקבלות גישה לרשת ויכולות לבצע משימות או סנכרונים שנדחו.
איור 2. איור שמראה איך מצב Doze מחיל רמה שנייה של הגבלות על פעילות המערכת אחרי שהמכשיר לא זז במשך זמן מסוים.
חשוב לדעת: הפעלת המסך או חיבור המכשיר לחשמל מוציאים אותו ממצב Doze ומסירים את מגבלות העיבוד האלה. ההתנהגות הנוספת לא משפיעה על ההמלצות והשיטות המומלצות להתאמת האפליקציה לגרסה הקודמת של מצב חיסכון בסוללה שהוצגה ב-Android 6.0 (רמת API 23), כפי שמתואר במאמר אופטימיזציה למצב חיסכון בסוללה ולאפליקציה במצב המתנה. עדיין צריך לפעול לפי ההמלצות האלה, כמו שימוש ב-"העברת הודעות בענן ב-Firebase" (FCM) כדי לשלוח ולקבל הודעות, ולהתחיל לתכנן עדכונים שיתאימו להתנהגות הנוספת של מצב Doze.
פרויקט Svelte: אופטימיזציות ברקע
ב-Android 7.0 הוסרו שלוש הודעות מרומזות כדי לעזור באופטימיזציה של השימוש בזיכרון ושל צריכת החשמל. השינוי הזה נדרש כי הודעות מרומזות מפעילות לעיתים קרובות אפליקציות שנרשמו להאזנה להן ברקע. הסרת השידורים האלה יכולה לשפר באופן משמעותי את הביצועים של המכשיר ואת חוויית המשתמש.
במכשירים ניידים יש שינויים תכופים בקישוריות, למשל כשעוברים בין Wi-Fi לחבילת גלישה. נכון לעכשיו, אפליקציות יכולות לעקוב אחרי שינויים בקישוריות על ידי רישום מקלט לשידור המרומז CONNECTIVITY_ACTION במניפסט שלהן. הרבה אפליקציות נרשמות כדי לקבל את השידור הזה, ולכן מתג רשת אחד יכול לגרום לכולן להתעורר ולעבד את השידור בבת אחת.
באופן דומה, בגרסאות קודמות של Android, אפליקציות יכלו להירשם כדי לקבל שידורים מרומזים של ACTION_NEW_PICTURE ו-ACTION_NEW_VIDEO מאפליקציות אחרות, כמו המצלמה. כשמשתמש מצלם תמונה באמצעות אפליקציית המצלמה, האפליקציות האלה מתעוררות כדי לעבד את השידור.
כדי לפתור את הבעיות האלה, ב-Android 7.0 מתבצעות האופטימיזציות הבאות:
- אפליקציות שמטרגטות ל-Android 7.0 (רמת API 24) ומעלה לא מקבלות שידורי
CONNECTIVITY_ACTIONאם הן מצהירות על מקלט השידור שלהן במניפסט. אפליקציות עדיין יקבלו שידוריCONNECTIVITY_ACTIONאם הן ירשמו את ה-BroadcastReceiverשלהן באמצעותContext.registerReceiver()וההקשר הזה עדיין יהיה תקף. - המערכת לא שולחת יותר שידורי
ACTION_NEW_PICTUREאוACTION_NEW_VIDEO. האופטימיזציה הזו משפיעה על כל האפליקציות, לא רק על אלה שמטרגטות ל-Android 7.0.
אם האפליקציה שלכם משתמשת באחד מה-Intent האלה, כדאי להסיר את התלות בהם בהקדם האפשרי כדי שתוכלו לטרגט מכשירי Android 7.0 כמו שצריך.
מסגרת Android מספקת כמה פתרונות כדי לצמצם את הצורך בהודעות המרומזות האלה. לדוגמה, ה-API של JobScheduler מספק מנגנון חזק לתזמון פעולות ברשת כשמתקיימים תנאים מסוימים, כמו חיבור לרשת ללא הגבלת נפח. אפשר אפילו להשתמש ב-JobScheduler כדי להגיב לשינויים בספקים לניהול גישה.
מידע נוסף על אופטימיזציות ברקע ב-Android 7.0 (רמת API 24) ועל התאמת האפליקציה זמין במאמר אופטימיזציות ברקע.
שינויים בהרשאות
ב-Android 7.0 יש שינויים בהרשאות שעשויים להשפיע על האפליקציה שלכם.
שינויים בהרשאות של מערכת הקבצים
כדי לשפר את האבטחה של קבצים פרטיים, הגישה לספרייה הפרטית של אפליקציות שמטרגטות ל-Android בגרסה 7.0 ואילך מוגבלת (0700). ההגדרה הזו מונעת דליפה של מטא-נתונים של קבצים פרטיים, כמו הגודל שלהם או עצם קיומם. לשינוי ההרשאה הזה יש כמה השפעות:
-
הבעלים של קבצים פרטיים לא יכולים יותר להקל על ההרשאות לקבצים, וניסיון לעשות זאת באמצעות
MODE_WORLD_READABLEאוMODE_WORLD_WRITEABLEיפעילSecurityException.הערה: נכון לעכשיו, ההגבלה הזו לא נאכפת באופן מלא. אפליקציות עדיין יכולות לשנות את ההרשאות לספרייה הפרטית שלהן באמצעות ממשקי API מקוריים או ה-API של
File. עם זאת, אנחנו ממליצים מאוד לא להקל בהרשאות לספרייה הפרטית. -
העברת מזהי URI של
file://מחוץ לדומיין של החבילה עלולה להשאיר את המקבל עם נתיב לא נגיש. לכן, ניסיונות להעביר URI שלfile://מפעיליםFileUriExposedException. הדרך המומלצת לשתף את התוכן של קובץ פרטי היא באמצעותFileProvider. -
האפליקציה
DownloadManagerלא יכולה יותר לשתף קבצים שמאוחסנים באופן פרטי לפי שם הקובץ. אפליקציות מדור קודם עלולות להגיע לנתיב לא נגיש כשמנסים לגשת אלCOLUMN_LOCAL_FILENAME. אפליקציות שמטרגטות את Android בגרסה 7.0 ואילך מפעילותSecurityExceptionכשמנסים לגשת אלCOLUMN_LOCAL_FILENAME. אפליקציות מדור קודם שמגדירות את מיקום ההורדה למיקום ציבורי באמצעותDownloadManager.Request.setDestinationInExternalFilesDir()אוDownloadManager.Request.setDestinationInExternalPublicDir()עדיין יכולות לגשת לנתיב ב-COLUMN_LOCAL_FILENAME, אבל אנחנו ממליצים מאוד לא להשתמש בשיטה הזו. הדרך המועדפת לגשת לקובץ שחשוף על ידיDownloadManagerהיא באמצעותContentResolver.openFileDescriptor().
שיתוף קבצים בין אפליקציות
באפליקציות שמטרגטות את Android 7.0, מסגרת Android אוכפת את מדיניות ה-API של StrictMode שאוסרת על חשיפת מזהי URI של file:// מחוץ לאפליקציה. אם Intent שמכיל URI של קובץ יוצא מהאפליקציה, האפליקציה נכשלת עם חריגה של FileUriExposedException.
כדי לשתף קבצים בין אפליקציות, צריך לשלוח URI של content:// ולתת הרשאת גישה זמנית ל-URI. הדרך הכי קלה לתת את ההרשאה הזו היא באמצעות המחלקה FileProvider. מידע נוסף על הרשאות ושיתוף קבצים זמין במאמר בנושא שיתוף קבצים.
שיפורים בנגישות
ב-Android 7.0 יש שינויים שנועדו לשפר את נוחות השימוש בפלטפורמה למשתמשים עם ליקויי ראייה. בדרך כלל, השינויים האלה לא דורשים שינויים בקוד של האפליקציה, אבל כדאי לבדוק את התכונות האלה באפליקציה כדי להעריך את ההשפעות האפשריות על חוויית המשתמש.
שינוי מרחק התצוגה
ב-Android 7.0, המשתמשים יכולים להגדיר את גודל התצוגה, שמגדיל או מקטין את כל הרכיבים במסך, וכך משפר את הנגישות של המכשיר למשתמשים עם ליקויי ראייה. המשתמשים לא יכולים להגדיל את המסך מעבר לרוחב מסך מינימלי של sw320dp, שהוא הרוחב של Nexus 4, טלפון נפוץ בגודל בינוני.
איור 3. במסך שמשמאל מוצגת ההשפעה של הגדלת גודל התצוגה במכשיר שפועל עם קובץ אימג' של מערכת Android 7.0.
כשצפיפות המכשיר משתנה, המערכת מודיעה לאפליקציות שפועלות בדרכים הבאות:
- אם האפליקציה מטרגטת לרמת ה-API המיועדת 23 או פחות, המערכת סוגרת באופן אוטומטי את כל התהליכים שפועלים ברקע. כלומר, אם משתמש עובר מאפליקציה כזו כדי לפתוח את מסך ההגדרות ומשנה את ההגדרה גודל התצוגה, המערכת סוגרת את האפליקציה באותו אופן שבו היא הייתה עושה זאת במצב של זיכרון נמוך. אם לאפליקציה יש תהליכים שפועלים בחזית, המערכת מודיעה לתהליכים האלה על השינוי בהגדרות האישיות, כפי שמתואר במאמר טיפול בשינויים בזמן הריצה, בדיוק כמו במקרה של שינוי בכיוון המכשיר.
- אם אפליקציה מטרגטת ל-Android 7.0, כל התהליכים שלה (בחזית וברקע) מקבלים הודעה על השינוי בהגדרה, כפי שמתואר במאמר טיפול בשינויים בזמן הריצה.
ברוב האפליקציות לא צריך לבצע שינויים כדי לתמוך בתכונה הזו, בתנאי שהאפליקציות פועלות לפי השיטות המומלצות של Android. דברים ספציפיים שכדאי לבדוק:
- צריך לבדוק את האפליקציה במכשיר עם מסך ברוחב
sw320dpולוודא שהיא פועלת כמו שצריך. - כשתצורת המכשיר משתנה, צריך לעדכן את כל המידע ששמור במטמון ותלוי בצפיפות, כמו מפות סיביות (bitmap) ששמורות במטמון או משאבים שנטענים מהרשת. בודקים אם יש שינויים בהגדרות כשהאפליקציה ממשיכה לפעול אחרי שהושהתה.
הערה: אם אתם שומרים במטמון נתונים שתלויים בהגדרות האישיות, מומלץ לכלול מטא-נתונים רלוונטיים כמו גודל המסך או צפיפות הפיקסלים שמתאימים לנתונים האלה. שמירת המטא-נתונים האלה מאפשרת לכם להחליט אם אתם צריכים לרענן את הנתונים שנשמרו במטמון אחרי שינוי בהגדרות.
- אל תציינו מידות ביחידות px, כי הן לא משתנות בהתאם לצפיפות המסך. במקום זאת, ציינו את המידות ביחידות של פיקסלים שלא תלויים בצפיפות (
dp).
הגדרות הראייה באשף ההגדרה
ב-Android 7.0 יש הגדרות ראייה במסך הפתיחה, שבהן המשתמשים יכולים להגדיר את הגדרות בנושא נגישות הבאות במכשיר חדש: תנועת הגדלה, גודל גופן, גודל תצוגה ו-TalkBack. השינוי הזה מגביר את החשיפה של באגים שקשורים להגדרות מסך שונות. כדי להעריך את ההשפעה של התכונה הזו, כדאי לבדוק את האפליקציות כשההגדרות האלה מופעלות. ההגדרות נמצאות בקטע הגדרות > נגישות.
אפליקציות NDK שמקושרות לספריות של הפלטפורמה
החל מ-Android 7.0, המערכת מונעת מאפליקציות לקשר באופן דינמי לספריות שאינן NDK, מה שעלול לגרום לקריסת האפליקציה. מטרת השינוי הזה היא ליצור חוויית שימוש עקבית באפליקציה, גם כשמעדכנים את הפלטפורמה וגם כשמשתמשים במכשירים שונים. גם אם הקוד שלכם לא מקשר לספריות פרטיות, יכול להיות שספרייה סטטית של צד שלישי באפליקציה שלכם עושה את זה. לכן, כל המפתחים צריכים לוודא שהאפליקציות שלהם לא קורסות במכשירים עם Android 7.0. אם האפליקציה משתמשת בקוד Native, צריך להשתמש רק בממשקי API ציבוריים של NDK.
יש שלוש דרכים שבהן האפליקציה יכולה לנסות לגשת לממשקי API פרטיים של הפלטפורמה:
- האפליקציה ניגשת ישירות לספריות פרטיות של הפלטפורמה. צריך לעדכן את האפליקציה כך שתכלול עותק משלה של הספריות האלה, או להשתמש בממשקי ה-API הציבוריים של NDK.
- האפליקציה משתמשת בספריית צד שלישי שניגשת לספריות פרטיות של הפלטפורמה. גם אם אתם בטוחים שהאפליקציה שלכם לא ניגשת ישירות לספריות פרטיות, עדיין כדאי לבדוק את האפליקציה בתרחיש הזה.
- האפליקציה מפנה לספרייה שלא נכללת ב-APK שלה. לדוגמה, זה יכול לקרות אם ניסיתם להשתמש בעותק משלכם של OpenSSL אבל שכחתם לצרף אותו ל-APK של האפליקציה. יכול להיות שהאפליקציה תפעל כרגיל בגרסאות של פלטפורמת Android שכוללות את
libcrypto.so. עם זאת, האפליקציה עלולה לקרוס בגרסאות מתקדמות יותר של Android שלא כוללות את הספרייה הזו (למשל, Android 6.0 ואילך). כדי לפתור את הבעיה, צריך לוודא שכל הספריות שאינן NDK נכללות ב-APK.
אסור להשתמש באפליקציות בספריות Native שלא כלולות ב-NDK, כי הן עשויות להשתנות או להיות מוסרות בין גרסאות שונות של Android. המעבר מ-OpenSSL ל-BoringSSL הוא דוגמה לשינוי כזה. בנוסף, מכיוון שאין דרישות תאימות לספריות פלטפורמה שלא כלולות ב-NDK, מכשירים שונים עשויים להציע רמות תאימות שונות.
כדי לצמצם את ההשפעה של ההגבלה הזו על אפליקציות שכבר פורסמו, קבוצה של ספריות שנמצאות בשימוש נרחב – כמו libandroid_runtime.so, libcutils.so, libcrypto.so ו-libssl.so – נגישות באופן זמני ב-Android 7.0 (רמת API 24) לאפליקציות שמטרגטות את רמת ה-API המיועדת 23 או רמה נמוכה יותר. אם האפליקציה טוענת אחת מהספריות האלה, logcat יוצר אזהרה ומופיעה הודעה קצרה במכשיר היעד כדי להודיע לכם. אם מופיעות האזהרות האלה, צריך לעדכן את האפליקציה כך שתכלול עותק משלה של הספריות האלה, או להשתמש רק בממשקי ה-API הציבוריים של NDK. בגרסאות עתידיות של פלטפורמת Android, יכול להיות שהשימוש בספריות פרטיות יוגבל לחלוטין והאפליקציה תקרוס.
כל האפליקציות יוצרות שגיאת זמן ריצה כשהן קוראות ל-API שהוא לא ציבורי או נגיש באופן זמני. התוצאה היא שגם System.loadLibrary וגם dlopen(3) מחזירים את הערך NULL, וזה עלול לגרום לקריסה של האפליקציה. מומלץ לבדוק את קוד האפליקציה כדי להסיר את השימוש בממשקי API פרטיים של הפלטפורמה, ולבדוק ביסודיות את האפליקציות באמצעות מכשיר או אמולטור עם Android בגרסה 7.0 (רמת API 24). אם אתם לא בטוחים אם האפליקציה שלכם משתמשת בספריות פרטיות, אתם יכולים לבדוק את logcat כדי לזהות את שגיאת זמן הריצה.
בטבלה הבאה מתוארת ההתנהגות הצפויה של אפליקציה, בהתאם לשימוש שלה בספריות Native פרטיות ולרמת ה-API המיועדת שלה (android:targetSdkVersion).
| ספריות | רמת ה-API לטירגוט | גישה בזמן ריצה באמצעות מקשר דינמי | התנהגות ב-Android 7.0 (רמת API 24) | ההתנהגות העתידית של פלטפורמת Android |
|---|---|---|---|---|
| NDK Public | כל צבע | נגיש | פועלת כמצופה | פועלת כמצופה |
| פרטי (ספריות פרטיות שנגישות באופן זמני) | 23 או פחות | גישה זמנית | האפליקציה פועלת כמצופה, אבל מתקבלת אזהרת logcat. | שגיאת זמן ריצה |
| פרטי (ספריות פרטיות שנגישות באופן זמני) | 24 ומעלה | מוגבל | שגיאת זמן ריצה | שגיאת זמן ריצה |
| פרטי (אחר) | כל צבע | מוגבל | שגיאת זמן ריצה | שגיאת זמן ריצה |
איך בודקים אם האפליקציה משתמשת בספריות פרטיות
כדי לעזור לכם לזהות בעיות בטעינת ספריות פרטיות, יכול להיות ש-logcat ייצור אזהרה או שגיאת זמן ריצה. לדוגמה, אם האפליקציה מטרגטת את רמת API 23 או רמה נמוכה יותר, ומנסה לגשת לספרייה פרטית במכשיר עם Android 7.0, יכול להיות שתוצג אזהרה דומה לזו:
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120
האזהרות האלה ב-logcat מציינות איזו ספרייה מנסה לגשת ל-API פרטי של הפלטפורמה, אבל הן לא יגרמו לאפליקציה לקרוס. עם זאת, אם האפליקציה מטרגטת את רמת ה-API המיועדת 24 ומעלה, Logcat יוצר את שגיאת זמן הריצה הבאה והאפליקציה עלולה לקרוס:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by
"/system/lib/libnativeloader.so" is not accessible for the namespace
"classloader-namespace"
at java.lang.Runtime.loadLibrary0(Runtime.java:977)
at java.lang.System.loadLibrary(System.java:1602)
יכול להיות שפלט ה-logcat הזה יופיע גם אם האפליקציה משתמשת בספריות של צד שלישי שמקושרות באופן דינמי לממשקי API פרטיים של הפלטפורמה. הכלי readelf ב-Android 7.0 NDK מאפשר ליצור רשימה של כל הספריות המשותפות המקושרות באופן דינמי של קובץ .so נתון, על ידי הפעלת הפקודה הבאה:
aarch64-linux-android-readelf -dW libMyLibrary.so
עדכון האפליקציה
ריכזנו כאן כמה פעולות שאפשר לבצע כדי לתקן את השגיאות האלה ולוודא שהאפליקציה לא תקרוס בעדכוני פלטפורמה עתידיים:
- אם האפליקציה משתמשת בספריות פלטפורמה פרטיות, צריך לעדכן אותה כך שתכלול עותק משלה של הספריות האלה או להשתמש בממשקי ה-API הציבוריים של NDK.
- אם האפליקציה משתמשת בספריית צד שלישי שניגשת לסמלים פרטיים, צריך לפנות ליוצר הספרייה כדי לעדכן אותה.
- חשוב לוודא שכל הספריות שאינן NDK נכללות ב-APK.
- צריך להשתמש בפונקציות JNI רגילות במקום ב-
getJavaVMוב-getJNIEnvמ-libandroid_runtime.so:AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
- צריך להשתמש ב-
__system_property_getבמקום בסמל הפרטיproperty_getמ-libcutils.so. כדי לעשות את זה, משתמשים ב-__system_property_getעם ה-include הבא:#include <sys/system_properties.h>הערה: הזמינות והתוכן של מאפייני המערכת לא נבדקים באמצעות CTS. תיקון טוב יותר יהיה להימנע משימוש במאפיינים האלה בכלל.
- צריך להשתמש בגרסה מקומית של הסמל
SSL_ctrlמ-libcrypto.so. לדוגמה, צריך לקשר באופן סטטי אתlibcyrpto.aבקובץ.so, או לכלול גרסה מקושרת באופן דינמי שלlibcrypto.soמ-BoringSSL/OpenSSL ולכלול אותה בחבילה של ה-APK.
Android for Work
ב-Android 7.0 יש שינויים באפליקציות שמטרגטות את Android for Work, כולל שינויים בהתקנת אישורים, באיפוס סיסמאות, בניהול משתמשים משניים ובגישה למזהי מכשירים. אם אתם מפתחים אפליקציות לסביבות Android for Work, כדאי שתעיינו בשינויים האלה ותשנו את האפליקציה בהתאם.
- כדי שה-DPC יוכל להגדיר מתקין אישורים מורשה, צריך להתקין אותו. באפליקציות של פרופיל ושל בעלי מכשירים שמטרגטות את Android 7.0 (רמת API 24), צריך להתקין את מתקין האישורים שהוקצו לפני שהבקר לניהול מדיניות מכשירים (DPC) קורא ל-
DevicePolicyManager.setCertInstallerPackage(). אם תוכנת ההתקנה לא מותקנת, המערכת מקפיצה את השגיאהIllegalArgumentException. - הגבלות על איפוס סיסמאות של אדמינים במכשירים חלות עכשיו על בעלי פרופילים. מנהלי מכשירים לא יכולים יותר להשתמש ב-
DevicePolicyManager.resetPassword()כדי למחוק סיסמאות או לשנות סיסמאות שכבר הוגדרו. מנהלי מכשירים עדיין יכולים להגדיר סיסמה, אבל רק אם למכשיר אין סיסמה, קוד אימות או קו פתיחת נעילה. - בעלי מכשירים ופרופילים יכולים לנהל חשבונות גם אם הוגדרו הגבלות. בעלי מכשירים ובעלי פרופילים יכולים להפעיל את ממשקי ה-Account Management API גם אם חלות הגבלות על משתמשי
DISALLOW_MODIFY_ACCOUNTS. - בעלי המכשיר יכולים לנהל משתמשים משניים. כשמכשיר פועל במצב ניהול ברמת בעלים, ההגבלה
DISALLOW_ADD_USERמוגדרת באופן אוטומטי. ההגדרה הזו מונעת ממשתמשים ליצור משתמשים משניים לא מנוהלים. בנוסף, השיטותCreateUser()ו-createAndInitializeUser()הוצאו משימוש, והשיטה החדשהDevicePolicyManager.createAndManageUser()מחליפה אותן. - בעלי המכשיר יכולים לגשת למזהי המכשיר. בעלי המכשיר יכולים לגשת לכתובת ה-MAC של ה-Wi-Fi במכשיר באמצעות
DevicePolicyManager.getWifiMacAddress(). אם ה-Wi-Fi אף פעם לא הופעל במכשיר, השיטה הזו מחזירה את הערךnull. - ההגדרה "מצב עבודה" קובעת את הגישה לאפליקציות לעבודה. כשהמצב "בעבודה" מושבת, מרכז האפליקציות של המערכת מציין שהאפליקציות לעבודה לא זמינות על ידי הצגת הסמלים שלהן באפור. כדי לחזור לפעילות רגילה, צריך להפעיל שוב את מצב העבודה.
- כשמתקינים קובץ PKCS #12 שמכיל שרשרת אישורי לקוח ואת המפתח הפרטי התואם מממשק המשתמש של ההגדרות, אישור ה-CA בשרשרת לא מותקן יותר באחסון פרטי הכניסה המהימנים. השינוי הזה לא משפיע על התוצאה של
KeyChain.getCertificateChain()כשאפליקציות מנסות לאחזר את שרשרת אישורי הלקוח בשלב מאוחר יותר. אם צריך, אפשר להתקין את אישור ה-CA באחסון פרטי הכניסה המהימנים באמצעות ממשק המשתמש של ההגדרות בנפרד, בפורמט בקידוד DER עם סיומת קובץ .crt או .cer. - החל מ-Android 7.0, הרישום והאחסון של טביעות האצבע מנוהלים לכל משתמש בנפרד. אם ה-Device Policy Client (DPC) של בעלי הפרופיל מטרגט את רמת ה-API המיועדת 23 (או רמה נמוכה יותר) במכשיר עם Android 7.0 (רמת API 24), המשתמש עדיין יכול להגדיר טביעת אצבע במכשיר, אבל לאפליקציות העבודה אין גישה לטביעת האצבע במכשיר. כשה-DPC מטרגט את רמת ה-API המיועדת 24 ומעלה, המשתמש יכול להגדיר טביעת אצבע ספציפית לפרופיל העבודה דרך הגדרות > אבטחה > אבטחת פרופיל העבודה.
- הפונקציה
DevicePolicyManager.getStorageEncryptionStatus()מחזירה סטטוס הצפנה חדשENCRYPTION_STATUS_ACTIVE_PER_USER, שמציין שההצפנה פעילה ומפתח ההצפנה קשור למשתמש. הסטטוס החדש מוחזר רק אם ה-DPC מטרגט את רמת ה-API המיועדת 24 ומעלה. באפליקציות שמטרגטות רמות API מוקדמות יותר, מוחזר הערךENCRYPTION_STATUS_ACTIVE, גם אם מפתח ההצפנה ספציפי למשתמש או לפרופיל. - ב-Android 7.0, כמה שיטות שבדרך כלל משפיעות על כל המכשיר פועלות אחרת אם מותקן במכשיר פרופיל עבודה עם אימות נפרד. במקום להשפיע על כל המכשיר, השיטות האלה חלות רק על פרופיל העבודה. (הרשימה המלאה של השיטות האלה מופיעה במסמכי התיעוד של
DevicePolicyManager.getParentProfileInstance().) לדוגמה,DevicePolicyManager.lockNow()נועל רק את פרופיל העבודה, במקום לנעול את כל המכשיר. בכל אחת מהשיטות האלה, אפשר לקבל את ההתנהגות הישנה על ידי קריאה ל-method במופע ההורה שלDevicePolicyManager. אפשר לקבל את ההורה הזה על ידי קריאה ל-DevicePolicyManager.getParentProfileInstance(). לדוגמה, אם קוראים ל-methodlockNow()של המכונה הראשית, כל המכשיר ננעל.
שמירת הערות
ב-Android 7.0 תוקן באג שגרם להתעלמות מההגדרות של הרשאות הגישה להערות. הבעיה הזו אפשרה לסביבת זמן הריצה לגשת להערות שלא הייתה אמורה להיות לה גישה אליהן. ההערות האלה כללו:
-
VISIBILITY_BUILD: אמור להיות גלוי רק בזמן ה-build. -
VISIBILITY_SYSTEM: אמור להיות גלוי בזמן הריצה, אבל רק למערכת הבסיסית.
אם האפליקציה שלכם הסתמכה על ההתנהגות הזו, הוסיפו מדיניות שמירת נתונים להערות שצריכות להיות זמינות בזמן הריצה. כדי לעשות את זה, משתמשים ב-@Retention(RetentionPolicy.RUNTIME).
שינויים בהגדרות ברירת המחדל של TLS/SSL
ב-Android 7.0, בוצעו השינויים הבאים בהגדרת ברירת המחדל של TLS/SSL שמשמשת אפליקציות לתעבורת נתונים ב-HTTPS וב-TLS/SSL אחרים:
- הסטים של אלגוריתמים להצפנה מסוג RC4 מושבתים עכשיו.
- עכשיו מופעלים סטים של אלגוריתמים להצפנה מסוג CHACHA20-POLY1305.
אם RC4 מושבת כברירת מחדל, יכולות להיות תקלות בקישוריות של HTTPS או TLS/SSL כשהשרת לא מנהל משא ומתן על סטים מודרניים של אלגוריתמים להצפנה (cipher suite). התיקון המועדף הוא לשפר את הגדרות השרת כדי להפעיל פרוטוקולים וסטים של אלגוריתמים להצפנה (cipher suite) חזקים ומודרניים יותר. באופן אידיאלי, צריך להפעיל את TLSv1.2 ו-AES-GCM, ולהפעיל ולהעדיף סטים של אלגוריתמים להצפנה (cipher suite) מסוג סודיות העברה (ECDHE).
לחלופין, אפשר לשנות את האפליקציה כך שתשתמש ב-SSLSocketFactory בהתאמה אישית כדי לתקשר עם השרת. ה-factory צריך להיות מתוכנן ליצור מופעי SSLSocket שחלק מסט האלגוריתמים להצפנה (cipher suite) שנדרשים על ידי השרת מופעלים בהם, בנוסף לסט האלגוריתמים להצפנה שמוגדר כברירת מחדל.
הערה: השינויים האלה לא רלוונטיים ל-WebView.
אפליקציות שמטרגטות את Android 7.0
השינויים האלה בהתנהגות רלוונטיים רק לאפליקציות שמטרגטות ל-Android בגרסה 7.0 (רמת API 24) ומעלה. באפליקציות שמקומפלות ל-Android 7.0 או שהערך של targetSdkVersion בהן מוגדר ל-Android 7.0 ומעלה, צריך לשנות את האפליקציות כדי שהן יתמכו בהתנהגויות האלה כמו שצריך, במקרים הרלוונטיים לאפליקציה.
שינויים בסידור הפרקים
ב-Android 7.0 (רמת API 24) תוקן באג בחישוב של ברירת המחדל של serialVersionUID, שבו הוא לא תאם למפרט.
במחלקות שמטמיעות את Serializable
ולא מציינות שדה serialVersionUID מפורש,
יכול להיות שינוי ב-serialVersionUID שמוגדר כברירת מחדל. השינוי הזה יגרום להשלכת חריגה
כשמנסים לבטל סריאליזציה של מופעים של המחלקה שעברו סריאליזציה בגרסה קודמת, או שעברו סריאליזציה על ידי אפליקציה שמטרגטת גרסה קודמת. הודעת השגיאה תיראה בערך כך:
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
כדי לפתור את הבעיות האלה, צריך להוסיף שדה serialVersionUID לכל מחלקה שמושפעת, עם הערך של stream classdesc
serialVersionUID מהודעת השגיאה, למשל 1234 במקרה הזה. השינוי הזה תואם לכל ההמלצות לשיטות מומלצות לכתיבת קוד סריאליזציה, והוא יעבוד בכל הגרסאות של Android.
הבאג הספציפי שתוקן היה קשור לנוכחות של שיטות אתחול סטטיות, כלומר <clinit>. לפי המפרט, הנוכחות או ההיעדרות של מתודת מאתחל סטטי במחלקה ישפיעו על ברירת המחדל של serialVersionUID שמחושב עבור אותה מחלקה.
לפני תיקון הבאג, החישוב בדק גם את מחלקת העל של מאתחל סטטי אם למחלקה לא היה מאתחל סטטי.
כדי להבהיר, השינוי הזה לא משפיע על אפליקציות שמטרגטות לרמות API 23 ומטה, על מחלקות שיש להן שדה serialVersionUID או על מחלקות שיש להן שיטת אתחול סטטית.
נקודות חשובות נוספות
- כשאפליקציה פועלת ב-Android 7.0 אבל מטרגטת רמת API נמוכה יותר, והמשתמש משנה את גודל התצוגה, תהליך האפליקציה נפסק. האפליקציה צריכה להיות מסוגלת לטפל בתרחיש הזה בצורה חלקה. אחרת, היא תקרוס כשהמשתמש ישחזר אותה מהאפליקציות האחרונות.
חשוב לבדוק את האפליקציה כדי לוודא שההתנהגות הזו לא מתרחשת. כדי לעשות את זה, אפשר לגרום לקריסה זהה כשסוגרים את האפליקציה באופן ידני באמצעות DDMS.
אפליקציות שמטרגטות ל-Android 7.0 (רמת API 24) ומעלה לא נסגרות באופן אוטומטי כשצפיפות הפיקסלים משתנה, אבל יכול להיות שהן עדיין לא יגיבו טוב לשינויים בהגדרות.
- אפליקציות ב-Android 7.0 אמורות להיות מסוגלות לטפל בשינויים בהגדרות האישיות בצורה חלקה, ולא לקרוס בהפעלות הבאות. כדי לבדוק את התנהגות האפליקציה, אפשר לשנות את גודל הגופן (הגדרות > תצוגה > גודל גופן) ואז לשחזר את האפליקציה מהאפליקציות האחרונות.
-
בגלל באג בגרסאות קודמות של Android, המערכת לא סימנה כתיבה לשקע TCP בשרשור הראשי כהפרה של המצב הקפדני. ב-Android 7.0 הבאג הזה תוקן.
אפליקציות שמתנהגות ככה עכשיו זורקות
android.os.NetworkOnMainThreadException. באופן כללי, לא מומלץ לבצע פעולות ברשת ב-thread הראשי כי לפעולות האלה בדרך כלל יש זמן אחזור ארוך שגורם לשגיאות ANR ולתנודות בקצב הפריימים. -
כברירת מחדל, משפחת השיטות
Debug.startMethodTracing()שומרת עכשיו את הפלט בספרייה הספציפית לחבילה בנפח האחסון המשותף, במקום ברמה העליונה של כרטיס ה-SD. זה אומר שאפליקציות לא צריכות יותר לבקש את ההרשאהWRITE_EXTERNAL_STORAGEכדי להשתמש בממשקי ה-API האלה. -
הרבה ממשקי API של פלטפורמות התחילו לבדוק אם נשלחים מטענים ייעודיים (payloads) גדולים בעסקאות
Binder, והמערכת זורקת מחדש אתTransactionTooLargeExceptionsבתורRuntimeExceptions, במקום לתעד אותם ביומן או להשתיק אותם בלי להודיע. דוגמה נפוצה אחת היא אחסון של יותר מדי נתונים ב-Activity.onSaveInstanceState(), מה שגורם ל-ActivityThread.StopInfoלהציגRuntimeExceptionכשהאפליקציה מטרגטת ל-Android 7.0. -
אם אפליקציה מפרסמת משימות מסוג
Runnableב-View, ו-Viewלא מצורף לחלון, המערכת מוסיפה את המשימה מסוגRunnableלתור עםView. המשימה מסוגRunnableלא מבוצעת עד ש-Viewמצורף לחלון. ההתנהגות הזו מתקנת את הבאגים הבאים: -
אם אפליקציה ב-Android 7.0 עם ההרשאה
DELETE_PACKAGESמנסה למחוק חבילה, אבל אפליקציה אחרת התקינה את החבילה הזו, המערכת דורשת אישור מהמשתמש. בתרחיש הזה, האפליקציות צריכות לצפות לסטטוס החזרהSTATUS_PENDING_USER_ACTIONכשהן מפעילות אתPackageInstaller.uninstall(). - ספק ה-JCA שנקרא Crypto הוצא משימוש, כי האלגוריתם היחיד שלו, SHA1PRNG, חלש מבחינה קריפטוגרפית. אפליקציות לא יכולות יותר להשתמש ב-SHA1PRNG כדי להפיק מפתחות (באופן לא מאובטח), כי הספק הזה כבר לא זמין. למידע נוסף, קראו את הפוסט בבלוג Security "Crypto" provider deprecated in Android N.