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

يتضمن Android 10 تغييرات في السلوك قد تؤثر في تطبيقك. وتنطبق التغييرات الواردة في هذه الصفحة على تطبيقك عند تشغيله على Android 10، بغض النظر عن 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).

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

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

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

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

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

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

الإصدار Android 6.0 (المستوى 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.

مكتبات أو برامج ثنائية للنظام تم تعيينها إلى ذاكرة التنفيذ فقط

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

يمكنك تحديد ما إذا كان هذا السلوك قد تسبّب في حدوث عطل، من خلال فحص ملف رمز القبور ذي الصلة في /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 والإصدارات الأحدث.
  • لا يتوفّر وضع "المراسلة النصية في الوقت الفعلي" (RTT).

ويمكنك، إن أردت، الحصول على SSLContext تم إيقاف الإصدار 1.3 من بروتوكول أمان طبقة النقل (TLS) فيه من خلال الاتصال SSLContext.getInstance("TLSv1.2"). يمكنك أيضًا تفعيل إصدارات البروتوكول أو إيقافها على أساس كل اتصال من خلال استدعاء setEnabledProtocols() على كائن مناسب.

الشهادات الموقَّعة باستخدام خوارزمية SHA-1 غير موثوق بها في بروتوكول أمان طبقة النقل (TLS)

في نظام التشغيل Android 10، لا تكون الشهادات التي تستخدم خوارزمية التجزئة SHA-1 موثوقة في اتصالات بروتوكول أمان طبقة النقل (TLS). لم تُصدر شهادات CA الجذر هذه الشهادة منذ عام 2016، ولم تعد موثوقة في Chrome أو المتصفحات الرئيسية الأخرى.

يتعذّر إتمام أي محاولة للاتصال إذا كان الاتصال بموقع إلكتروني يقدم شهادة باستخدام خوارزمية SHA-1.

التغييرات والتحسينات في سلوك KeyChain

تتيح بعض المتصفّحات، مثل Google Chrome، للمستخدمين اختيار شهادة عندما يُرسِل خادم بروتوكول أمان طبقة النقل (TLS) رسالة طلب شهادة كجزء من عملية تأكيد اتصال بروتوكول أمان طبقة النقل (TLS). اعتبارًا من Android 10، تلتزم عناصر KeyChain بجهات الإصدار ومَعلمات المواصفات الرئيسية عند طلب البيانات من KeyChain.choosePrivateKeyAlias() لعرض طلب اختيار شهادة للمستخدمين. وعلى وجه الخصوص، لا يحتوي هذا الطلب على خيارات لا تلتزم بمواصفات الخادم.

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

بالإضافة إلى ذلك، ليس من الضروري إعداد قفل شاشة للجهاز في الإصدار 10 من نظام التشغيل Android أو الإصدارات الأحدث لاستيراد المفاتيح أو شهادات CA إلى كائن KeyChain.

تغييرات أخرى في بروتوكول أمان طبقة النقل (TLS) والتشفير

تم إجراء عدة تغييرات طفيفة في مكتبات بروتوكول أمان طبقة النقل والتشفير يتم تطبيقها على Android 10:

  • ويعرض التشفيران AES/GCM/NoPadding وCha20/Poly1305/NoPadding أحجامًا أكثر دقة للمخزن المؤقت من getOutputSize().
  • يتم حذف مجموعة رموز TLS_FALLBACK_SCSV من محاولات الاتصال باستخدام بروتوكول TLS 1.2 أو الإصدارات الأحدث. بسبب التحسينات التي تمّ إجراؤها على عمليات تنفيذ خادم بروتوكول أمان طبقة النقل (TLS)، لا ننصح بتجربة استخدام نسخة احتياطية من بروتوكول أمان طبقة النقل (TLS) خارجي. بدلاً من ذلك، ننصح بالاعتماد على التفاوض على إصدار بروتوكول أمان طبقة النقل (TLS).
  • ChaCha20-Poly1305 هو اسم مستعار لـ ChaCha20/Poly1305/NoPadding.
  • لا تُعتبر أسماء المضيف التي تتضمّن نقاطًا لاحقة أسماء مضيفين صالحة لإشارة اسم الخادم (SNI).
  • يُرجى العلم أنّ الإضافة متوافقة مع الترميز Support_signature_algorithms في CertificateRequest مقبولة عند اختيار مفتاح توقيع للردود على الشهادة.
  • ويمكن استخدام مفاتيح التوقيع المعتمة، مثل تلك المتوفرة من Android Keystore، مع توقيعات RA-PSS في بروتوكول أمان طبقة النقل (TLS).

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

على نظام التشغيل Android 10، لا يتم تثبيت أحداث البث التالية المرتبطة بميزة Wi-Fi المباشر:

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

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

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

إذا أرسل أحد التطبيقات على جهاز Go نية مع الإجراء ACTION_MANAGE_OVERLAY_PERMISSION، يرفض النظام الطلب تلقائيًا، وسيتم نقل المستخدم إلى شاشة الإعدادات تفيد بأنّ الإذن غير مسموح به لأنّه يبطئ الجهاز. إذا استدعاء تطبيق على جهاز Go Settings.canDrawOverlays()، فإن الطريقة دائمًا ما تعرض القيمة "خطأ". ومرة أخرى، لا تسري هذه القيود على التطبيقات التي حصلت على إذن 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 التغييرات التالية في السلوك ذات الصلة باستخدام التطبيقات:

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

  • التدرّج الرمادي لكل تطبيق -

  • حالة تشتيت الانتباه لكل تطبيق -

  • التعليق والتشغيل -

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

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

تم إيقاف مكتبة android.preference نهائيًا.

تم إيقاف مكتبة android.preference نهائيًا اعتبارًا من الإصدار 10 من نظام التشغيل Android. وبدلاً من ذلك، على المطوّرين استخدام مكتبة الإعدادات المفضَّلة AndroidX التي تشكّل جزءًا من حزمة Android Jeetpack. للحصول على مراجع إضافية للمساعدة في عملية نقل البيانات والتطوير، يمكنك الاطّلاع على دليل الإعدادات المعدَّل بالإضافة إلى نموذج تطبيق متاح للجميع ومستندات مرجعية.

تغييرات في مكتبة الملفات بتنسيق ZIP

يقدّم Android 10 التغييرات التالية على الفئات في حزمة java.util.zip التي تعالج ملفات ZIP. تجعل هذه التغييرات سلوك المكتبة أكثر اتساقًا بين Android والأنظمة الأساسية الأخرى التي تستخدم java.util.zip.

آلة نفخ

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

ملف Zip

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

ZipOutputStream

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

التغييرات التي طرأت على الكاميرا

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

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

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

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

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

إيقاف شعاع Android نهائيًا

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

الزاوية التلقائية لـ GradentDrawable هي الآن 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. إذا كنت بحاجة إلى السلوك القديم، يجب استخدام رمز برمجي أصلي