שינויים ב-Android 6.0

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

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

הרשאות בזמן ריצה

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

באפליקציות שמטרגטות את Android 6.0 (רמת API ‏23) ואילך, חשוב לבדוק ולבקש הרשאות במהלך זמן הריצה. כדי לבדוק אם לאפליקציה הוענקה הרשאה, צריך לבצע קריאה ל-method החדש checkSelfPermission(). כדי לבקש הרשאה, צריך להפעיל את השיטה החדשה requestPermissions(). גם אם האפליקציה שלכם לא מטרגטת את Android 6.0 (רמת API ‏23), כדאי לבדוק אותה לפי מודל ההרשאות החדש.

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

מצב 'נמנום' ו'אפליקציה במצב המתנה'

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

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

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

הסרה של לקוח HTTP של Apache

במהדורה 6.0 של Android הוסרה התמיכה בלקוח ה-HTTP של Apache. אם האפליקציה שלכם משתמשת בלקוח הזה ומטרגטת את Android מגרסה 2.3 (רמת API 9) ואילך, השתמשו במקום זאת בכיתה HttpURLConnection. ה-API הזה יעיל יותר כי הוא מצמצם את השימוש ברשת באמצעות דחיסת נתונים שקופה ואחסון בתגובה במטמון, ומצמצם את צריכת החשמל. כדי להמשיך להשתמש בממשקי ה-API של Apache HTTP, קודם צריך להצהיר על התלות הבאה בזמן הידור בקובץ build.gradle:

android {
    useLibrary 'org.apache.http.legacy'
}

BoringSSL

Android עוברת מ-OpenSSL לספרייה BoringSSL. אם באפליקציה שלכם משתמשים ב-Android NDK, אסור לקשר לספריות קריפטוגרפיות שהן לא חלק מ-NDK API, כמו libcrypto.so ו-libssl.so. הספריות האלה הן לא ממשקי API ציבוריים, ויכול להיות שהן ישתנו או ייפגע התפקוד שלהן ללא הודעה מוקדמת בגרסאות ובמכשירים שונים. בנוסף, אתם עלולים לחשוף את עצמכם לנקודות חולשה באבטחה. במקום זאת, אפשר לשנות את קוד המקור כך שיקרא לממשקי ה-API לקריפטוגרפיה של Java דרך JNI או כדי לקשר באופן סטטי לספריית קריפטוגרפיה לבחירתכם.

גישה למזהה החומרה

כדי לספק למשתמשים הגנה טובה יותר על הנתונים, החל מהגרסה הזו, מערכת Android מסירה את הגישה הפרוגרמטית למזהה החומרה המקומי של המכשיר לאפליקציות שמשתמשות בממשקי ה-API של Wi-Fi ו-Bluetooth. השיטות WifiInfo.getMacAddress() ו-BluetoothAdapter.getAddress() מחזירות עכשיו ערך קבוע של 02:00:00:00:00:00.

כדי לגשת למזהי החומרה של מכשירים חיצוניים בקרבת מקום באמצעות סריקות Bluetooth ו-Wi-Fi, לאפליקציה צריכות להיות עכשיו ההרשאות ACCESS_FINE_LOCATION או ACCESS_COARSE_LOCATION:

הערה: כשמכשיר עם Android 6.0 (רמת API‏ 23) מפעיל סריקת Wi-Fi או Bluetooth ברקע, המכשיר מוגדר למכשירים חיצוניים כמקור של כתובת MAC אקראית.

התראות

בגרסה הזו הוסר השיטה Notification.setLatestEventInfo(). במקום זאת, משתמשים בכיתה Notification.Builder כדי ליצור התראות. כדי לעדכן התראה שוב ושוב, משתמשים מחדש במכונה Notification.Builder. קוראים ל-method‏ build() כדי לקבל מכונות Notification מעודכנות.

הפקודה adb shell dumpsys notification כבר לא מדפיסה את טקסט ההתראה. במקום זאת, משתמשים בפקודה adb shell dumpsys notification --noredact כדי להדפיס את הטקסט באובייקט ההתראה.

שינויים ב-AudioManager

אין יותר תמיכה בהגדרת עוצמת הקול ישירות או בהשתקת שידורים ספציפיים באמצעות הכיתה AudioManager. השיטה setStreamSolo() הוצאה משימוש. במקום זאת, צריך לבצע קריאה ל-method‏ requestAudioFocus(). באופן דומה, השיטה setStreamMute() הוצאה משימוש. במקום זאת, צריך להפעיל את השיטה adjustStreamVolume() ולהעביר את ערך הכיוון ADJUST_MUTE או ADJUST_UNMUTE.

בחירת טקסט

מסך שבו מוצגות תכונות חדשות לבחירת טקסט בתוך סרגל כלים צף

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

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

  1. באובייקט View או Activity, משנים את הקריאות ל-ActionMode מ-startActionMode(Callback) ל-startActionMode(Callback, ActionMode.TYPE_FLOATING).
  2. צריך לקחת את ההטמעה הקיימת של ActionMode.Callback ולהרחיב אותה ל-ActionMode.Callback2 במקום זאת.
  3. משנים את השיטה onGetContentRect() כדי לספק את הקואורדינטות של אובייקט התוכן Rect (כמו מלבן של טקסט שנבחר) בתצוגה.
  4. אם מיקום המלבן כבר לא תקין, וזה הרכיב היחיד שהתוקף שלו בוטל, צריך לבצע קריאה לשיטה invalidateContentRect().

אם אתם משתמשים בגרסה 22.2 של Android Support Library, חשוב לדעת שסרגל כלים צף לא תואם לאחור, ו-appcompat מקבלת שליטה על אובייקטים מסוג ActionMode כברירת מחדל. כך לא יוצגו סרחי כלים צפים. כדי להפעיל את התמיכה ב-ActionMode ב-AppCompatActivity, קוראים ל-getDelegate() ואז קוראים ל-setHandleNativeActionModesEnabled() באובייקט AppCompatDelegate שמוחזר ומגדירים את פרמטר הקלט ל-false. הקריאה הזו מחזירה ל-framework את השליטה על אובייקטים של ActionMode. במכשירים עם Android 6.0 (רמת API‏ 23), המסגרת תומכת במצבים ActionBar או בסרגל כלים צף. במכשירים עם Android 5.1 (רמת API‏ 22) ומטה, המסגרת תומכת רק במצבים ActionBar.

שינויים בסימנייה בדפדפן

הגרסה הזו מסירה את התמיכה בסימניות גלובליות. השיטות android.provider.Browser.getAllBookmarks() ו-android.provider.Browser.saveBookmark() הוסרו. באותו אופן, ההרשאות READ_HISTORY_BOOKMARKS ו-WRITE_HISTORY_BOOKMARKS מוסרות. אם האפליקציה שלכם מטרגטת ל-Android 6.0 (רמת API ‏23) ואילך, אל תיגשו לסימניות מהספק הגלובלי ואל תשתמשו בהרשאות של הסימניות. במקום זאת, האפליקציה צריכה לאחסן את נתוני הסימניות באופן פנימי.

שינויים ב-Android Keystore

בגרסה הזו, ספק Android Keystore לא תומך יותר ב-DSA. עדיין יש תמיכה ב-ECDSA.

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

שינויים ב-Wi-Fi וברשתות

בגרסה הזו נוספו השינויים הבאים בהתנהגות של ממשקי ה-API של Wi-Fi ושל הרשתות.

  • מעכשיו, האפליקציות שלכם יכולות לשנות את המצב של אובייקטים מסוג WifiConfiguration רק אם אתם יצרתם את האובייקטים האלה. אסור לשנות או למחוק אובייקטים של WifiConfiguration שנוצרו על ידי המשתמש או על ידי אפליקציות אחרות.
  • בעבר, אם אפליקציה אילצה את המכשיר להתחבר לרשת Wi-Fi ספציפית באמצעות enableNetwork() עם ההגדרה disableAllOthers=true, המכשיר התנתק מרשתות אחרות כמו נתונים סלולריים. בגרסה הזו, המכשיר כבר לא מתנתק מרשתות כאלה. אם הערך של targetSdkVersion של האפליקציה הוא “20” או נמוך יותר, היא תוצמד לרשת ה-Wi-Fi שנבחרה. אם הערך של targetSdkVersion של האפליקציה הוא “21” ומעלה, צריך להשתמש בממשקי ה-API לרשתות מרובות (כמו openConnection(),‏ bindSocket() והשיטה החדשה bindProcessToNetwork()) כדי לוודא שתנועת הרשת של האפליקציה נשלחת ברשת שנבחרה.

שינויים בשירות המצלמה

בגרסה הזו, המודל לגישה למשאבים משותפים בשירות המצלמה השתנה מהמודל הקודם של 'כל הקודם זוכה' למודל גישה שבו ניתנת עדיפות לתהליכים בעדיפות גבוהה. שינויים בהתנהגות השירות כוללים:

  • הגישה למשאבי מערכת המשנה של המצלמה, כולל פתיחה והגדרה של מכשיר מצלמה, ניתנת על סמך ה'עדיפות' של תהליך אפליקציית הלקוח. בדרך כלל, תהליכי אפליקציות עם פעילויות שגלויות למשתמש או פעילויות בחזית מקבלים עדיפות גבוהה יותר, כך שהשימוש במשאבי המצלמה והשגתם יהיו מהימנים יותר.
  • לקוחות מצלמה פעילים של אפליקציות עם עדיפות נמוכה יותר עשויים להיות 'מודחים' כשאפליקציה עם עדיפות גבוהה יותר מנסה להשתמש במצלמה. בממשק ה-API הוצא משימוש Camera, הקריאה ל-onError() מתבצעת עבור הלקוח שהוצא. ב-API של Camera2, התוצאה תהיה קריאה ל-onDisconnected() עבור הלקוח שסולק.
  • במכשירים עם חומרת מצלמה מתאימה, אפשר לפתוח תהליכים נפרדים של אפליקציות כדי לפתוח התקני מצלמה נפרדים ולהשתמש בהם בו-זמנית. עם זאת, שירות המצלמה מזהה עכשיו מקרים של שימוש במספר תהליכים, שבהם גישה בו-זמנית גורמת לירידה משמעותית בביצועים או ביכולות של כל אחד ממכשירי המצלמה הפתוחים, ומסרב לאשר אותם. השינוי הזה עלול להוביל ל'פינוי' של לקוחות בעדיפות נמוכה, גם אם אף אפליקציה אחרת לא מנסה באופן ישיר לגשת לאותו מכשיר מצלמה.
  • שינוי המשתמש הנוכחי גורם להוצאה של לקוחות מצלמה פעילים באפליקציות שבבעלות חשבון המשתמש הקודם. הגישה למצלמה מוגבלת לפרופילים של משתמשים שבבעלות משתמש המכשיר הנוכחי. בפועל, המשמעות היא שלחשבון 'אורח', לדוגמה, לא תהיה אפשרות להשאיר תהליכים שפועלים ומשתמשים במערכת המשנה של המצלמה כשהמשתמש עובר לחשבון אחר.

זמן ריצה

זמן הריצה של ART מיישם עכשיו כללי גישה ל-method newInstance() באופן תקין. השינוי הזה מתקן בעיה שבה Dalvik בדק את כללי הגישה בצורה שגויה בגרסאות קודמות. אם האפליקציה שלכם משתמשת ב-method‏ newInstance() ואתם רוצים לשנות את בדיקות הגישה, צריך לבצע קריאה ל-method‏ setAccessible() עם הפרמטר של הקלט מוגדר כ-true. אם האפליקציה שלכם משתמשת בספריית v7 appcompat או בספריית v7 recyclerview, עליכם לעדכן את האפליקציה כך שתשתמש בגרסאות האחרונות של הספריות האלה. אחרת, צריך לוודא שכל הכיתות בהתאמה אישית שמפונות מה-XML מעודכנות כך שאפשר יהיה לגשת למבני הכיתות שלהן.

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

הדגל dlopen(3) RTLD_LOCAL הוטמע עכשיו בצורה נכונה. הערה: RTLD_LOCAL היא ברירת המחדל, כך שקריאות ל-dlopen(3) שלא השתמשו במפורש ב-RTLD_LOCAL יושפעו (אלא אם האפליקציה שלך השתמשה באופן מפורש ב-RTLD_GLOBAL). עם RTLD_LOCAL, הסמלים לא יהיו זמינים לספריות שנטענות על ידי קריאות מאוחרות יותר ל-dlopen(3) (בניגוד לרשומות של DT_NEEDED שמפנות אליהן).

בגרסאות קודמות של Android, אם האפליקציה ביקשה מהמערכת לטעון ספרייה משותפת עם העברת טקסט, המערכת הציגה אזהרה אבל עדיין אפשרה לטעון את הספרייה. החל מהגרסה הזו, המערכת דוחה את הספרייה הזו אם גרסת ה-SDK של האפליקציה היא 23 ואילך. כדי לזהות אם ספרייה לא נטענה, האפליקציה צריכה לתעד ביומן את הכישלון של dlopen(3), ולכלול את הטקסט של תיאור הבעיה שמוחזר על ידי הקריאה dlerror(3). מידע נוסף על טיפול בהעברת טקסט מופיע במדריך הזה.

אימות של קובץ APK

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

חיבור USB

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

שינויים ב-Android for Work

הגרסה הזו כוללת את השינויים הבאים בהתנהגות של Android for Work:

  • אנשי קשר בעבודה בהקשרים אישיים. ביומן השיחות של Google Dialer מוצגים עכשיו אנשי קשר מהעבודה כשהמשתמשים צופים בשיחות הקודמות. אם מגדירים את setCrossProfileCallerIdDisabled() לערך true, אנשי הקשר בפרופיל העבודה מוסתרים ביומן השיחות של Google Dialer. אפשר להציג את אנשי הקשר בעבודה לצד אנשי הקשר האישיים במכשירים דרך Bluetooth רק אם מגדירים את setBluetoothContactSharingDisabled() לערך false. כברירת מחדל, הוא מוגדר כ-true.
  • הסרת הגדרות Wi-Fi: הגדרות Wi-Fi שנוספו על ידי הבעלים של הפרופיל (לדוגמה, באמצעות קריאות ל-method‏ addNetwork()) יוסרו עכשיו אם פרופיל העבודה הזה יימחק.
  • נעילה של הגדרות Wi-Fi: הגדרות Wi-Fi שנוצרו על ידי בעלים פעיל של מכשיר לא יוכלו יותר לשנות או למחוק אותן אם הערך של WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN הוא לא אפס. המשתמש עדיין יכול ליצור ולשנות הגדרות Wi-Fi משלו. לבעלי המכשיר הפעילים יש הרשאה לערוך או להסיר הגדרות Wi-Fi, כולל הגדרות שלא הם יצרו.
  • הורדת אמצעי בקרה על מדיניות המכשיר באמצעות הוספת חשבון Google: כשחשבון Google שמחייב ניהול דרך אפליקציית אמצעי בקרה על מדיניות המכשיר (DPC) מתווסף למכשיר מחוץ להקשר המנוהל, תהליך הוספת החשבון מאפשר עכשיו למשתמש להתקין את אמצעי הבקרה המתאים. ההתנהגות הזו חלה גם על חשבונות שנוספו דרך הגדרות > חשבונות ובאשף ההגדרה הראשונית של המכשיר.
  • שינויים בהתנהגויות ספציפיות של DevicePolicyManager API:
    • קריאה ל-method‏ setCameraDisabled() משפיעה על המצלמה של המשתמש שמבצע את הקריאה בלבד. קריאה ל-method מהפרופיל המנוהל לא משפיעה על אפליקציות המצלמה שפועלות אצל המשתמש הראשי.
    • בנוסף, השיטה setKeyguardDisabledFeatures() זמינה עכשיו לבעלי פרופילים וגם לבעלי מכשירים.
    • הבעלים של הפרופיל יכול להגדיר את ההגבלות הבאות על מסך הנעילה:
    • השיטות DevicePolicyManager.createAndInitializeUser() ו-DevicePolicyManager.createUser() הוצאו משימוש.
    • השיטה setScreenCaptureDisabled() חוסמת עכשיו גם את מבנה העזרה כשאפליקציה של המשתמש הנתון נמצאת בחזית.
    • ברירת המחדל של EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM היא SHA-256. עדיין יש תמיכה ב-SHA-1 לצורך תאימות לאחור, אבל היא תוסר בעתיד. EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM מתקבל עכשיו רק SHA-256.
    • ממשקי ה-API להפעלת מכשיר שהיו קיימים ב-Android 6.0 (רמת API ‏23) הוסרו.
    • EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS הוסר כדי שאי אפשר יהיה לבצע באופן פרוגרמטי ביטול נעילה של מכשיר שמוגן באמצעות איפוס להגדרות היצרן באמצעות תצורה באמצעות מגע NFC.
    • עכשיו אפשר להשתמש ב-EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE כדי להעביר נתונים לאפליקציה של בעלי המכשיר במהלך הקצאת NFC למכשיר המנוהל.
    • ממשקי ה-API של Android for Work מותאמים להרשאות בסביבת זמן ריצה של M, כולל פרופילים לעבודה, שכבת עזרה ועוד. ממשקי ה-API החדשים של ההרשאות DevicePolicyManager לא משפיעים על אפליקציות מדור קודם.
    • כשמשתמשים יוצאים מהחלק הסינכרוני של תהליך ההגדרה שהתחיל באמצעות כוונה מסוג ACTION_PROVISION_MANAGED_PROFILE או ACTION_PROVISION_MANAGED_DEVICE, המערכת מחזירה עכשיו את קוד התוצאה RESULT_CANCELED.
  • שינויים בממשקי API אחרים:
    • שימוש בנתונים: שם הכיתה android.app.usage.NetworkUsageStats השתנה ל-NetworkStats.
  • שינויים בהגדרות הגלובליות: