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

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

إذا كان targetSdkVersion لتطبيقك هو 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.

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

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

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

كرونة دنماركية

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

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

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

يفرض SELinux هذا القيد على التطبيقات التي تستهدف الإصدار 10 من Android أو الإصدارات الأحدث. إذا استمرت هذه التطبيقات في استخدام عناصر مشترَكة تحتوي على عمليات إعادة توجيه للنصوص، ستواجه خطرًا كبيرًا بالتعطُّل.

التغييرات في مكتبات 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.

ملفات النظام الثنائية/المكتبات المرتبطة بذاكرة للتنفيذ فقط

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

  • لا يمكن تخصيص مجموعات رموز التشفير في بروتوكول أمان طبقة النقل (TLS) 1.3. يتم دائمًا تفعيل مجموعات تشفير طبقة النقل الآمنة 1.3 المتوافقة عند تفعيل الإصدار 1.3 من بروتوكول أمان طبقة النقل. ويتم تجاهل أي محاولة لإيقافها من خلال استدعاء setEnabledCipherSuites().
  • عند التفاوض على الإصدار 1.3 من بروتوكول أمان طبقة النقل (TLS)، يتم استدعاء كائنات HandshakeCompletedListener قبل إضافة الجلسات إلى ذاكرة التخزين المؤقت للجلسة. (في TLS 1.2 والإصدارات السابقة الأخرى، تُسمى هذه الكائنات بعد إضافة الجلسات إلى ذاكرة التخزين المؤقت للجلسة.)
  • في بعض الحالات التي تعرض فيها مثيلات 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، مع توقيعات RA-PSS في بروتوكول أمان طبقة النقل (TLS).

عمليات بث Wi-Fi Direct

في نظام التشغيل Android 10، لا تكون عمليات البث التالية المرتبطة بتقنية Wi-Fi Direct ثابتة:

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

إمكانات التعرُّف على شبكات Wi-Fi

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

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

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

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

  • بالإضافة إلى ذلك، يتتبّع الإصدار Android 10 استخدام التطبيقات الفورية بشكل صحيح.

تغييرات في اتصال HTTPS

إذا أرسل تطبيق يعمل بنظام التشغيل Android 10 null إلى setSSLSocketFactory()، يحدث IllegalArgumentException. في الإصدارات السابقة، كان لضبط null على setSSLSocketFactory() التأثير نفسه لضبط default factory الحالي.

تم إيقاف مكتبة 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

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

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

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

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

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

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

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

إيقاف ميزة "الشعاع" في Android نهائيًا

في Android 10، نحن بصدد إيقاف ميزة "شعاع Android" نهائيًا، وهي ميزة قديمة لبدء مشاركة البيانات عبر الأجهزة من خلال تقنية الاتصال القصير المدى (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 التلقائي

بدءًا من الإصدار Android 7.0 (المستوى 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. إذا كنت بحاجة إلى السلوك القديم، يجب استخدام رمز أصلي.