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

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

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

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

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

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

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

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

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

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

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

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

החל מגרסה 10 של Android, המשתמשים יכולים להפעיל ניווט באמצעות תנועות בכל המכשיר. אם משתמש מפעיל את הניווט באמצעות תנועות, הדבר משפיע על כל האפליקציות במכשיר, גם אם האפליקציה מטרגטת את רמת ה-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/.

לצורך תאימות, ה-symlinks מסופקים בנתיבים הישנים. לדוגמה, /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(). עם זאת, מומלץ מאוד להגדיר אותה חזרה ל-execute-only לאחר מכן, כי הגדרת הרשאת הגישה הזו מספקת הגנה טובה יותר לאפליקציה ולמשתמשים.

אבטחה

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

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

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

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

אם רוצים, אפשר לקבל SSLContext שבו TLS 1.3 מושבת על ידי קריאה ל-SSLContext.getInstance("TLSv1.2"). אפשר גם להפעיל או להשבית גרסאות פרוטוקול לכל חיבור בנפרד, על ידי קריאה ל-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 ואילך אין צורך בחיבור מסך המכשיר כדי לייבא מפתחות או אישורי CA לאובייקט KeyChain.

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

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

  • הצפנות AES/GCM/NoPגנים ו-ChaCha20/Poly1305/NoP-# של הצפנה מחזירים נתונים זמניים מדויקים יותר החל מ-getOutputSize().
  • סט הצפנות TLS_FALLBACK_SCSV לא נכלל בניסיונות החיבור עם פרוטוקול מקסימלי של TLS 1.2 ואילך. בגלל השיפורים בהטמעות של שרת TLS, אנחנו לא ממליצים לנסות חלופה חיצונית ל-TLS. במקום זאת, אנחנו ממליצים להסתמך על משא ומתן לגבי גרסת ה-TLS.
  • ChaCha20-Poly1305 הוא כינוי ל-ChaCha20/Poly1305/NoPadding.
  • שמות מארח עם נקודות בסוף לא נחשבים לשמות מארח תקינים של SNI.
  • התוסף נתמך_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) ומטה. אם האפליקציה דורשת מהמשתמש להעניק הרשאות, הוא גם מקבל הזדמנות לשנות את ההרשאות של האפליקציה לפני שהיא תורשה לפעול בפעם הראשונה.

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

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

סטים הבאים של אלגוריתמים להצפנה (cipher suite) מסוג 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 נכללים השינויים הבאים בהתנהגות של שימוש באפליקציות:

  • בנוסף, ב-Android 10 מתבצע מעקב תקין אחרי השימוש באפליקציות אינסטנט.

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

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

הספרייה 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, השיטות האלה גורמות להשלכת NullPointerException במקום זאת.

ZipFile

ב-Android 10 ואילך, הקונסטרוקטור של 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 ובדפוס הדפוס

התוצאה של 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 כללי יותר אם אינדקס הקבוצה מחוץ לטווח. בעבר, השיטות האלה העלו את השגיאה 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 ומטה, האובייקט יקרא בצורה נכונה על ידי אפליקציות שמטרגטות לרמת API 24 ומעלה, ולהפך.

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

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