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

‫Android 10 כולל שינויים בהתנהגות שעשויים להשפיע על האפליקציה שלכם. השינויים שמפורטים בדף הזה חלים על האפליקציה שלכם כשהיא פועלת ב-Android 10, בלי קשר ל-targetSdkVersion של האפליקציה. כדאי לבדוק את האפליקציה ולשנות אותה לפי הצורך כדי לתמוך בשינויים האלה בצורה תקינה.

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

הערה: בנוסף לשינויים שמפורטים בדף הזה, ב-Android 10 יש מספר רב של שינויים והגבלות שקשורים לפרטיות, כולל:

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

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

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

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

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

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

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

ניווט באמצעות תנועות

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

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

NDK

‫Android 10 כוללת את השינויים הבאים ב-NDK.

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

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

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

שינויים בספריות Bionic ובנתיבי המקשר הדינמי

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

  • /system/lib/libc.so -> /apex/com.android.runtime/lib/bionic/libc.so
  • /system/lib/libm.so -> /apex/com.android.runtime/lib/bionic/libm.so
  • /system/lib/libdl.so -> /apex/com.android.runtime/lib/bionic/libdl.so
  • /system/bin/linker -> /apex/com.android.runtime/bin/linker

השינויים האלה חלים גם על גרסאות 64 ביט של הקובץ, כאשר lib/ מוחלף ב-lib64/.

לצורך תאימות, הקישורים הסמליים מסופקים בנתיבים הישנים. לדוגמה, /system/lib/libc.so הוא קישור סמלי ל-/apex/com.android.runtime/lib/bionic/libc.so. לכן, dlopen(“/system/lib/libc.so”) ממשיך לפעול, אבל האפליקציות יזהו את ההבדל כשהן ינסו לבדוק את הספריות שנטענו על ידי קריאת /proc/self/maps או פקודה דומה. זה לא נפוץ, אבל גילינו שאפליקציות מסוימות עושות את זה כחלק מתהליך למניעת פריצה. אם כן, צריך להוסיף את הנתיבים של /apex/… כנתיבים תקינים לקובצי Bionic.

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

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

כדי לדעת אם ההתנהגות הזו גרמה לקריסה, אפשר לבדוק את קובץ ה-tombstone שקשור אליה ב-/data/tombstones/. קריסה שקשורה להרשאת ביצוע בלבד כוללת את הודעת הביטול הבאה:

Cause: execute-only (no-read) memory access error; likely due to data in .text.

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

אבטחה

‫Android 10 כוללת את שינויי האבטחה הבאים.

הפרוטוקול TLS 1.3 מופעל כברירת מחדל

ב-Android 10 ואילך, ‏ TLS 1.3 מופעל כברירת מחדל לכל חיבורי ה-TLS. ריכזנו כאן כמה פרטים חשובים על ההטמעה של TLS 1.3:

  • אי אפשר להתאים אישית את סטים של אלגוריתמים להצפנה (cipher suite) מסוג TLS 1.3. האלגוריתמים להצפנה (cipher suite) של TLS 1.3 שתומכים ב-Chrome תמיד מופעלים כש-TLS 1.3 מופעל. כל ניסיון להשבית אותם באמצעות התקשרות אל setEnabledCipherSuites() יידחה.
  • כשמתנהל משא ומתן על TLS 1.3, אובייקטים של HandshakeCompletedListener נקראים לפני שמוסיפים סשנים למטמון הסשנים. (ב-TLS 1.2 ובגרסאות קודמות אחרות, האובייקטים האלה נקראים סשנים של אחרי שמוסיפים אותם למטמון הסשנים).
  • במצבים מסוימים שבהם מופעלת SSLEngine מופעלת SSLEngine SSLHandshakeException בגרסאות קודמות של Android, המופעים האלה מפעילים SSLProtocolException במקום זאת ב-Android 10 ואילך.
  • אין תמיכה במצב 0-RTT.

אם רוצים, אפשר להתקשר אל SSLContext.getInstance("TLSv1.2") כדי לקבל SSLContext שבו TLS 1.3 מושבת. אפשר גם להפעיל או להשבית גרסאות של פרוטוקולים לכל חיבור בנפרד באמצעות קריאה ל-setEnabledProtocols() באובייקט המתאים.

אישורים שחתומים באמצעות SHA-1 לא נחשבים מהימנים ב-TLS

ב-Android 10, אישורים שמשתמשים באלגוריתם הגיבוב SHA-1 לא נחשבים מהימנים בחיבורי TLS. רשויות אישורים בסיסיות לא הנפיקו אישור כזה מאז 2016, ואין יותר אמון בהן ב-Chrome או בדפדפנים מרכזיים אחרים.

כל ניסיון להתחבר ייכשל אם החיבור הוא לאתר שמציג אישור באמצעות SHA-1.

שינויים ושיפורים בהתנהגות של KeyChain

דפדפנים מסוימים, כמו Google Chrome, מאפשרים למשתמשים לבחור אישור כששרת TLS שולח הודעת בקשת אישור כחלק מלחיצת היד של TLS. החל מ-Android 10, אובייקטים של KeyChain מכבדים את פרמטרי המנפיקים ואת פרמטרי מפרט המפתח כשמתבצעת קריאה ל-KeyChain.choosePrivateKeyAlias() כדי להציג למשתמשים הנחיה לבחירת אישור. בפרט, ההנחיה הזו לא כוללת אפשרויות שלא עומדות במפרטים של השרת.

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

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

שינויים אחרים ב-TLS ובקריפטוגרפיה

בוצעו כמה שינויים קלים בספריות של TLS וקריפטוגרפיה שנכנסים לתוקף ב-Android 10:

  • הצפנים AES/GCM/NoPadding ו-ChaCha20/Poly1305/NoPadding מחזירים גדלים מדויקים יותר של מאגרים מ-getOutputSize().
  • הסט של האלגוריתמים להצפנה TLS_FALLBACK_SCSV מושמט מניסיונות חיבור עם פרוטוקול מקסימלי של TLS 1.2 ומעלה. בגלל שיפורים בהטמעות של שרת TLS, לא מומלץ לנסות מעבר חזרה חיצוני ל-TLS. במקום זאת, מומלץ להסתמך על משא ומתן לגבי גרסת TLS.
  • ‫ChaCha20-Poly1305 הוא כינוי ל-ChaCha20/Poly1305/NoPadding.
  • שמות מארחים עם נקודות בסוף לא נחשבים לשמות מארחים תקינים של SNI.
  • התוסף supported_signature_algorithms ב-CertificateRequest נלקח בחשבון כשבוחרים מפתח חתימה לתגובות לאישורים.
  • אפשר להשתמש במפתחות חתימה אטומים, כמו אלה מ-Android Keystore, עם חתימות RSA-PSS ב-TLS.

שידורים דרך Wi-Fi ישיר

ב-Android 10, השידורים הבאים שקשורים ל-Wi-Fi Direct לא נשארים:

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

היכולות של Wi-Fi Aware

ב-Android 10 נוספה תמיכה שמקלה על יצירת שקעי TCP/UDP באמצעות נתיבי נתונים של Wi-Fi Aware. כדי ליצור שקע TCP/UDP שמתחבר ל-ServerSocket, מכשיר הלקוח צריך לדעת את כתובת ה-IPv6 והיציאה של השרת. בעבר היה צורך להעביר את המידע הזה מחוץ לפס, למשל באמצעות הודעות בשכבה 2 של BT או Wi-Fi Aware, או לגלות אותו בתוך הפס באמצעות פרוטוקולים אחרים, כמו mDNS. ב-Android 10, אפשר להעביר את המידע כחלק מהגדרת הרשת.

השרת יכול לבצע אחת מהפעולות הבאות:

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

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

Kotlin

val ss = ServerSocket()
val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
  .setPskPassphrase("some-password")
  .setPort(ss.localPort)
  .build()

val myNetworkRequest = NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build()

Java

ServerSocket ss = new ServerSocket();
WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier
  .Builder(discoverySession, peerHandle)
  .setPskPassphrase(some-password)
  .setPort(ss.getLocalPort())
  .build();

NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build();

הלקוח מבצע בקשה לאחזור מהרשת Wi-Fi Aware כדי לקבל את ה-IPv6 ואת היציאה שסופקו על ידי השרת:

Kotlin

val callback = object : ConnectivityManager.NetworkCallback() {
  override fun onAvailable(network: Network) {
    ...
  }
  
  override fun onLinkPropertiesChanged(network: Network,
      linkProperties: LinkProperties) {
    ...
  }

  override fun onCapabilitiesChanged(network: Network,
      networkCapabilities: NetworkCapabilities) {
    ...
    val ti = networkCapabilities.transportInfo
    if (ti is WifiAwareNetworkInfo) {
       val peerAddress = ti.peerIpv6Addr
       val peerPort = ti.port
    }
  }
  override fun onLost(network: Network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback)

Java

callback = new ConnectivityManager.NetworkCallback() {
  @Override
  public void onAvailable(Network network) {
    ...
  }
  @Override
  public void onLinkPropertiesChanged(Network network,
      LinkProperties linkProperties) {
    ...
  }
  @Override
  public void onCapabilitiesChanged(Network network,
      NetworkCapabilities networkCapabilities) {
    ...
    TransportInfo ti = networkCapabilities.getTransportInfo();
    if (ti instanceof WifiAwareNetworkInfo) {
       WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti;
       Inet6Address peerAddress = info.getPeerIpv6Addr();
       int peerPort = info.getPort();
    }
  }
  @Override
  public void onLost(Network network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback);

SYSTEM_ALERT_WINDOW במכשירי Go

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

אם אפליקציה שפועלת במכשיר עם מהדורת Go של Android בגרסה 9 או בגרסה מוקדמת יותר מקבלת את ההרשאה SYSTEM_ALERT_WINDOW, היא שומרת את ההרשאה גם אם המכשיר משודרג ל-Android 10. עם זאת, לא ניתן להעניק הרשאה כזו לאפליקציות שלא קיבלו אותה לפני שדרוג המכשיר.

אם אפליקציה במכשיר Go שולחת Intent עם הפעולה ACTION_MANAGE_OVERLAY_PERMISSION, המערכת דוחה את הבקשה באופן אוטומטי ומעבירה את המשתמש למסך הגדרות שבו מצוין שההרשאה לא מאושרת כי היא מאטה את המכשיר. אם אפליקציה במכשיר Go קוראת ל-Settings.canDrawOverlays(), השיטה תמיד מחזירה false. שוב, ההגבלות האלה לא חלות על אפליקציות שקיבלו את ההרשאה SYSTEM_ALERT_WINDOW לפני שהמכשיר שודרג ל-Android 10.

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

במכשירים עם Android 10 ומעלה, המשתמשים מקבלים אזהרה בפעם הראשונה שהם מפעילים אפליקציה שמטרגטת ל-Android 5.1 (רמת API‏ 22) ומטה. אם האפליקציה דורשת מהמשתמש להעניק הרשאות, ניתנת לו גם הזדמנות לשנות את ההרשאות של האפליקציה לפני שהיא מורשית לפעול בפעם הראשונה.

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

הוסרו סטים של אלגוריתמים להצפנה (cipher suite) מסוג SHA-2 CBC

חבילות ההצפנה הבאות של SHA-2 CBC הוסרו מהפלטפורמה:

  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

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

שימוש באפליקציות

‫Android 10 כולל את השינויים הבאים בהתנהגות שקשורים לשימוש באפליקציות:

  • שיפורים בנתוני השימוש באפליקציות ב-UsageStats – <0x בנוסף, ב-Android 10 מתבצע מעקב מדויק אחר השימוש באפליקציות אינסטנט.

  • גווני אפור לכל אפליקציה – ב-Android 10 אפשר להגדיר מצב תצוגה בגווני אפור לכל אפליקציה בנפרד.

  • Per-app distraction state – <0x0A

  • השעיה והפעלה – <0x0A

שינויים בחיבור HTTPS

אם אפליקציה שפועלת ב-Android 10 מעבירה את null אל setSSLSocketFactory(), מתרחשת IllegalArgumentException. בגרסאות קודמות, העברת null אל setSSLSocketFactory() הייתה זהה להעברה של ברירת המחדל הנוכחית של factory.

הספרייה android.preference הוצאה משימוש

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

שינויים בספריית כלי השירות של קובצי ZIP

‫Android 10 כולל את השינויים הבאים במחלקות בחבילה java.util.zip, שמטפלת בקובצי ZIP. השינויים האלה הופכים את ההתנהגות של הספרייה לעקבית יותר בין Android לבין פלטפורמות אחרות שמשתמשות ב-java.util.zip.

משאבה לניפוח

בגרסאות קודמות, חלק מה-methods במחלקה Inflater הציגו את השגיאה IllegalStateException אם הם הופעלו אחרי קריאה ל-end(). ב-Android 10, ה-methods האלה מחזירות במקום זאת את הערך NullPointerException.

ZipFile

ב-Android 10 ואילך, ה-constructor של ZipFile שמקבל ארגומנטים מהסוגים File, int ו-Charset לא יוצר ZipException אם קובץ ה-ZIP שסופק לא מכיל קבצים.

ZipOutputStream

ב-Android 10 ואילך, השיטה finish() ב-ZipOutputStream לא יוצרת את ZipException אם היא מנסה לכתוב פלט של זרם לקובץ ZIP שלא מכיל קבצים.

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

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

באפליקציות שמטרגטות לרמת ה-API המיועדת 24 ומעלה, צריך להגדיר במפורש את android:resizeableActivity ולספק את הפונקציונליות הנדרשת לטיפול בפעולה של ריבוי חלונות.

מעקב אחר השימוש בסוללה

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

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

הוצאה משימוש של Android Beam

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

שינוי בהתנהגות של java.math.BigDecimal.stripTrailingZeros()‎

BigDecimal.stripTrailingZeros() כבר לא שומרת על אפסים בסוף כמקרה מיוחד אם ערך הקלט הוא אפס.

שינויים בהתנהגות של java.util.regex.Matcher ו-Pattern

התוצאה של split() השתנתה כך שהיא לא מתחילה יותר ב-String ("") ריק אם יש התאמה באורך אפס בתחילת הקלט. ההגדרה הזו משפיעה גם על String.split(). לדוגמה, הפקודה "x".split("") מחזירה עכשיו את הערך {"x"} במקום הערך {"", "x"} שהיא החזירה בגרסאות ישנות יותר של Android. המאפיין "aardvark".split("(?=a)" מחזיר עכשיו {"a", "ardv", "ark"} במקום {"", "a", "ardv", "ark"}.

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

  • appendReplacement(StringBuffer, String) מחזירה עכשיו את השגיאה IllegalArgumentException במקום IndexOutOfBoundsException אם המחרוזת String להחלפה מסתיימת בקו נטוי הפוך בודד, שזה לא חוקי. אותו חריג מוצג עכשיו אם המחרוזת להחלפה String מסתיימת ב-$. בעבר, לא נוצרה חריגה בתרחיש הזה.
  • replaceFirst(null) לא מתקשר יותר אל reset() ב-Matcher אם הוא מחזיר NullPointerException. השגיאה NullPointerException מוחזרת עכשיו גם כשאין התאמה. בעבר, השגיאה הזו הוחזרה רק כשהיה התאמה.
  • start(int group), ‏end(int group) ו-group(int group) מוציאים עכשיו IndexOutOfBoundsException כללי יותר אם אינדקס הקבוצה חורג מהגבולות. בעבר, ה-methods האלה החזירו ArrayIndexOutOfBoundsException.

זווית ברירת המחדל של GradientDrawable היא עכשיו TOP_BOTTOM

ב-Android 10, אם מגדירים GradientDrawable ב-XML ולא מציינים מדידת זווית, כיוון המעבר מוגדר כברירת מחדל ל- TOP_BOTTOM. זהו שינוי לעומת גרסאות קודמות של Android, שבהן ברירת המחדל הייתה LEFT_RIGHT.

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

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

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

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

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

  • האפליקציה מטרגטת לרמת API ‏23 ומטה.
  • מחלקים כיתה לסדרת נתונים.
  • המחלקות שעברו סריאליזציה משתמשות בערך ברירת המחדל serialVersionUID, במקום להגדיר במפורש serialVersionUID.
  • ערך ברירת המחדל של serialVersionUID שונה מזה של serialVersionUID אם האפליקציה מטרגטת רמת API 24 ומעלה.

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

שינויים ב-java.io.FileChannel.map()‎

החל מ-Android 10, אין תמיכה ב-FileChannel.map() עבור קבצים לא סטנדרטיים, כמו /dev/zero, שאי אפשר לשנות את הגודל שלהם באמצעות truncate(). בגרסאות קודמות של Android, המערכת התעלמה מהערך של errno שהוחזר על ידי truncate(), אבל ב-Android 10 מוצג IOException. אם אתם צריכים את ההתנהגות הישנה, אתם צריכים להשתמש בקוד Native.