שינויים בהתנהגות ב-Android 8.0

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

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

שינויים בכל האפליקציות

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

מגבלות ביצוע ברקע

אחד מהשינויים שמערכת Android 8.0 (רמת API 26) כוללת לשיפור חיי הסוללה, כשהאפליקציה נכנסת במטמון ללא פעילות רכיבים, המערכת משחררת את כל המנעולים של מצב שינה שהאפליקציה מחזיקה.

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

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

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

Android 8.0 (רמת API 26) כולל גם את השינויים הבאים בשיטות ספציפיות:

  • השיטה startService() גורמת עכשיו IllegalStateException אם אפליקציה שמטרגט את Android 8.0, המערכת מנסה להשתמש בשיטה הזו במצב שבו אסור ליצור שירותים שפועלים ברקע.
  • השיטה החדשה Context.startForegroundService() מפעילה שירות שפועל בחזית. המערכת מאפשרת לאפליקציות כדי להתקשר אל Context.startForegroundService() גם כשהאפליקציה ברקע. עם זאת, האפליקציה חייבת לקרוא ל-method של startForeground() של השירות בתוך חמש שניות לאחר יצירת השירות.

מידע נוסף זמין במאמר הבא: מגבלות ביצוע ברקע.

מגבלות מיקום ברקע ב-Android

כדי לשמור על תקינות הסוללה, חוויית המשתמש ותקינות המערכת, אפליקציות ברקע מקבלות עדכוני מיקום בתדירות נמוכה יותר כשמשתמשים במכשיר עם Android 8.0. השינוי הזה בהתנהגות ישפיע על כל האפליקציות שמקבלים עדכוני מיקום, כולל Google Play Services.

השינויים האלה ישפיעו על ממשקי ה-API הבאים:

  • ספק מיקום משולב (FLP)
  • גבולות וירטואליים
  • מדידות GNSS
  • מנהל מיקומים
  • מנהל Wi-Fi

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

  • בדקו את הלוגיקה של האפליקציה וודאו שאתם משתמשים במיקום העדכני ביותר ממשקי API.
  • צריך לבדוק שהאפליקציה מציגה את ההתנהגות שלך בכל שימוש מותאמת אישית.
  • מומלץ להשתמש מיזוג ספק מיקום (FLP) או הגדרת גבולות וירטואליים לצורך טיפול בתרחישים לדוגמה התלויים המיקום הנוכחי של המשתמש.

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

קיצורי דרך של אפליקציות

Android 8.0 (רמת API 26) כולל את השינויים הבאים במקשי קיצור של אפליקציות:

  • מספר השידור של com.android.launcher.action.INSTALL_SHORTCUT אין יותר השפעה על האפליקציה שלך, כי היא מוגדרת עכשיו כפרטית ומרומזת שידור. במקום זאת, כדאי ליצור קיצור דרך לאפליקציה באמצעות requestPinShortcut() מהמחלקה ShortcutManager.
  • ACTION_CREATE_SHORTCUT Intent יכול עכשיו ליצור קיצורי דרך לאפליקציות שאתם מנהלים באמצעות כיתה אחת (ShortcutManager). הכוונה הזו יכולה גם ליצור מקשי קיצור מדור קודם במרכז האפליקציות שלא יוצרים איתם אינטראקציה ShortcutManager בעבר, הכוונה הזו הייתה יכולה ליצור רק קיצורי דרך מדור קודם למרכז האפליקציות.
  • קיצורי דרך שנוצרו באמצעות requestPinShortcut() וקיצורי דרך שנוצרו בפעילות שמטפלת ACTION_CREATE_SHORTCUT Intent הם עכשיו מקשי קיצור מלאים לאפליקציות. לכן, עכשיו אפליקציות יכולות לעדכן אותן באמצעות השיטות ב-ShortcutManager.
  • מקשי הקיצור הקודמים שומרים על הפונקציונליות שלהם מגרסאות קודמות של ב-Android, אבל צריך להמיר אותם לקיצורי דרך של אפליקציות באופן ידני באפליקציה.

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

לוקאלים ובינלאומיות

ב-Android 7.0 (רמת API 24) נוסף הקונספט של יכולת לציין לוקאל קטגוריה שמוגדר כברירת מחדל, אבל חלק מממשקי ה-API המשיכו להשתמש Locale.getDefault() כללי method, ללא ארגומנטים, כאשר הם היו אמורים להשתמש במקום זאת בלוקאל של קטגוריית ברירת המחדל DISPLAY. ב-Android 8.0 (רמת API 26), הפרמטר השיטות הבאות משתמשות עכשיו ב-Locale.getDefault(Category.DISPLAY) במקום Locale.getDefault():

Locale.getDisplayScript(Locale) גם חוזר אל Locale.getDefault() כאשר צוין ערך displayScript עבור Locale הארגומנט לא זמין.

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

  • אם מתקשרים אל Currency.getDisplayName(null), מקבלים NullPointerException, תואמת להתנהגות שתועדה.
  • ניתוח השם של אזור הזמן השתנה. בעבר, מכשירי Android השתמשו בערך של שעון המערכת שנדגם בזמן ההפעלה זמן לשמירה במטמון של שמות אזורי הזמן ששימשו לניתוח התאריך פעמים. כתוצאה מכך, הניתוח עלול להיפגע אם המערכת השעון היה שגוי בזמן האתחול או במקרים אחרים, נדירים יותר.

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

  • מערכת Android 8.0 (רמת API 26) מעדכנת את גרסת ICU לגרסה 58.

חלונות התראות

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

...החלונות האלה מופיעים תמיד מתחת לחלונות שמשתמשים בהם חלון TYPE_APPLICATION_OVERLAY מהסוג הזה. אם אפליקציה מטרגטת ל-Android 8.0 (רמת API 26), האפליקציה משתמשת ב TYPE_APPLICATION_OVERLAY סוג החלון להצגת חלונות התראות.

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

קלט וניווט

בעקבות ההשקה של אפליקציות ל-Android ב-ChromeOS וגורמי צורה גדולים אחרים, כמו טאבלטים, אנחנו רואים עלייה מחודשת בשימוש בניווט באמצעות המקלדת אפליקציות ל-Android. ב-Android 8.0 (רמת API 26), טיפלנו מחדש באמצעות את המקלדת ככלי לקלט ניווט, וכתוצאה מכך מודל לחיזוי (prediction) של ניווט המבוסס על חצים וכרטיסיות.

באופן ספציפי, ביצענו את השינויים הבאים בפוקוס של הרכיבים התנהגות:

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

    אם לא רוצים שאובייקט View ישתמש בברירת המחדל הזו להדגיש כשהוא מקבל את המיקוד, המאפיין android:defaultFocusHighlightEnabled נשלח אל false בקובץ ה-XML של הפריסה שמכיל את View, או להעביר את false אל setDefaultFocusHighlightEnabled() בלוגיקת ממשק המשתמש של האפליקציה.

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

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

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

מילוי אוטומטי של טופס אינטרנט

עכשיו, באמצעות המילוי האוטומטי של Android Framework מספק תמיכה מובנית לפונקציונליות של מילוי אוטומטי, השיטות הבאות הקשורות ל-WebView אובייקטים השתנו לאפליקציות שמותקנות במכשירים עם Android 8.0 (רמת API 26):

WebSettings
  • getSaveFormData() השיטה מחזירה את הערך false. בעבר, השיטה הזו החזירה יש גם אפשרות true.
  • ביצוע שיחה setSaveFormData() לא למשך זמן ארוך יותר.
WebViewDatabase
  • ביצוע שיחה clearFormData() לא למשך זמן ארוך יותר.
  • אמצעי תשלום אחד (hasFormData()) עכשיו מחזירה false. בעבר, השיטה הזו החזירה true כאשר הטופס הכיל נתונים.

נגישות

Android 8.0 (רמת API 26) כולל את השינויים הבאים בנגישות:

  • במסגרת הנגישות, כל התנועות של הקשה כפולה ממירה עכשיו את כל התנועות של ההקשה הכפולה ACTION_CLICK פעולות. השינוי הזה מאפשר ל-TalkBack להתנהג יותר כמו תגובות אחרות שירותי נגישות.

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

  • שירותי הנגישות מודעים כעת לכל ClickableSpan מופעים בתוך האפליקציה TextView אובייקטים.

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

רשת וקישוריות HTTP(S)

Android 8.0 (רמת API 26) כולל את שינויי ההתנהגות הבאים ב: רשת וקישוריות HTTP(S):

  • לבקשות אפשרויות ללא גוף יש Content-Length: 0 הכותרת. בעבר לא הייתה להם כותרת Content-Length.
  • הפונקציה HttpURLConnection מנרמלת כתובות URL שמכילות נתיבים ריקים על ידי צירוף קו נטוי אחרי שם המארח או הרשות. לדוגמה, ממירה את http://example.com ל- http://example.com/.
  • בורר מותאם אישית של שרת proxy המוגדר באמצעות ProxySelector.setDefault() מטרגט רק את הכתובת (סכימה, מארח ויציאה) של כתובת URL מבוקשת. כתוצאה מכך, ייתכן שבחירת שרת proxy תתבסס רק על הערכים האלה. כתובת URL מועבר לבורר של שרת proxy מותאם אישית לא כולל את כתובות ה-URL המבוקשות נתיב, פרמטרים של שאילתה או מקטעים.
  • מזהי URI לא יכולים להכיל תוויות ריקות.

    בעבר, הפלטפורמה תמכה בפתרון עקיף לקבלת תוויות ריקות שמות מארחים, שהם שימוש לא חוקי ב-URI. הפתרון הזה נועד ל תאימות לגרסאות ישנות יותר של libcore. מפתחים שמשתמשים ב-API יראה באופן שגוי הודעת ADB: "URI example.com כולל תוויות ריקות ב- שם המארח. הפורמט הזה שגוי ולא יתקבל בעתיד ב-Android ". מערכת Android 8.0 מסירה את המעקף הזה. המערכת מחזירה null למזהי URI שגויים.

  • יישום HttpsURLConnection ב-Android 8.0 לא משתמשת בגרסה לא מאובטחת של TLS/פרוטוקול SSL.
  • הטיפול במנהור חיבורי HTTP(S) השתנה באופן הבא:
    • בעת מנהור של חיבור HTTPS דרך חיבור, המערכת ממקמת בצורה נכונה את מספר היציאה (443) בשורת המארח בעת השליחה את המידע הזה לשרת ביניים. בעבר, השקע המספר התרחש רק בשורה CONNECT.
    • המערכת לא שולחת יותר סוכן משתמש או הרשאה לשרת proxy מבקשה במנהורת לשרת ה-proxy.

      המערכת לא שולחת יותר כותרת להרשאת שרת proxy Http(s)URLConnection לשרת ה-proxy בעת הגדרת מנהרה. במקום זאת, המערכת יוצרת כותרת להרשאת שרת proxy, ושולח אותו לשרת ה-Proxy כששרת ה-Proxy שולח HTTP 407 בתגובה לבקשה הראשונית.

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

  • send(java.net.DatagramPacket) ה-method מזרקת Socket מפרסמים אם ה-connect() שבוצע קודם לכן נכשלה.
    • DatagramSocket.connect() מגדיר ערך pendingSocketError אם יש שגיאה פנימית. לפני Android 8.0, הפונקציה recv() עוקבת הקריאה זרמה SocketError למרות שקריאה send() הייתה מצליחה. כדי לשמור על עקביות, שתי הקריאות גורמות עכשיו ל-SocketError.
  • InetAddress.isReachable() מנסה את מערכת ה-ICMP לפני חזרה להד TCP של Google.
    • חלק מהמארחים שחוסמים את יציאה 7 (TCP Echo), כמו google.com, עשויים עכשיו יהיו נגישים אם הם מקבלים את פרוטוקול ICMP Echo.
    • למארחים שלא ניתן להגיע אליהם באמת, השינוי הזה פירושו שסכום כפול הזמן שחולף לפני שהשיחה חוזרת.

‫Bluetooth

מערכת Android 8.0 (רמת API 26) מבצעת את השינויים הבאים באורך של את הנתונים שהמודל ScanRecord.getBytes() ה-method מאחזרת:

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

קישוריות חלקה

ב-Android 8.0 (רמת API 26) מתבצעים כמה שיפורים בהגדרות ה-Wi-Fi כדי להקל על הבחירה רשת ה-Wi-Fi שמציעה את חוויית המשתמש הטובה ביותר. השינויים הספציפיים כוללים:

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

אבטחה

מערכת Android 8.0 כוללת את הרכיבים הבאים הקשורים לאבטחה שינויים:

  • הפלטפורמה לא תומכת יותר ב-SSLv3.
  • כשיוצרים חיבור HTTPS לשרת, משתמשת במשא ומתן בגרסת פרוטוקול של TLS, HttpsURLConnection לא מנסה יותר לפתור את הבעיה של חזרה לגרסאות קודמות של פרוטוקול TLS וביצוע ניסיון חוזר.
  • מערכת Android 8.0 (רמת API 26) מחילה מחשוב מאובטח (SECCOMP) סינון לפי כל האפליקציות. רשימת ה-syscalls המותרים מוגבלת למפרסמים נחשףות דרך יונית. למרות שיש כמה מערכות קריאה אחרות לתאימות לאחור, אנחנו ממליצים לא להשתמש בהם.
  • WebView האובייקטים של האפליקציה פועלים עכשיו בריבוי תהליכים במצב תצוגה. תוכן מהאינטרנט מטופל בתהליך נפרד ומבודד שכולל את התהליך של האפליקציה לאבטחה משופרת.
  • כבר לא ניתן להניח שחבילות APK נמצאות בספריות שהשמות שלהן מסתיימים ב-1 או ב-2. באילו אפליקציות צריך להשתמש sourceDir כדי לקבל את ההטבה ולא להסתמך ישירות על פורמט הספרייה.
  • למידע על שיפורי אבטחה שקשורים לשימוש בשפת נייטיב ספריות, ראו ספריות מקוריות.

בנוסף, בגרסה Android 8.0 (רמת API 26) מוצגים השינויים הבאים שקשורים להתקנה אפליקציות לא מוכרות ממקורות לא מוכרים:

  • הערך של ההגדרה הקודמת INSTALL_NON_MARKET_APPS נקראת עכשיו תמיד 1. כדי לקבוע אם מקור לא ידוע יכול להתקין אפליקציות באמצעות עליך להשתמש במקום זאת בערך המוחזר של canRequestPackageInstalls()
  • אם מנסים לשנות את הערך של INSTALL_NON_MARKET_APPS משתמשים setSecureSetting(), UnsupportedOperationException נזרק. כדי למנוע ממשתמשים להתקין אפליקציות לא מוכרות באמצעות אפליקציות לא מוכרות מקורות מידע, צריך להחיל במקום זאת משתמש ב-DISALLOW_INSTALL_UNKNOWN_SOURCES המוגבלות של המשאבים.
  • לפרופילים מנוהלים שנוצרו במכשירים עם Android 8.0 (API ברמה 26), מוגדר באופן אוטומטי משתמש ב-DISALLOW_INSTALL_UNKNOWN_SOURCES ההגבלה מופעלת. לפרופילים מנוהלים קיימים במכשירים ששודרגו ל-Android 8.0, משתמש ב-DISALLOW_INSTALL_UNKNOWN_SOURCES ההגבלה מופעלת באופן אוטומטי, אלא אם הבעלים של הפרופיל הגדיר במפורש השביתה את ההגבלה הזו (לפני השדרוג) באמצעות הגדרה INSTALL_NON_MARKET_APPS ל-1.

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

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

פרטיות

בגרסת Android 8.0 (רמת API 26) מתבצעת את הפעולות הבאות שקשורות לפרטיות לשינויים בפלטפורמה.

  • הפלטפורמה הזו מטפלת עכשיו במזהים באופן שונה.
    • עבור אפליקציות שהותקנו לפני OTA לגרסה של Android 8.0 (רמת API 26) (רמת API 26), הערך של המדד ANDROID_ID לא השתנה אלא אם הם הוסרו ואז הותקנו מחדש לאחר ה-OTA. כדי לשמור על ערכים בכל הסרות לאחר OTA, מפתחים יכולים לשייך את הערכים הישנים לערכים החדשים באמצעות גיבוי של מפתחות/ערך.
    • עבור אפליקציות שמותקנות במכשיר שמותקנת בו מערכת Android 8.0, הערך ANDROID_ID בהיקף לכל חתימת אפליקציה, וגם לכל משתמש. הערך של ANDROID_ID הוא ייחודי לכל שילוב של חתימת אפליקציה, משתמש ומכשיר. כתוצאה מכך, אפליקציות עם מפתחות חתימה שונים פועלות באותו מכשיר לא לראות יותר את אותו מזהה Android (גם לא עבור אותו משתמש).
    • הערך של ANDROID_ID לא משתנה בהסרה או בהתקנה מחדש של החבילה, כל עוד מפתח החתימה זהה (והאפליקציה לא הותקנה לפני OTA ל- גרסה 8.0 של Android).
    • הערך של ANDROID_ID לא משתנה גם אם עדכון מערכת גורם לשינוי מפתח חתימת החבילה.
    • במכשירים עם מזהה הפרסום ומזהה הפרסום של Google Play Services, חובה להשתמש מזהה הפרסום. מערכת פשוטה וסטנדרטית למונטיזציה מאפליקציות. מזהה פרסום הוא מזהה ייחודי שניתן לאיפוס על ידי המשתמש לצורך פרסום. כן, מאת Google Play Services.

      מומלץ להמשיך עם יצרני מכשירים אחרים כדי לספק ANDROID_ID.

  • שליחת שאילתה למאפיין המערכת net.hostname מחזירה ערך null תוצאה אחת.

רישום של חריגות שלא זוהו

אם אפליקציה מתקינה Thread.UncaughtExceptionHandler לא לקרוא לברירת המחדל Thread.UncaughtExceptionHandler, שהמערכת עושה לא להרוג את האפליקציה כשמתרחש חריג לא מובן. החל מ- Android 8.0 (רמת API 26), המערכת רושמת ביומן את דוח הקריסות החריג מצב; בגרסאות קודמות של הפלטפורמה, המערכת לא הייתה תועד דוח הקריסות של החריגים.

מומלץ להתאים אישית את Thread.UncaughtExceptionHandler של הטמעות, תמיד צריך לקרוא ה-handler שמוגדר כברירת מחדל; אפליקציות שמבוססות על ההמלצה הזו לא מושפעות השינוי ב-Android 8.0.

שינוי בחתימה של findViewById()

כל המופעים של השיטה findViewById() מחזירים עכשיו את הערך <T extends View> T במקום View. השינוי הזה יש את ההשלכות הבאות:

  • כתוצאה מכך, יכול להיות שסוג ההחזרה לא ברור לקוד הקיים, לדוגמה אם יש גם someMethod(View) וגם someMethod(TextView) שמעביר את התוצאה של הקריאה אל findViewById().
  • כשמשתמשים בשפת המקור של Java 8, צריך להפעיל Cast מפורש אל View כשסוג ההחזרה לא מוגבל (לדוגמה, assertNotNull(findViewById(...)).someViewMethod()).
  • שינויים של findViewById() methods שאינן סופיות (עבור לדוגמה, Activity.findViewById()) יצטרך להחזיר את המוצר הסוג עודכן.

שינוי בנתוני השימוש של ספק אנשי הקשר

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

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

השינוי הזה בהתנהגות משפיע על הפרמטרים הבאים של השאילתות:

טיפול באוסף

AbstractCollection.removeAll() ו-AbstractCollection.retainAll() עכשיו תן תמיד NullPointerException; קודם, NullPointerException לא שודר כשהאוסף ריק. השינוי הזה מבטיח שההתנהגות תהיה תואמת למסמכי התיעוד.

Android לארגונים

מערכת Android 8.0 (רמת API 26) משנה את ההתנהגות של חלק מממשקי ה-API והתכונות באפליקציות לארגונים, כולל מכשירים נאמני מידע (DPC). השינויים כוללים:

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

כדי לראות את כל השינויים הארגוניים ב-Android 8.0 (רמת API 26) וללמוד כיצד הם עשויים להיות זמינים משפיעים על האפליקציה, קוראים את Android ב-Enterprise.

אפליקציות שמטרגטות את Android 8.0

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

חלונות התראות

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

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

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

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

התראות על שינויים בתוכן

מערכת Android 8.0 (רמת API 26) משנה את האופן שבו ContentResolver.notifyChange() ו-registerContentObserver(Uri, boolean, ContentObserver) להתנהג באפליקציות שמטרגטות את Android 8.0.

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

הצגת המיקוד

אובייקטים מסוג View שניתן ללחוץ עליהם עכשיו ניתנים למיקוד גם באמצעות כברירת מחדל. אם רוצים שאובייקט View יהיה קליקבילי, אבל לא שניתן להתמקד בו, מאפיין android:focusable ל-false בפריסה קובץ XML שמכיל את View, או מעביר ב-false אל setFocusable() בממשק המשתמש של האפליקציה בלוגיקה.

התאמת סוכן משתמש בזיהוי הדפדפן

Android 8.0 (רמת API 26) ואילך כולל את מחרוזת מזהה ה-build OPR. התאמות מסוימות של הדפוסים עשויות תגרום ללוגיקת זיהוי הדפדפן לזהות בטעות דפדפן שאינו Opera כ-Opera. דוגמה להתאמת תבניות כזו יכולה להיות:

if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}

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

אבטחה

השינויים הבאים משפיעים על האבטחה ב-Android 8.0 (רמת API 26):

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

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

גישה לחשבון ויכולת גילוי

ב-Android 8.0 (רמת API 26) אין יותר גישה לאפליקציות לחשבונות משתמשים, אלא אם המאמת הוא הבעלים של החשבונות או משתמש מעניק את הרשאת הגישה הזו. הרשאה מסוג GET_ACCOUNTS כבר לא מספיק. כדי לקבל גישה לחשבון, אפליקציות צריך להשתמש ב-AccountManager.newChooseAccountIntent() או נתונים ספציפיים למאמת החשבונות . לאחר קבלת גישה לחשבונות, אפליקציה יכולה להתקשר AccountManager.getAccounts() כדי לגשת אליהן.

Android 8.0 יוצא משימוש LOGIN_ACCOUNTS_CHANGED_ACTION קמפיינים לקידום אפליקציות צריך להשתמש במקום זאת addOnAccountsUpdatedListener() כדי לקבל עדכונים לגבי חשבונות במהלך זמן ריצה.

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

פרטיות

השינויים הבאים משפיעים על הפרטיות ב-Android 8.0 (רמת API 26).

  • מאפייני המערכת: net.dns1, net.dns2, net.dns3 ו-net.dns4 כבר לא זמין, שינוי שמשפר את הפרטיות בפלטפורמה.
  • כדי לקבל מידע על רשתות, כמו שרתי DNS, אפליקציות עם ACCESS_NETWORK_STATE הרשאה יכולה לרשום NetworkRequest או אובייקט NetworkCallback. הכיתות האלה זמינות ב-Android מגרסה 5.0 (רמת API 21) ואילך.
  • Build.SERIAL הוצא משימוש. במקום זאת, אפליקציות שצריכות לדעת את המספר הסידורי של החומרה להשתמש בשיטה Build.getSerial() החדשה, דורש READ_PHONE_STATE הרשאה.
  • באמצעות API של LauncherApps אי אפשר יותר ליצור פרופיל עבודה כדי לקבל מידע על הפרופיל הראשי. כשמשתמש נמצא בעבודה הפרופיל, ה-API של LauncherApps פועל כאילו אין אפליקציות מותקנים בפרופילים אחרים באותה קבוצת פרופילים. כמו קודם, ניסיונות לגשת לפרופילים לא קשורים גורמים ל-Security חריגות.

הרשאות

לפני Android 8.0 (רמת API 26), אם אפליקציה ביקשה הרשאה בזמן הריצה וההרשאה ניתנה, המערכת גם העניק לאפליקציה את שאר ההרשאות ששייכות לאותה אפליקציה קבוצת הרשאות שנרשמו במניפסט.

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

לדוגמה, נניח שאפליקציה מציגה גם את READ_EXTERNAL_STORAGE וגם WRITE_EXTERNAL_STORAGE במניפסט שלו. האפליקציה מבקשת READ_EXTERNAL_STORAGE וגם שהמשתמש מעניק לו. אם האפליקציה מטרגטת רמת API 25 ומטה, המערכת גם מעניקה WRITE_EXTERNAL_STORAGE במספר זהה כי הוא שייך לאותה קבוצת הרשאות STORAGE וגם רשומות במניפסט. אם האפליקציה מטרגטת את Android 8.0 (רמת API 26), המערכת מעניקה רק READ_EXTERNAL_STORAGE באותו זמן; עם זאת, אם האפליקציה תבקש את WRITE_EXTERNAL_STORAGE בשלב מאוחר יותר, המערכת מיד מעניקה את ההרשאה הזו בלי להציג בקשה למשתמש.

מדיה

  • תוכנת ה-framework יכולה לבצע הנמכה אוטומטית של עוצמת השמע כשלעצמו. במקרה הזה, כשאפליקציה אחרת מתמקדת ב- AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, האפליקציה בעל התמקדות מפחית את עוצמת הקול שלו, אבל בדרך כלל לא מקבל onAudioFocusChange() להתקשרות חזרה ולא פוקוס האודיו. יש ממשקי API חדשים כדי לבטל את ההתנהגות הזו עבור שצריך להשהות במקום להנמיך אותם.
  • כשהמשתמש מבצע שיחת טלפון, שידורי המדיה הפעילים מושתקים למשך שיחה.
  • כל ממשקי ה-API שקשורים לאודיו צריכים להשתמש ב-AudioAttributes במקום סוגים של זרם אודיו כדי לתאר את התרחיש לדוגמה של הפעלת אודיו. ממשיכים להשתמש בסוגים של שידורי אודיו רק לבקרת עוצמת הקול. שימושים אחרים בסוגי מקורות נתונים ימשיכו לפעול (לדוגמה, הארגומנט streamType לתג שהוצאה משימוש AudioTrack constructor), אבל המערכת מתעדת את הפעולה הזו כשגיאה.
  • כשמשתמשים ב-AudioTrack, אם האפליקציה מבקש מאגר אודיו גדול מספיק, המערכת תנסה להשתמש בפלט של מאגר הנתונים הזמני העמוק, אם הוא זמין.
  • ב-Android 8.0 (רמת API 26) אופן הטיפול באירועים של לחצני מדיה שונה:
    1. אופן הטיפול בלחצני המדיה בפעילות בממשק המשתמש לא השתנה: פעילויות בחזית עדיין מקבלות עדיפות בטיפול אירועים של לחצן מדיה.
    2. אם הפעילות בחזית לא מטפלת באירוע של לחצן המדיה, המערכת מנתבת את האירוע לאפליקציה שהשמיעה לאחרונה אודיו באופן מקומי. סטטוס פעיל, דגלים והפעלה המצב של סשן במדיה אינו מובאים בחשבון בעת קביעה איזו אפליקציה מקבלת מדיה אירועי לחצנים.
    3. אם שוחררו סשן המדיה של האפליקציה, המערכת שולחת את האירוע של לחצן המדיה MediaButtonReceiver אם יש לו.
    4. בכל מקרה אחר, המערכת מוחקת את האירוע של לחצן המדיה.

ספריות מקוריות

באפליקציות שמטרגטות ל-Android 8.0 (רמת API 26), ספריות מקוריות לא טעינה ארוכה יותר אם הם מכילים קטע עומס שהוא גם ניתן לכתיבה קובץ הפעלה. יכול להיות שאפליקציות מסוימות יפסיקו לפעול בגלל השינוי הזה, אם הן ספריות מקוריות עם מקטעי טעינה שגויים. זהו אמצעי לחיזוק האבטחה.

מידע נוסף זמין במאמר פלחים ניתנים לכתיבה ולביצוע.

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

טיפול באוסף

ב-Android 8.0 (רמת API 26), ההטמעה של Collections.sort() בוצעה בתאריך בחלק העליון של List.sort(). להיפך היה True ב-Android 7.x (רמות API 24 ו-25): הטמעת ברירת המחדל של List.sort() שנקרא Collections.sort().

השינוי הזה מאפשר ל-Collections.sort() כדי לנצל את האופטימיזציה של List.sort() אלא על המגבלות הבאות:

  • הטמעות של List.sort() לא יכול לקרוא ל-Collections.sort(), כי הפעולה הזו תגרום להצגת גלישת קריסות בגלל חזרה אינסופית. במקום זאת, אם רוצים להגדיר את התנהגות ברירת המחדל בהטמעה של List, צריך להימנע מעקיפת sort().

    אם כיתת הורה מטמיעה את sort() באופן לא הולם, בדרך כלל אפשר לעקוף את List.sort() באמצעות הטמעה שמבוססת על List.toArray(), Arrays.sort(), וגם ListIterator.set() לדוגמה:

    @Override
    public void sort(Comparator<? super E> c) {
      Object[] elements = toArray();
      Arrays.sort(elements, c);
      ListIterator<E> iterator = (ListIterator<Object>) listIterator();
      for (Object element : elements) {
        iterator.next();
        iterator.set((E) element);
      }
    }
    

    ברוב המקרים אפשר גם לשנות מברירת המחדל List.sort() עם שמשתמשת במודלים שונים של ברירת מחדל בהתאם לרמת ה-API. לדוגמה:

    @Override
    public void sort(Comparator<? super E> comparator) {
      if (Build.VERSION.SDK_INT <= 25) {
        Collections.sort(this);
      } else {
        super.sort(comparator);
      }
    }
    

    אם בוחרים באפשרות השנייה רק כי רוצים sort() הזמינה בכל רמות ה-API, כדאי לתת לה שם ייחודי, כמו sortCompat(), במקום לשנות sort()

  • Collections.sort() נחשב עכשיו בתור שינוי מבני הצגת רשימה של הטמעות שקריאות ל-sort(). לדוגמה, בגרסאות של בפלטפורמה שקודמת ל-Android 8.0 (רמת API 26), חזרה על ArrayList והתקשרות אליו sort() דרך האיטרציה היה מחזיר ConcurrentModificationException אם המיון בוצע באמצעות הטלפון List.sort(). Collections.sort() לא גרמה לחריגה.

    השינוי הזה נועד להגביר את העקביות של אופן הפעולה של הפלטפורמה: גישה כזו תוביל עכשיו ל-ConcurrentModificationException.

ההתנהגות של טעינת הכיתה

Android 8.0 (רמת API 26) מבצע בדיקה כדי לוודא שמרכזי הטעינה של מחלקות לא לשבור את ההנחות לגבי סביבת זמן הריצה כשטוענים מחלקות חדשות. הבדיקות האלה מבוצעת אם ההפניה למחלקה מ-Java ( forName()), בייטקוד Dalvik או JNI. הפלטפורמה לא מיירט שיחות ישירות מ-Java שיטת loadClass(), וגם לא בודקת אותה התוצאות של שיחות כאלה. התנהגות כזו לא אמורה להשפיע על תפקוד תקין. הטעינה של הכיתה.

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

הפלטפורמה גם בודקת שהמתארים של המחלקות המבוקשות תקפים. הזה בודקות קריאות JNI שטוענים מחלקות באופן עקיף כמו GetFieldID(), העברת תיאורים לא חוקיים למחלקות האלה. לדוגמה, שדה עם חתימה האפליקציה java/lang/String לא נמצאה כי החתימה הזו לא חוקית. הוא צריך להיות Ljava/lang/String;.

שיחה זו שונה מקריאה של JNI ל-FindClass() java/lang/String הוא שם בעל הרשאות מלאות.

ב-Android 8.0 (רמת API 26) אין תמיכה בכך שמטענים מרובים של מחלקות ינסו להגדיר מחלקות באמצעות אותו אובייקט DexFile. ניסיון לעשות זאת יגרום לסביבת זמן הריצה של Android InternalError עם ההודעה "ניסיון לרשום קובץ dex" <filename> עם כמה טעינה של כיתות".

DexFile API הוצא משימוש, ומומלץ מאוד להשתמש בו אחד מה-classloads של הפלטפורמה, כולל PathClassLoader או BaseDexClassLoader, במקום זאת.

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

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

זהירות: בגרסאות של הפלטפורמה נמוכה מ-Android 8.0 (רמת API 26), הפרה של ההנחות האלה יכולה להוביל להגדרת הרבה פעמים, ערימה של שחיתות בגלל בלבול בכיתה, והשפעות לא רצויות אחרות.