בנוסף לתכונות וליכולות חדשות, Android 7.0 כולל מגוון שינויים בהתנהגות המערכת וב-API. במסמך הזה נתאר כמה מהשינויים העיקריים שחשוב להבין ולקחת בחשבון באפליקציות שלכם.
אם פרסמת בעבר אפליקציה ל-Android, חשוב לזכור שייתכן שהאפליקציה מושפעת מהשינויים האלה בפלטפורמה.
סוללה וזיכרון
גרסת Android 7.0 כוללת שינויים בהתנהגות המערכת שמטרתם לשפר את חיי הסוללה של המכשירים ולצמצם את השימוש ב-RAM. השינויים האלה יכולים להשפיע על גישת האפליקציה למשאבי המערכת, ועל האופן שבו האפליקציה מקיימת אינטראקציה עם אפליקציות אחרות באמצעות כוונות מרומזות מסוימות.
נמנום
התכונה Doze הוצגה ב-Android 6.0 (רמת API 23) ומאריכה את חיי הסוללה על ידי דחיית פעילויות של המעבד והרשת כשהמשתמש משאיר את המכשיר לא מחובר, נייח והמסך כבוי. ב-Android 7.0 נוספו שיפורים ל-Doze, שמופעלים קבוצת משנה של הגבלות על המעבד והרשת כשהמכשיר לא מחובר והמסך כבוי, אבל לא בהכרח נייח. לדוגמה, כשהמכשיר הנייד נמצא בכיס של המשתמש.
כשמכשיר פועל על סוללה והמסך כבוי במשך זמן מסוים, המכשיר עובר למצב Doze ומחילה את קבוצת המשנה הראשונה של ההגבלות: הוא משבית את הגישה של האפליקציות לרשת, ומעכב משימות וסנכרון. אם המכשיר נייח למשך זמן מסוים אחרי שהוא נכנס למצב Doze, המערכת מחילה את שאר ההגבלות של Doze על PowerManager.WakeLock
, על ההתראות של AlarmManager
, על ה-GPS ועל סריקות ה-Wi-Fi. לא משנה אם חלות חלק מההגבלות של מצב 'נמנום' או את כולן, המערכת מוציאה את המכשיר ממצב שינה לחלונות תחזוקה קצרים, שבמהלך התקופה הזו לאפליקציות מורשות
גישה לרשת ויכולה להפעיל משימות/סנכרונים שנדחו.
חשוב לזכור שהפעלת המסך או חיבור המכשיר מבטלים את מצב Doze ומבטלים את הגבלות העיבוד האלה. ההתנהגות הנוספת לא משפיעה על ההמלצות ועל השיטות המומלצות להתאמת האפליקציה לגרסה הקודמת של Doze שהושקה ב-Android 6.0 (רמת API 23), כפי שמתואר באופטימיזציה ל'נמנום' ול-App Standby. עדיין מומלץ לפעול לפי ההמלצות האלה, למשל להשתמש ב-Firebase Cloud Messaging (FCM) כדי לשלוח ולקבל הודעות, ולהתחיל לתכנן עדכונים בהתאם להתנהגות הנוספת של Doze.
Project 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.
אם האפליקציה שלכם משתמשת באחת מהכוונות האלה, עליכם להסיר את התלות בהן בהקדם האפשרי כדי שתוכלו לטרגט כראוי מכשירי 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
. עם זאת, אנחנו ממליצים מאוד לא להקל על ההרשאות בספרייה הפרטית. -
העברת URIs של
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, טלפון נפוץ בגודל בינוני.
כשהצפיפות במכשיר משתנה, המערכת מעדכנת את האפליקציות שפועלות בדרכים הבאות:
- אם אפליקציה מטרגטת רמת API 23 ומטה, המערכת משביתה באופן אוטומטי את כל תהליכי הרקע שלה. כלומר, אם משתמש יוצא מאפליקציה כזו כדי לפתוח את מסך ההגדרות ומשנה את ההגדרה גודל תצוגה, המערכת תרוג את האפליקציה באותו אופן שבו היא תסגור את האפליקציה במצב של מעט זיכרון. אם יש באפליקציה תהליכים בחזית, המערכת תודיע לתהליכים האלה על שינוי התצורה, כפי שמתואר בקטע טיפול בשינויים בסביבת זמן הריצה, בדיוק כמו אם כיוון המכשיר השתנה.
- אם אפליקציה מטרגטת את Android 7.0, כל התהליכים שלה (בחזית וברקע) יקבלו הודעה על שינוי התצורה, כפי שמתואר בקטע טיפול בשינויים בסביבת זמן הריצה.
ברוב האפליקציות אין צורך לבצע שינויים כדי לתמוך בתכונה הזו, בתנאי שהאפליקציות פועלות בהתאם לשיטות המומלצות ל-Android. דברים ספציפיים שכדאי לבדוק:
- בודקים את האפליקציה במכשיר עם רוחב מסך
sw320dp
ומוודאים שהיא פועלת כראוי. - כשהגדרות המכשיר משתנות, כדאי לעדכן את כל המידע שנשמר במטמון שתלוי בדחיסות, כמו מפות ביטים שנשמרו במטמון או משאבים שנטענו מהרשת. בודקים אם התרחשו שינויים בהגדרות כשהאפליקציה ממשיכה לפעול מהמצב שהושהה.
הערה: אם אתם שומרים במטמון נתונים שמוגדרים בהגדרות, מומלץ לכלול מטא-נתונים רלוונטיים כמו גודל המסך המתאים או צפיפות הפיקסלים של הנתונים האלה. שמירת המטא-נתונים האלה מאפשרת לכם להחליט אם צריך לרענן את הנתונים ששמורים במטמון אחרי שינוי בתצורה.
- מומלץ להימנע מהגדרת מידות ביחידות px, כי הן לא משתנות בהתאם לצפיפות המסך. במקום זאת, צריך לציין את המימדים ביחידות של פיקסלים שאינם תלויים בדחיסות (
dp
).
הגדרות הראייה באשף ההגדרה
ב-Android 7.0 יש הגדרות ראייה במסך הפתיחה, שבהן המשתמשים יכולים להגדיר את הגדרות הנגישות הבאות במכשיר חדש: תנועת הגדלה, גודל הגופן, גודל התצוגה ו-TalkBack. השינוי הזה מגדיל את החשיפה של באגים שקשורים להגדרות מסך שונות. כדי להעריך את ההשפעה של התכונה הזו, מומלץ לבדוק את האפליקציות כשההגדרות האלה מופעלות. ההגדרות מופיעות בקטע הגדרות > נגישות.
קישור אפליקציות NDK לספריות פלטפורמה
החל מ-Android 7.0, המערכת מונעת קישור דינמי של אפליקציות אל ספריות שאינן NDK. הקישור הזה עלול לגרום לקריסת האפליקציה. השינוי הזה נועד ליצור חוויית שימוש עקבית באפליקציה בכל עדכוני הפלטפורמה ובמכשירים שונים. גם אם הקוד שלכם לא מקשר לספריות פרטיות, יכול להיות שספרייה סטטית של צד שלישי באפליקציה שלכם עושה זאת. לכן, כל המפתחים צריכים לוודא שהאפליקציות שלהם לא קורסות במכשירים עם Android 7.0. אם באפליקציה נעשה שימוש בקוד נייטיב, צריך להשתמש רק בממשקי NDK ציבוריים.
יש שלוש דרכים שבהן האפליקציה שלכם עשויה לנסות לגשת לממשקי API פרטיים של פלטפורמות:
- האפליקציה שלכם ניגשת ישירות לספריות פרטיות של הפלטפורמה. עליכם לעדכן את האפליקציה כך שתכלול עותק משלה של הספריות האלה, או להשתמש בממשקי ה-API הציבוריים של NDK.
- האפליקציה שלכם משתמשת בספרייה של צד שלישי שמקבלת גישה לספריות פרטיות של פלטפורמות. גם אם אתם בטוחים שהאפליקציה שלכם לא ניגשת ישירות לספריות פרטיות, עדיין כדאי לבדוק את האפליקציה בתרחיש הזה.
- האפליקציה מפנה לספרייה שלא נכללת ב-APK שלה. לדוגמה, מצב כזה יכול לקרות אם ניסית להשתמש בעותק משלך של OpenSSL
אבל שכחת לצרף אותו ל-APK של האפליקציה. יכול להיות שהאפליקציה תפעל באופן תקין בגרסאות של פלטפורמת Android שכוללות את
libcrypto.so
. עם זאת, האפליקציה עלולה לקרוס בגרסאות מאוחרות יותר של Android שלא כוללות את הספרייה הזו (למשל, Android 6.0 ואילך). כדי לפתור את הבעיה, צריך לוודא שכל הספריות שאינן NDK נכללות בחבילת ה-APK.
לא מומלץ להשתמש באפליקציות בספריות מקומיות שלא נכללות ב-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 כדי לזהות את שגיאת זמן הריצה.
בטבלה הבאה מתוארת ההתנהגות שצפוי להתרחש באפליקציה, בהתאם לשימוש בספריות נייטיב פרטיות וברמת ה-API לטירגוט של האפליקציה (android:targetSdkVersion
).
ספריות | רמת ה-API לטירגוט | גישה בסביבת זמן ריצה באמצעות קישור דינמי | התנהגות ב-Android 7.0 (רמת API 24) | התנהגות עתידית של פלטפורמת Android |
---|---|---|---|---|
NDK ציבורי | כל צבע | נגיש | פועלת כמצופה | פועלת כמצופה |
פרטית (ספריות פרטיות נגישות באופן זמני) | 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.0DK מאפשר ליצור רשימה של כל הספריות המשותפות המקושרות באופן דינמי בקובץ .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 <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()
כדי למחוק סיסמאות או לשנות סיסמאות שכבר מוגדרות. אדמינים של מכשירים עדיין יכולים להגדיר סיסמה, אבל רק אם אין במכשיר סיסמה, קוד אימות או קו ביטול נעילה. - הבעלים של המכשיר ושל הפרופיל יכולים לנהל את החשבונות גם אם מוגדרות הגבלות. בעלי המכשיר ובעלי הפרופילים יכולים להפעיל את ממשקי ה-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 - החל מגרסה 7.0 של Android, הרישום והאחסון של טביעות האצבע מנוהלים לכל משתמש בנפרד. אם לקוח מדיניות המכשיר (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()
. לדוגמה, אם קוראים לשיטהlockNow()
של המכונה ההורה, כל המכשיר נעול.
שמירת הערות
ב-Android 7.0 תוקן באג שגרם לכך שהמערכת התעלמה מההסתרה של ההערות. הבעיה הזו אפשרה לסביבת זמן הריצה לגשת להערות שלא הייתה אמורה לגשת אליהן. ההערות האלה כללו:
VISIBILITY_BUILD
: מיועד להיות גלוי רק בזמן ה-build.VISIBILITY_SYSTEM
: נועדו להיות גלויים בזמן הריצה, אבל רק למערכת הבסיסית.
אם האפליקציה שלך הסתמכה על ההתנהגות הזו, צריך להוסיף מדיניות שמירת נתונים להערות שחייבות להיות זמינות בזמן הריצה. אפשר לעשות את זה באמצעות @Retention(RetentionPolicy.RUNTIME)
.
שינויים בהגדרות ברירת המחדל של TLS/SSL
ב-Android 7.0 מתבצעים השינויים הבאים בהגדרות ברירת המחדל של TLS/SSL (אבטחת שכבת התעבורה)/SSL, שמשמשות אפליקציות ל-HTTPS ולתנועת TLS/SSL אחרת:
- סטים של אלגוריתמים להצפנה (cipher suite) מסוג RC4 מושבתים עכשיו.
- סטים של אלגוריתמים להצפנה (cipher suite) מסוג CHACHA20-POLY1305 מופעלים עכשיו.
השבתת RC4 כברירת מחדל עלולה לגרום לשיבושים בחיבור HTTPS או TLS/SSL אם השרת לא מנהל משא ומתן על סט אלגוריתמים מודרני להצפנה. התיקון המועדף הוא לשפר את ההגדרות של השרת כדי לאפשר שימוש בפרוטוקולים ובחבילות הצפנה חזקים ומודרניים יותר. באופן אידיאלי, צריך להפעיל את TLSv1.2 ואת AES-GCM, וגם להפעיל את חבילות ההצפנה של Forward Secrecy (ECDHE) ולהעדיף אותן.
לחלופין, אפשר לשנות את האפליקציה כך שתשתמש ב-SSLSocketFactory
בהתאמה אישית כדי לתקשר עם השרת. המפעל צריך להיות מתוכנן כך שיוצר מכונות SSLSocket
שבהן חלק מחבילות הצפנה שנדרשות לשרת מופעלות בנוסף לחבילות הצפנה שמוגדרות כברירת מחדל.
הערה: השינויים האלה לא רלוונטיים ל-WebView
.
אפליקציות שמטרגטות את Android מגרסה 7.0
השינויים האלה בהתנהגות חלים רק על אפליקציות שמטרגטות
ל-Android 7.0 (רמת API 24) ואילך. באפליקציות שעברו הידור (compile) ל-Android 7.0,
או שמגדירים את targetSdkVersion
ל-Android 7.0 ואילך, חייבים לשנות
את האפליקציות שלהן כך שיתמכו בהתנהגויות האלה באופן תקין, במקרים שבהם הן רלוונטיות לאפליקציה.
שינויים בעריכה בסדרה
מערכת Android 7.0 (רמת API 24) תיקנה באג בחישוב של ה-resisVersionUID שמוגדר כברירת מחדל, כאשר הוא לא תואם למפרט.
בכיתות שמטמיעות את Serializable
ולא מציינות שדה serialVersionUID
מפורש, יכול להיות שיהיה שינוי ב-serialVersionUID שמוגדר כברירת מחדל, וכתוצאה מכך תופיע חריגה כשמנסים לבצע דה-סריאליזציה של מכונות מהקלאס שהומרו לסריאליזציה בגרסה קודמת או שהומרו לסריאליזציה על ידי אפליקציה שמטרגטת גרסה קודמת. הודעת השגיאה תיראה בערך כך:
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
כדי לפתור את הבעיות האלה, צריך להוסיף שדה serialVersionUID
לכל כיתה שהושפעה עם הערך stream classdesc
serialVersionUID
מהודעת השגיאה, למשל 1234
במקרה הזה. השינוי הזה עומד בכל ההמלצות לשיטות מומלצות לכתיבת קוד שרשור, והוא יפעל בכל הגרסאות של Android.
הבאג הספציפי שתוקן היה קשור לנוכחות של שיטות מאתחל סטטיות, כלומר <clinit>
. לפי המפרט, נוכחות או היעדר של שיטת initializer סטטית בכיתה ישפיעו על 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 רבים של פלטפורמות התחילו לבדוק אם נשלחים עומסי נתונים גדולים בעסקאות
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.