يتضمّن الإصدار 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 لواجهة برمجة التطبيقات أم لا. على سبيل المثال، إذا مرّر المستخدم سريعًا من حافة الشاشة، يفسّر النظام هذه الإيماءة على أنّها تنقّل إلى الخطوة السابقة ، ما لم يلغِي تطبيق معيّن هذه الإيماءة على أجزاء من الشاشة.
لجعل تطبيقك متوافقًا مع ميزة التنقّل بالإيماءات، عليك توسيع محتوى التطبيق من حافة إلى أخرى، والتعامل مع الإيماءات المتضاربة بشكل مناسب. للحصول على معلومات، يُرجى الاطّلاع على مستندات التنقّل باستخدام الإيماءات.
NDK
يتضمّن الإصدار 10 من Android التغييرات التالية في حزمة NDK.
لا يمكن أن تحتوي العناصر المشترَكة على عمليات إعادة تحديد موضع النص.
حظر الإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات) استخدام عمليات إعادة تحديد موضع النص في العناصر المشترَكة. يجب تحميل الرمز كما هو، ويجب عدم تعديله. ويؤدي هذا التغيير إلى تحسين أوقات تحميل التطبيقات وأمانها.
يفرض SELinux هذا القيد على التطبيقات التي تستهدف الإصدار 10 من Android أو الإصدارات الأحدث. إذا استمرت هذه التطبيقات في استخدام عناصر مشترَكة تحتوي على عمليات إعادة توجيه للنصوص، ستواجه خطرًا كبيرًا بالتعطُّل.
التغييرات على مكتبات Bionic ومسارات الربط الديناميكي
اعتبارًا من الإصدار 10 من Android، أصبحت عدة مسارات روابط رمزية بدلاً من الملفات العادية. التطبيقات التي كانت تعتمد على المسارات كملفّات عادية قد تتعذّر تشغيلها:
/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 من بروتوكول أمان طبقة النقل مفعَّل تلقائيًا
في الإصدار 10 من Android والإصدارات الأحدث، يكون بروتوكول TLS 1.3 مفعَّلاً تلقائيًا لجميع اتصالات بروتوكول TLS. في ما يلي بعض التفاصيل المهمة حول تنفيذ بروتوكول TLS 1.3:
- لا يمكن تخصيص مجموعات رموز التشفير في بروتوكول أمان طبقة النقل (TLS) 1.3. يتم دائمًا تفعيل مجموعات ترميز بروتوكول أمان طبقة النقل (TLS) 1.3 المتوافقة عند تفعيل بروتوكول أمان طبقة النقل (TLS) 1.3. ويتم تجاهل أي محاولة لإيقاف
هذه الإعدادات من خلال استدعاء
setEnabledCipherSuites()
. - عند التفاوض على بروتوكول أمان طبقة النقل (TLS) 1.3، يتمّ استدعاء
HandshakeCompletedListener
العناصر قبل إضافة الجلسات إلى ذاكرة التخزين المؤقت للجلسات. (في TLS 1.2 والإصدارات السابقة الأخرى، يتمّ استدعاء هذه العناصر بعد إضافة الجلسات إلى ذاكرة التخزين المؤقت للجلسة). - في بعض الحالات التي تُعرِض فيها نُسخ
SSLEngine
SSLHandshakeException
على إصدارات Android السابقة، تعرِض هذه النُسخSSLProtocolException
بدلاً من ذلك على الإصدار 10 من Android والإصدارات الأحدث. - وضع 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، للمستخدمين باختيار شهادة عندما يُرسِل
خادم بروتوكول أمان طبقة النقل رسالة طلب شهادة كجزء من عملية تأكيد اتصال بروتوكول أمان طبقة النقل. اعتبارًا من الإصدار
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"، مع توقيعات 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 ومنفذ الخادم. في السابق، كان يجب إرسال هذه المعلومات خارج النطاق، مثلاً باستخدام رسائل الربط بين الأجهزة عبر البلوتوث أو 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 التغييرات التالية في السلوك المتعلّقة باستخدام التطبيقات:
تغييرات في اتصال HTTPS
إذا تم نقل null
إلى
setSSLSocketFactory()
في تطبيق يعمل بنظام التشغيل Android 10،
يحدث 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
في الإصدار 10 من نظام التشغيل Android والإصدارات الأحدث، لا تُعرِض الطريقة
finish()
في
ZipOutputStream
ZipException
إذا حاولت كتابة مجرى ملف ناتج لملف ZIP لا يحتوي على أي ملفات.
تغييرات الكاميرا
تفترض العديد من التطبيقات التي تستخدم الكاميرا أنّه إذا كان الجهاز في وضع عمودي، فهذا يعني أنّ الجهاز المادي أيضًا في الوضع العمودي، كما هو موضّح في اتجاه الكاميرا. كان هذا الافتراض صحيحًا في السابق، ولكن تغيّر ذلك مع توسيع نطاق أشكال الأجهزة المتاحة، مثل الأجهزة القابلة للطي. يمكن أن يؤدي هذا الافتراض على هذه الأجهزة إلى عرض عدسة الكاميرا بشكل مُعوج أو مُكبَّر بشكل غير صحيح (أو كلاهما).
يجب أن تضبط التطبيقات التي تستهدف المستوى 24 أو أعلى لواجهة برمجة التطبيقات android:resizeableActivity
صراحةً وأن توفّر الوظائف اللازمة للتعامل مع ميزة
تشغيل التطبيقات في وضع "النوافذ المتعددة".
تتبُّع استخدام البطارية
بدءًا من الإصدار 10 من Android، يُعيد
SystemHealthManager
ضبط
إحصاءات استخدام البطارية كلما تم فصل الجهاز عن مصدر الطاقة بعد حدث شارِج
رئيسي. بشكل عام، حدث الشحن الرئيسي هو إما: تم شحن الجهاز
بالكامل، أو تم شحن الجهاز من حالة تفريغ البطارية بالكامل إلى حالة شحنها بالكامل.
قبل الإصدار 10 من Android، كانت تتم إعادة ضبط إحصاءات استخدام البطارية كلما تم فصل الجهاز عن مصدر الطاقة، بغض النظر عن مدى صغر التغيير الذي طرأ على مستوى شحن البطارية.
إيقاف ميزة "الشعاع" في Android نهائيًا
في 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 التلقائي
بدءًا من الإصدار Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات)، أجرى النظام الأساسي إصلاحًا
على القيمة التلقائية serialVersionUID
للعناصر
التي يمكن تسلسلها. ولم يؤثر هذا الإصلاح
في التطبيقات التي تستهدف المستوى 23 أو أقل من واجهة برمجة التطبيقات.
اعتبارًا من الإصدار 10 من نظام التشغيل Android، إذا كان التطبيق يستهدف المستوى 23 أو أقل لواجهة برمجة التطبيقات ويعتمد على serialVersionUID
التلقائي القديم وغير الصحيح، يسجّل النظام تحذيرًا ويقترح إصلاحًا للرمز البرمجي.
وعلى وجه التحديد، يسجّل النظام تحذيرًا في حال استيفاء جميع الشروط التالية:
- يستهدف التطبيق المستوى 23 من واجهة برمجة التطبيقات أو المستويات الأقل.
- يتم تسلسل فئة.
- تستخدِم الفئة التي تم تسلسلها القيمة التلقائية
serialVersionUID
بدلاً من ضبط قيمةserialVersionUID
بشكل صريح. - يختلف
serialVersionUID
التلقائي عنserialVersionUID
الذي سيكون عليه إذا كان التطبيق يستهدف المستوى 24 أو أعلى من واجهة برمجة التطبيقات.
يتم تسجيل هذا التحذير مرّة واحدة لكل فئة متأثرة.
تتضمّن رسالة التحذير حلًا مقترَحًا، وهو ضبط serialVersionUID
صراحةً على القيمة التلقائية التي سيتم احتسابها إذا كان التطبيق يستهدف المستوى 24 من واجهة برمجة التطبيقات أو أعلى. باستخدام هذا الإصلاح، يمكنك التأكّد من أنّه
في حال تسلسل عنصر من هذه الفئة في تطبيق يستهدف المستوى
23 من واجهة برمجة التطبيقات أو مستوى أقل، سيتم قراءة العنصر بشكل صحيح من خلال التطبيقات التي تستهدف المستوى 24 أو مستوى أعلى،
والعكس صحيح.
التغييرات في java.io.FileChannel.map()
اعتبارًا من Android 10، لا يمكن استخدام FileChannel.map()
مع
الملفات غير العادية، مثل /dev/zero
، التي لا يمكن تغيير حجمها باستخدام
truncate()
. كانت الإصدارات السابقة من Android تتجاهل الخطأ errno الذي يعرضه truncate()
، ولكن يُعرِض Android 10 خطأ IOException. إذا كنت بحاجة إلى السلوك القديم،
يجب استخدام رمز أصلي.