تغييرات السلوك: جميع التطبيقات

يتضمّن Android 10 تغييرات في السلوك قد تؤثر في تطبيقك. تنطبق التغييرات المدرَجة في هذه الصفحة على تطبيقك عند تشغيله على Android 10، بغض النظر عن targetSdkVersion التطبيق. عليك اختبار تطبيقك وتعديله حسب الحاجة ليتوافق مع هذه التغييرات بشكل صحيح.

إذا كان الإصدار المستهدَف من حزمة تطوير البرامج (SDK) لتطبيقك هو 29 أو إصدار أحدث، عليك أيضًا إجراء تغييرات إضافية. يُرجى الاطّلاع على التغييرات في السلوك للتطبيقات التي تستهدف المستوى 29 لمزيد من التفاصيل.

ملاحظة: بالإضافة إلى التغييرات المدرَجة في هذه الصفحة، يقدّم Android 10 عددًا كبيرًا من التغييرات والقيود المستندة إلى الخصوصية، بما في ذلك ما يلي:

  • الوصول إلى الموقع الجغرافي للجهاز في الخلفية
  • بدء النشاط في الخلفية
  • معلومات تقارب جهات الاتصال
  • التوزيع العشوائي لعناوين MAC
  • البيانات الوصفية للكاميرا
  • نموذج الأذونات

تؤثر هذه التغييرات في جميع التطبيقات وتعزّز خصوصية المستخدم. لمزيد من المعلومات حول كيفية التوافق مع هذه التغييرات، يُرجى الاطّلاع على صفحة التغييرات في الخصوصية.

القيود المفروضة على الواجهات غير التابعة لحزمة تطوير البرامج (SDK)

للمساعدة في ضمان ثبات التطبيق والتوافق، بدأت المنصة في فرض قيود على الواجهات غير المضمّنة في حزمة تطوير البرامج (SDK) التي يمكن لتطبيقك استخدامها في الإصدار Android 9 (مستوى واجهة برمجة التطبيقات 28). يتضمّن Android 10 قوائم معدَّلة لواجهات غير حزمة تطوير البرامج (SDK) المحظورة استنادًا إلى التعاون مع مطوّري برامج Android وأحدث الاختبارات الداخلية. هدفنا هو التأكّد من توفّر بدائل عامة قبل حظر الواجهات غير المتوفّرة في حزمة SDK.

إذا لم تكن تستهدف الإصدار Android 10 (المستوى 29 لواجهة برمجة التطبيقات)، قد لا تؤثر بعض هذه التغييرات فيك على الفور. ومع ذلك، على الرغم من أنّه يمكنك حاليًا استخدام بعض الواجهات غير المتوفّرة في حزمة SDK (وفقًا لمستوى واجهة برمجة التطبيقات المستهدَف في تطبيقك)، فإنّ استخدام أي طريقة أو حقل غير متوفّر في حزمة SDK ينطوي دائمًا على مخاطرة كبيرة بتعطُّل تطبيقك.

إذا لم تكن متأكدًا مما إذا كان تطبيقك يستخدم واجهات غير متوفّرة في حزمة SDK، يمكنك اختبار تطبيقك لمعرفة ذلك. إذا كان تطبيقك يعتمد على واجهات غير متوفّرة في حزمة SDK، عليك البدء في التخطيط للانتقال إلى بدائل حزمة SDK. ومع ذلك، ندرك أنّ بعض التطبيقات لديها حالات استخدام صالحة لاستخدام واجهات غير حِزم تطوير البرامج (SDK). إذا لم تتمكّن من العثور على بديل لاستخدام واجهة غير متوفّرة في حزمة SDK لميزة في تطبيقك، عليك طلب واجهة برمجة تطبيقات عامة جديدة.

لمزيد من المعلومات، يُرجى الاطّلاع على التعديلات على القيود المفروضة على الواجهات غير المتوفّرة في حزمة SDK في Android 10 والقيود المفروضة على الواجهات غير المتوفّرة في حزمة SDK.

التنقُّل بالإيماءات

بدءًا من الإصدار Android 10، يمكن للمستخدمين تفعيل ميزة التنقّل بالإيماءات على مستوى الجهاز. إذا فعّل المستخدم ميزة "التنقّل بالإيماءات"، سيؤثر ذلك في جميع التطبيقات على الجهاز، سواء كان التطبيق يستهدف المستوى 29 من واجهة برمجة التطبيقات أم لا. على سبيل المثال، إذا مرّر المستخدم سريعًا من حافة الشاشة، يفسّر النظام هذه الإيماءة على أنّها تنقّل للخلف، ما لم يتجاوز التطبيق هذه الإيماءة تحديدًا لأجزاء من الشاشة.

لجعل تطبيقك متوافقًا مع ميزة "التنقّل بالإيماءات"، عليك توسيع محتوى التطبيق من الحافة إلى الحافة، والتعامل مع الإيماءات المتعارضة بشكل مناسب. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات التنقّل بالإيماءات.

NDK

يتضمّن Android 10 تغييرات NDK التالية.

لا يمكن أن تحتوي العناصر المشتركة على عمليات نقل النص

لم يسمح الإصدار 6.0 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 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 التغييرات التالية في الأمان.

تفعيل الإصدار 1.3 من بروتوكول أمان طبقة النقل (TLS) تلقائيًا

في الإصدار Android 10 والإصدارات الأحدث، يتم تفعيل الإصدار 1.3 من بروتوكول أمان طبقة النقل (TLS) تلقائيًا لجميع اتصالات بروتوكول أمان طبقة النقل (TLS). في ما يلي بعض التفاصيل المهمة حول تنفيذ الإصدار 1.3 من بروتوكول أمان طبقة النقل (TLS):

  • لا يمكن تخصيص مجموعات رموز بروتوكول أمان طبقة النقل (TLS) 1.3. يتم دائمًا تفعيل مجموعات رموز بروتوكول أمان طبقة النقل (TLS) الإصدار 1.3 المتوافقة عند تفعيل هذا الإصدار. ويتم تجاهل أي محاولة لإيقافها من خلال استدعاء setEnabledCipherSuites().
  • عند التفاوض على الإصدار 1.3 من بروتوكول أمان طبقة النقل (TLS)، يتم استدعاء عناصر HandshakeCompletedListener قبل إضافة الجلسات إلى ذاكرة التخزين المؤقت للجلسات. (في الإصدار 1.2 من بروتوكول أمان طبقة النقل (TLS) والإصدارات السابقة الأخرى، يتم استدعاء هذه العناصر بعد إضافة الجلسات إلى ذاكرة التخزين المؤقت للجلسات).
  • في بعض الحالات التي تعرض فيها مثيلات SSLEngine الخطأ SSLHandshakeException في الإصدارات السابقة من Android، تعرض هذه المثيلات الخطأ SSLProtocolException بدلاً من ذلك في الإصدار Android 10 والإصدارات الأحدث.
  • وضع 0-RTT غير متاح.

إذا أردت، يمكنك الحصول على SSLContext تم إيقاف الإصدار 1.3 من بروتوكول أمان طبقة النقل (TLS) فيه من خلال طلب 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/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 مباشر ثابتة:

إذا كان تطبيقك يعتمد على تلقّي عمليات البث هذه عند التسجيل لأنّها كانت ثابتة، استخدِم طريقة get() المناسبة عند الإعداد للحصول على المعلومات بدلاً من ذلك.

إمكانات Wi-Fi Aware

يضيف Android 10 دعمًا لتسهيل إنشاء مقابس TCP/UDP باستخدام مسارات بيانات Wi-Fi Aware. لإنشاء مقبس TCP/UDP يتصل بـ ServerSocket، يحتاج جهاز العميل إلى معرفة عنوان IPv6 ومنفذ الخادم. في السابق، كان يجب إرسال هذه المعلومات خارج النطاق، مثلاً باستخدام رسائل الطبقة الثانية من 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 edition يعمل بالإصدار 9 من نظام التشغيل Android أو إصدار أقدم على إذن SYSTEM_ALERT_WINDOW، يحتفظ التطبيق بالإذن حتى إذا تمت ترقية الجهاز إلى الإصدار 10 من نظام التشغيل Android. ومع ذلك، لا يمكن منح هذا الإذن للتطبيقات التي لم تحصل عليه بعد ترقية الجهاز.

إذا أرسل تطبيق على جهاز Go طلبًا يتضمّن الإجراء ACTION_MANAGE_OVERLAY_PERMISSION، يرفض النظام الطلب تلقائيًا، وينقل المستخدم إلى شاشة الإعدادات التي توضّح أنّ الإذن غير مسموح به لأنّه يؤدي إلى إبطاء الجهاز. إذا استدعى تطبيق على جهاز Go‏ Settings.canDrawOverlays()، ستعرض الطريقة دائمًا القيمة false. مرة أخرى، لا تنطبق هذه القيود على التطبيقات التي حصلت على إذن SYSTEM_ALERT_WINDOW قبل ترقية الجهاز إلى Android 10.

تحذيرات بشأن التطبيقات التي تستهدف إصدارات Android القديمة

تحذّر الأجهزة التي تعمل بنظام التشغيل Android 10 أو الإصدارات الأحدث المستخدمين في المرة الأولى التي يشغّلون فيها أي تطبيق يستهدف الإصدار 5.1 من نظام التشغيل Android (المستوى 22 لواجهة برمجة التطبيقات) أو الإصدارات الأقدم. إذا كان التطبيق يتطلّب من المستخدم منح أذونات، يتم منح المستخدم أيضًا فرصة لتعديل أذونات التطبيق قبل السماح بتشغيل التطبيق للمرة الأولى.

بسبب متطلبات مستوى واجهة برمجة التطبيقات المستهدَف في Google Play، لا تظهر هذه التحذيرات للمستخدم إلا عند تشغيل تطبيق لم يتم تحديثه مؤخرًا. بالنسبة إلى التطبيقات التي يتم توزيعها من خلال متاجر أخرى، سيتم تطبيق متطلبات مشابهة لمستوى واجهة برمجة التطبيقات المستهدف خلال عام 2019. لمزيد من المعلومات حول هذه المتطلبات، يُرجى الاطّلاع على توسيع متطلبات مستوى واجهة برمجة التطبيقات المستهدف في عام 2019.

إزالة مجموعات رموز 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: يتتبّع نظام التشغيل Android 10 استخدام التطبيقات بدقة من خلال UsageStats عند استخدام التطبيقات في وضع تقسيم الشاشة أو وضع "نافذة ضمن النافذة". بالإضافة إلى ذلك، يتتبّع نظام التشغيل Android 10 استخدام التطبيقات الفورية بشكل صحيح.

  • التدرج الرمادي لكل تطبيق: يمكن لنظام التشغيل Android 10 ضبط وضع عرض التدرج الرمادي لكل تطبيق على حدة.

  • حالة التشتيت لكل تطبيق: يمكن لنظام التشغيل 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.

منفاخ

في الإصدارات السابقة، كانت بعض الطرق في فئة Inflater تعرض IllegalStateException إذا تم استدعاؤها بعد استدعاء end(). في Android 10، تعرض هذه الطرق NullPointerException بدلاً من ذلك.

ZipFile

في الإصدار 10 من نظام التشغيل Android والإصدارات الأحدث، لا يعرض مُنشئ ZipFile الذي يتلقّى وسيطات من النوع File وint وCharset ZipException إذا كان ملف ZIP المقدَّم لا يحتوي على أي ملفات.

ZipOutputStream

في الإصدار 10 من نظام التشغيل Android والإصدارات الأحدث، لا تعرض طريقة finish() في ZipOutputStream الخطأ ZipException إذا حاولت كتابة سلسلة بيانات ناتجة لملف ZIP لا يحتوي على أي ملفات.

تغييرات الكاميرا

تفترض العديد من التطبيقات التي تستخدم الكاميرا أنّه إذا كان الجهاز في الوضع العمودي، يكون الجهاز الفعلي أيضًا في الوضع العمودي، كما هو موضّح في اتجاه الكاميرا. كان هذا الافتراض آمنًا في الماضي، ولكن تغيّر ذلك مع توسّع أنواع الأجهزة المتاحة، مثل الأجهزة القابلة للطي. ويمكن أن يؤدي هذا الافتراض على هذه الأجهزة إلى عرض عدسة الكاميرا بشكل غير صحيح من حيث التدوير أو تغيير الحجم (أو كليهما).

يجب أن تضبط التطبيقات التي تستهدف المستوى 24 من واجهة برمجة التطبيقات أو أعلى android:resizeableActivity بشكل صريح وأن توفّر الوظائف اللازمة للتعامل مع عملية النوافذ المتعددة.

تتبُّع استخدام البطارية

بدءًا من الإصدار Android 10، يعيد تطبيق SystemHealthManager ضبط إحصاءات استخدام البطارية كلما تم فصل الجهاز عن مصدر الطاقة بعد عملية شحن كبيرة. بشكل عام، يكون حدث الشحن الرئيسي إما: تم شحن الجهاز بالكامل، أو انتقل الجهاز من حالة نفاد الشحن في الغالب إلى حالة الشحن في الغالب.

قبل الإصدار Android 10، كانت تتم إعادة ضبط إحصاءات استخدام البطارية كلما تم فصل الجهاز عن مصدر الطاقة، بغض النظر عن مدى التغيير في مستوى شحن البطارية.

إيقاف Android Beam نهائيًا

في Android 10، سنوقف نهائيًا ميزة Android Beam، وهي ميزة قديمة لبدء مشاركة البيانات على جميع الأجهزة من خلال الاتصال القصير المدى (NFC). سنوقف أيضًا نهائيًا العديد من واجهات برمجة التطبيقات ذات الصلة بتكنولوجيا NFC. تظل ميزة Android Beam متاحة اختياريًا لشركاء صناعة الأجهزة الذين يريدون استخدامها، ولكنها لم تعد قيد التطوير النشط. ومع ذلك، سيواصل Android إتاحة إمكانات وواجهات برمجة تطبيقات أخرى لتقنية 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 أكثر عمومية إذا كان فهرس المجموعة خارج الحدود. في السابق، كانت هذه الطرق تعرض الخطأ ArrayIndexOutOfBoundsException.

الزاوية التلقائية لـ GradientDrawable هي الآن TOP_BOTTOM

في Android 10، إذا حدّدت GradientDrawable في ملف XML ولم تقدّم قياسًا للزاوية، يتم ضبط اتجاه التدرج تلقائيًا على TOP_BOTTOM. يختلف هذا الإجراء عن إصدارات Android السابقة التي كان الإعداد التلقائي فيها هو LEFT_RIGHT.

كحل بديل، إذا حدّثت إلى أحدث إصدار من AAPT2، ستضبط الأداة قياس الزاوية على 0 للتطبيقات القديمة في حال عدم تحديد قياس الزاوية.

تسجيل الكائنات المتسلسلة باستخدام SUID التلقائي

بدءًا من الإصدار 7.0 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 24)، تم إجراء إصلاح على serialVersionUID التلقائي للعناصر القابلة للتسلسل. لم يؤثر هذا الإصلاح في التطبيقات التي تستهدف المستوى 23 من واجهة برمجة التطبيقات أو المستويات الأقل.

بدءًا من الإصدار Android 10، إذا كان التطبيق يستهدف المستوى 23 أو أقل لواجهة برمجة التطبيقات ويعتمد على الإعداد التلقائي القديم وغير الصحيح serialVersionUID، يسجّل النظام تحذيرًا ويقترح إصلاح الرمز.

وعلى وجه التحديد، يسجّل النظام تحذيرًا في حال استيفاء جميع الشروط التالية:

  • يستهدف التطبيق المستوى 23 أو أقل من واجهة برمجة التطبيقات.
  • يتم تسلسل الفئة.
  • تستخدم الفئة المتسلسلة القيمة التلقائية لـ serialVersionUID، بدلاً من ضبط serialVersionUID بشكل صريح.
  • يختلف الإعداد التلقائي لـ serialVersionUID عن serialVersionUID إذا كان التطبيق يستهدف المستوى 24 من واجهة برمجة التطبيقات أو المستويات الأعلى.

يتم تسجيل هذا التحذير مرة واحدة لكل صف متأثر. تتضمّن رسالة التحذير إصلاحًا مقترحًا، وهو ضبط serialVersionUID صراحةً على القيمة التلقائية التي سيتم احتسابها إذا كان التطبيق يستهدف المستوى 24 من واجهة برمجة التطبيقات أو أعلى. باستخدام هذا الإصلاح، يمكنك التأكد من أنه إذا تم إجراء تسلسل لكائن من هذه الفئة على تطبيق يستهدف المستوى 23 من واجهة برمجة التطبيقات أو أقل، فستتم قراءة الكائن بشكل صحيح بواسطة التطبيقات التي تستهدف المستوى 24 أو أعلى، والعكس صحيح.

تغييرات في java.io.FileChannel.map()‎

اعتبارًا من الإصدار Android 10، لا يتوفّر FileChannel.map() للملفات غير العادية، مثل /dev/zero، التي لا يمكن تغيير حجمها باستخدام truncate(). في الإصدارات السابقة من Android، كان يتم تجاهل رمز الخطأ الذي تعرضه الدالة truncate()، ولكن في Android 10 يتم عرض استثناء IOException. إذا كنت بحاجة إلى السلوك القديم، عليك استخدام الرموز البرمجية الأصلية.