إلى جانب الميزات والإمكانات الجديدة، يتضمّن Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) مجموعة متنوعة من التغييرات في النظام وسلوك واجهة برمجة التطبيقات. يلقي هذا المستند الضوء على بعض التغييرات الرئيسية التي يجب فهمها وأخذها في الحسبان في تطبيقاتك.
تؤثر معظم هذه التغييرات في جميع التطبيقات، بغض النظر عن إصدار Android الذي تستهدفه. ومع ذلك، هناك العديد من التغييرات تؤثر فقط في التطبيقات التي تستهدف الإصدار 8.0 من نظام التشغيل Android. لزيادة الوضوح إلى أقصى حد، تنقسم هذه الصفحة إلى قسمين: التغييرات على جميع التطبيقات والتغييرات على التطبيقات التي تستهدف الإصدار 8.0 من نظام التشغيل Android.
تغييرات لجميع التطبيقات
تسري تغييرات السلوك هذه على
حدود التنفيذ في الخلفية
هو أحد التغييرات التي أدخلها Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) لتحسين عمر البطارية، فعندما يدخل تطبيقك في حالة مخزَّن مؤقتًا بدون مكوّنات نشطة، يصدر النظام أي عمليات قفل التنشيط التي يحتفظ بها التطبيق.
بالإضافة إلى ذلك، لتحسين أداء الجهاز، يحدّ النظام من سلوكيات معيّنة من خلال التطبيقات التي لا تعمل في المقدّمة. ونخصّ بالذكر الشرط التالي:
- تفرض التطبيقات التي تعمل في الخلفية الآن حدودًا على حرية الوصول إلى الخدمات التي تعمل في الخلفية.
- ولا يمكن للتطبيقات استخدام بياناتها للتسجيل في معظم عمليات البث الضمنية (أي عمليات البث التي لا تستهدف التطبيق تحديدًا).
وبشكلٍ تلقائي، لا تسري هذه القيود إلا على التطبيقات التي تستهدف O. ومع ذلك، يمكن للمستخدمين تفعيل هذه القيود لأي تطبيق من شاشة الإعدادات، حتى إذا لم يستهدف التطبيق O.
يتضمّن الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) أيضًا التغييرات التالية على طرق معيّنة:
- تعرض الطريقة
startService()
الآن علامةIllegalStateException
إذا حاول أحد التطبيقات التي تستهدف الإصدار 8.0 من نظام التشغيل Android استخدام هذه الطريقة عندما لا يُسمح له بإنشاء خدمات في الخلفية. - تُشغِّل طريقة
Context.startForegroundService()
الجديدة خدمة تعمل في المقدّمة. يسمح النظام للتطبيقات بالاتصال برقمContext.startForegroundService()
حتى عندما يكون التطبيق في الخلفية. ومع ذلك، يجب أن يطلب التطبيق الإجراءstartForeground()
الخاصة بتلك الخدمة خلال خمس ثوانٍ من إنشاء الخدمة.
لمزيد من المعلومات، راجِع حدود التنفيذ في الخلفية.
الحدود القصوى للمواقع الجغرافية في الخلفية على أجهزة Android
وللحفاظ على البطارية وتجربة المستخدم وسلامة النظام، تتلقّى التطبيقات في الخلفية تحديثات للموقع الجغرافي بشكل أقل تكرارًا عند استخدامها على جهاز يعمل بنظام التشغيل Android 8.0. يؤثّر هذا التغيير في السلوك على جميع التطبيقات التي تتلقّى تحديثات للموقع الجغرافي، بما في ذلك "خدمات Google Play".
تؤثّر هذه التغييرات في واجهات برمجة التطبيقات التالية:
- موفِّر الموقع المدمج (FLP)
- وضع الحدود الجغرافية
- قياسات GNSS
- إدارة المواقع الجغرافية
- مدير شبكة Wi-Fi
لضمان تشغيل تطبيقك على النحو المتوقع، أكمِل الخطوات التالية:
- راجِع المنطق في تطبيقك وتأكَّد من استخدام أحدث واجهات برمجة تطبيقات للمواقع الجغرافية.
- وعليك اختبار ما إذا كان تطبيقك يُظهر السلوك الذي تتوقعه لكل حالة استخدام.
- يمكنك استخدام موفِّر الموقع المدمج (FLP) أو وضع حدود جغرافية للتعامل مع حالات الاستخدام التي تعتمد على الموقع الجغرافي الحالي للمستخدم.
لمزيد من المعلومات حول هذه التغييرات، يمكنك الاطّلاع على حدود المواقع الجغرافية في الخلفية.
اختصارات التطبيقات
يتضمّن الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) التغييرات التالية على اختصارات التطبيقات:
- لم يعُد لعملية بث
com.android.launcher.action.INSTALL_SHORTCUT
أي تأثير على تطبيقك، لأنها أصبحت الآن بثًا خاصًا ضمنيًا. بدلاً من ذلك، عليك إنشاء اختصار للتطبيق باستخدام طريقةrequestPinShortcut()
من الفئةShortcutManager
. - إنّ الغرض من
ACTION_CREATE_SHORTCUT
يمكن الآن إنشاء اختصارات للتطبيقات التي تديرها باستخدام الفئةShortcutManager
. يمكن لهذا الغرض أيضًا إنشاء اختصارات مشغّل تطبيقات قديمة لا تتفاعل معShortcutManager
. في السابق، كان من الممكن أن ينشئ هذا الغرض اختصارات مشغّلات التطبيقات القديمة فقط. - الاختصارات التي تم إنشاؤها باستخدام
requestPinShortcut()
والاختصارات التي تم إنشاؤها في نشاط يعالج هدفACTION_CREATE_SHORTCUT
أصبحت الآن اختصارات كاملة للتطبيقات. ونتيجة لذلك، يمكن للتطبيقات الآن تحديثها باستخدام الطرق الواردة فيShortcutManager
. - تحتفظ الاختصارات القديمة بوظائفها من الإصدارات السابقة من نظام التشغيل Android، ولكن عليك تحويلها إلى اختصارات في التطبيق يدويًا في تطبيقك.
لمزيد من المعلومات حول التغييرات التي يتم إجراؤها على اختصارات التطبيقات، اطّلِع على دليل ميزة تثبيت الاختصارات والتطبيقات المصغّرة.
اللغات والتدويل
قدّم نظام التشغيل Android 7.0 (مستوى واجهة برمجة التطبيقات 24) مفهوم القدرة على تحديد لغة فئة تلقائية، إلا أنّ بعض واجهات برمجة التطبيقات واصلت استخدام طريقة Locale.getDefault()
العامة بدون وسيطات، حيث كان من المفترض أن تستخدم بدلاً من ذلك لغة الفئة DISPLAY
التلقائية. في نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، تستخدم الطرق التالية الآن Locale.getDefault(Category.DISPLAY)
بدلاً من Locale.getDefault()
:
يعود Locale.getDisplayScript(Locale)
أيضًا
إلى Locale.getDefault()
عندما تكون قيمة
displayScript المحددة للوسيطة Locale
غير متوفرة.
في ما يلي المزيد من التغييرات ذات الصلة باللغة والدولة:
- يؤدي استدعاء
Currency.getDisplayName(null)
إلى إنشاء خطأNullPointerException
، مطابق للسلوك الموثَّق. - تم تغيير تحليل اسم المنطقة الزمنية. في السابق، كانت أجهزة Android تستخدم قيمة ساعة النظام التي تم أخذ عينات منها في وقت التشغيل لتخزين أسماء المناطق الزمنية المستخدَمة في تحليل الأوقات الزمنية. ونتيجةً لذلك، يمكن أن يتأثر التحليل سلبًا إذا كانت ساعة النظام
خاطئة في وقت التشغيل أو في حالات أخرى نادرة.
والآن، في الحالات الشائعة، يستخدم منطق التحليل وحدة ICU وقيمة ساعة النظام الحالية عند تحليل أسماء المناطق الزمنية. يقدّم هذا التغيير نتائج أكثر دقة، والتي قد تختلف عن إصدارات Android السابقة عندما يستخدم تطبيقك فئات مثل
SimpleDateFormat
. - يحدِّث Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) إصدار وحدة ICU إلى الإصدار 58.
نوافذ التنبيهات
إذا كان التطبيق يستخدم إذن SYSTEM_ALERT_WINDOW
ويستخدم أحد أنواع النوافذ التالية لمحاولة عرض
نوافذ التنبيه فوق التطبيقات ونوافذ النظام الأخرى:
...ستظهر هذه النوافذ دائمًا أسفل النوافذ التي تستخدم
نوع النافذة
TYPE_APPLICATION_OVERLAY
. إذا كان التطبيق يستهدف الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، يستخدم التطبيق
TYPE_APPLICATION_OVERLAY
نوع النافذة لعرض نوافذ التنبيهات.
للحصول على مزيد من المعلومات، يُرجى الاطّلاع على القسم أنواع النوافذ الشائعة لنوافذ التنبيهات ضمن التغييرات في سلوك التطبيقات التي تستهدف الإصدار 8.0 من نظام التشغيل Android.
الإدخال والتنقل
نشهد إعادة استخدام التنقل باستخدام لوحة المفاتيح داخل تطبيقات Android مع ظهور تطبيقات Android على ChromeOS وغير ذلك من أشكال الأجهزة الكبيرة، مثل الأجهزة اللوحية. في نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، تمت إعادة معالجة استخدام لوحة المفاتيح كجهاز إدخال للتنقّل، ما أدى إلى إنشاء نموذج أكثر موثوقية ويمكن توقّعه للتنقّل باستخدام الأسهم وعلامات التبويب.
وعلى وجه الخصوص، أجرينا التغييرات التالية على سلوك التركيز على العناصر:
-
إذا لم تكن قد حددت أي ألوان لحالة التركيز لكائن
View
(سواء كان ذلك في المقدمة أو في الخلفية)، يضبط إطار العمل الآن لون تمييز التركيز التلقائي لعنصرView
. إنّ إبراز التركيز هذا عبارة عن شكل تموّج قابل للرسم استنادًا إلى موضوع النشاط.إذا كنت لا تريد أن يستخدم كائن
View
عملية التظليل التلقائية هذه عند التركيز عليها، يمكنك ضبط السمةandroid:defaultFocusHighlightEnabled
علىfalse
في ملف XML للتنسيق الذي يحتوي علىView
، أو ضبط السمةfalse
إلىsetDefaultFocusHighlightEnabled()
في منطق واجهة المستخدم الخاصة بالتطبيق. - لاختبار مدى تأثير إدخال لوحة المفاتيح على تركيز عنصر واجهة المستخدم، يمكنك تفعيل خيار مطوّر البرامج الرسم > إظهار حدود التنسيق. في نظام التشغيل Android 8.0، يعرض هذا الخيار الرمز "X" فوق العنصر الذي يتم التركيز عليه حاليًا.
علاوةً على ذلك، فإن جميع عناصر شريط الأدوات في Android 8.0 هي تلقائيًا مجموعات تنقل باستخدام لوحة المفاتيح، ما يسهّل على المستخدمين التنقل داخل كل شريط أدوات وخارجه ككامل.
لمعرفة المزيد حول كيفية تحسين دعم التنقل بلوحة المفاتيح داخل تطبيقك، اقرأ دليل إتاحة التنقل باستخدام لوحة المفاتيح.
الملء التلقائي لنموذج الويب
الآن وبعد أن أصبح إطار عمل
الملء التلقائي لنظام التشغيل Android متوافقًا مع وظائف الملء التلقائي، تغيّرت الطرق التالية المتعلّقة بكائنات WebView
للتطبيقات المثبّتة على الأجهزة التي تعمل بنظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات):
WebSettings
-
- تعرض الطريقة
getSaveFormData()
الآن القيمةfalse
. وكانت هذه الطريقة في السابق تعرضtrue
بدلاً منها. - لم يعُد للاتصال برقم
setSaveFormData()
أي تأثير.
- تعرض الطريقة
WebViewDatabase
-
- لم يعُد للاتصال برقم
clearFormData()
أي تأثير. - تعرض الطريقة
hasFormData()
الآن القيمةfalse
. في السابق، كانت هذه الطريقة تعرض الخطأtrue
عندما كان النموذج يحتوي على بيانات.
- لم يعُد للاتصال برقم
تسهيل الاستخدام
يتضمّن Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) التغييرات التالية بشأن تسهيل الاستخدام:
-
يحوّل إطار عمل تسهيل الاستخدام الآن جميع إيماءات النقر مرّتين إلى إجراءات
ACTION_CLICK
. يسمح هذا التغيير لميزة TalkBack بعملها مثل خدمات تسهيل الاستخدام الأخرى.إذا كانت كائنات
View
في تطبيقك تستخدم طريقة معالجة مخصّصة باللمس، عليك التأكّد من أنّها لا تزال تعمل مع ميزة TalkBack. قد تحتاج فقط إلى تسجيل معالج النقرات الذي تستخدمه عناصرView
. وإذا ظلت ميزة TalkBack لا تتعرّف على الإيماءات التي تتم على عناصرView
هذه، يمكنك إلغاءperformAccessibilityAction()
. - تتعرّف خدمات تسهيل الاستخدام الآن على جميع مثيلات
ClickableSpan
ضمن كائناتTextView
في تطبيقك.
للاطّلاع على مزيد من المعلومات حول كيفية تسهيل استخدام تطبيقك، اطّلِع على قسم تسهيل الاستخدام.
الاتصال بالشبكات واتصال HTTP(S)
يتضمّن الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) تغييرات السلوك التالية على الشبكات واتصال HTTP(S):
- تتضمّن طلبات OPTIONS بدون نص العنوان
Content-Length: 0
. ولم يكن يتوفّر لها عنوانContent-Length
في السابق. - يعمل HttpURLConnection على تسوية عناوين URL التي تحتوي على مسارات فارغة من خلال إلحاق شرطة مائلة بعد اسم المضيف أو المرجع بشرطة مائلة. على سبيل المثال، تحوّل القيمة
http://example.com
إلىhttp://example.com/
. - أداة اختيار الخادم الوكيل المخصّصة التي تم ضبطها من خلال ProxySelector.setDefault() لا تستهدف سوى العنوان (المخطط والمضيف والمنفذ) لعنوان URL المطلوب. ونتيجةً لذلك، قد يستند اختيار الخادم الوكيل إلى هذه القيم فقط. إنّ عنوان URL الذي تم تمريره إلى أداة اختيار الخادم الوكيل المخصّص لا يتضمّن مسار عنوان URL المطلوب أو معلَمات طلب البحث أو أجزاءً.
- لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) على تصنيفات فارغة.
في السابق، كانت المنصة توفّر حلاً بديلاً لقبول التصنيفات الفارغة في أسماء المضيفين، وهو استخدام غير قانوني لمعرّفات الموارد المنتظمة (URI). وكان هذا الحل البديل متوافقًا مع إصدارات libcore القديمة. وسيرى المطوّرون الذين يستخدمون واجهة برمجة التطبيقات بشكل غير صحيح رسالة ADB: "يحتوي عنوان URI example.com على تصنيفات فارغة في اسم المضيف. تمت كتابة هذا النص بشكل غير صحيح ولن يتم قبوله في إصدارات Android المستقبلية. يزيل الإصدار Android 8.0 هذا الحل البديل، ويعرض النظام قيمة فارغة للمعرّفات الموارد المنتظمة (URI) التي تمت صياغتها بشكل غير صحيح.
- إنّ تطبيق HttpsURLConnection في نظام Android 8.0 لا يؤدي إلى إجراء احتياطي غير آمن لإصدار بروتوكول أمان طبقة النقل (TLS)/بروتوكول طبقة المقابس الآمنة.
- تم تغيير معالجة اتصالات HTTP(S) النفقية على النحو التالي:
- عند إجراء اتصال نفقي HTTPS من خلال الاتصال، يضع النظام رقم المنفذ (443:) بشكل صحيح في سطر المضيف عند إرسال هذه المعلومات إلى خادم وسيط. وفي السابق، كان رقم المنفذ يظهر فقط في خط CONNECT.
- لم يعد النظام يرسل عناوين وكيل المستخدم والتفويض
للخادم الوكيل من طلب نفقي إلى الخادم الوكيل.
لم يعُد النظام يرسل عنوان تفويض الخادم الوكيل على عنوان Http(s)URLConnection إلى الخادم الوكيل عند إعداد النفق. بدلاً من ذلك، ينشئ النظام عنوان تفويض الخادم الوكيل، ويرسله إلى الخادم الوكيل عندما يرسل ذلك الخادم الوكيل HTTP 407 استجابةً للطلب الأولي.
وبالمثل، لا ينسخ النظام بعد ذلك عنوان وكيل المستخدم من الطلب النفقي إلى طلب الخادم الوكيل الذي يُعدّ النفق. بدلاً من ذلك، تنشئ المكتبة عنوان وكيل مستخدم لهذا الطلب.
- تعرض الطريقة
send(java.net.DatagramPacket)
SocketException في حال تعذَّر تنفيذ طريقة connect() التي تم تنفيذها سابقًا.- يعيِّن DatagramSocket.connect() قيمةPendingSocketException في حال حدوث خطأ داخلي. قبل استخدام Android 8.0، كان هناك استدعاء recv() لاحق لاستجابة SocketException على الرغم من نجاح استدعاء send(). من أجل الاتساق، تطرح كلتا المكالمتين الآن SocketException.
- يحاول InetAddress.isReachable() محاولة بروتوكول ICMP قبل العودة إلى بروتوكول
TCP Echo.
- قد يصبح بالإمكان الآن الوصول إلى بعض الأجهزة المضيفة التي تحظر المنفذ 7 (TCP Echo)، مثل google.com، في حال قبول بروتوكول ICMP Echo.
- بالنسبة إلى المضيفين الذين لا يمكن الوصول إليهم، يعني هذا التغيير أنّه يتم قضاء ضعف مقدار الوقت قبل عودة المكالمة.
البلوتوث
يجري نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) التغييرات التالية على طول البيانات التي تستردها طريقة ScanRecord.getBytes()
:
- لا تضع الطريقة
getBytes()
أي افتراضات بشأن عدد وحدات البايت التي يتم استلامها. ولذلك، يجب ألا تعتمد التطبيقات على أي حد أدنى أو أقصى لعدد وحدات البايت المعروضة. بدلاً من ذلك، عليهم تقييم طول الصفيفة الناتجة. - قد تعرض الأجهزة المتوافقة مع البلوتوث 5 بيانات يتجاوز طولها الحد الأقصى السابق وهو 60 بايت تقريبًا.
- في حال لم يوفِّر الجهاز البعيد استجابة فحص، قد يتم عرض أقل من 60 بايت أيضًا.
إمكانية اتصال سلس
يجري نظام Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) عددًا من التحسينات على إعدادات Wi-Fi لتسهيل اختيار شبكة Wi-Fi التي تقدّم أفضل تجربة للمستخدم. تشمل التغييرات المحددة ما يلي:
- تحسينات على مستوى الثبات والموثوقية
- واجهة مستخدم أكثر سهولة في القراءة.
- قائمة واحدة موحّدة لتفضيلات Wi-Fi.
- يتم تفعيل شبكة Wi-Fi تلقائيًا على الأجهزة المتوافقة عندما تكون هناك شبكة محفوظة عالية الجودة بالقرب منك.
الأمان
يتضمن Android 8.0 التغييرات التالية المتعلقة بالأمان:
- لم يعد النظام الأساسي متوافقًا مع SSLv3.
- عند إنشاء اتصال HTTPS بخادم ينفّذ بشكل غير صحيح عملية تفاوض بشأن إصدار بروتوكول أمان طبقة النقل (TLS)، لم يعُد
HttpsURLConnection
يحاول إيجاد الحل البديل للرجوع إلى الإصدارات السابقة من بروتوكول أمان طبقة النقل (TLS) وإعادة المحاولة. - يطبِّق نظام Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) فلتر الحوسبة الآمنة (SECCOMP) على جميع التطبيقات. تقتصر قائمة مكالمات النظام المسموح بها على تلك التي يتم الكشف عنها من خلال النظام الحيوية. وعلى الرغم من توفُّر العديد من طلبات النظام الأخرى للتوافق مع الأنظمة القديمة، إلا أنّنا ننصح بعدم استخدامها.
- يتم الآن تشغيل عناصر
WebView
في تطبيقك في وضع متعدد العمليات. يتم التعامل مع محتوى الويب في عملية منفصلة ومنعزلة عن العملية التي تتضمّن التطبيق لتحسين مستوى الأمان. -
لم يعد بإمكانك افتراض وجود حِزم APK في أدلة تنتهي أسماؤها
بـ -1 أو -2. ويجب أن تستخدم التطبيقات
sourceDir
للحصول على الدليل، وألا تعتمد على تنسيق الدليل مباشرةً. - ولمزيد من المعلومات عن تحسينات الأمان ذات الصلة باستخدام المكتبات الأصلية، يُرجى الاطّلاع على المكتبات الأصلية.
بالإضافة إلى ذلك، يقدِّم Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) التغييرات التالية المتعلقة بتثبيت التطبيقات غير المعروفة من مصادر غير معروفة:
- أصبحت قيمة الإعداد القديم
INSTALL_NON_MARKET_APPS
الآن 1 دائمًا. لتحديد ما إذا كان بإمكان مصدر غير معروف تثبيت التطبيقات باستخدام أداة تثبيت الحزمة، عليك استخدام القيمة المعروضةcanRequestPackageInstalls()
بدلاً من ذلك. - وإذا حاولت تغيير قيمة
INSTALL_NON_MARKET_APPS
باستخدامsetSecureSetting()
، يتم عرضUnsupportedOperationException
. لمنع المستخدمين من تثبيت تطبيقات غير معروفة باستخدام مصادر غير معروفة، يجب بدلاً من ذلك تطبيق القيد المفروض على المستخدمDISALLOW_INSTALL_UNKNOWN_SOURCES
. -
يتم تلقائيًا تفعيل
قيود
DISALLOW_INSTALL_UNKNOWN_SOURCES
للمستخدمين في الملفات الشخصية المُدارة التي تم إنشاؤها على أجهزة تعمل بنظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات). بالنسبة إلى الملفات الشخصية المُدارة الحالية على الأجهزة التي تمت ترقيتها إلى Android 8.0، يتم تفعيل تقييد المستخدمDISALLOW_INSTALL_UNKNOWN_SOURCES
تلقائيًا ما لم يوقِف مالك الملف الشخصي هذا الحظر صراحةً (قبل الترقية) من خلال ضبطINSTALL_NON_MARKET_APPS
على 1.
للحصول على تفاصيل إضافية حول تثبيت التطبيقات غير المعروفة، يُرجى الاطّلاع على دليل أذونات تثبيت التطبيقات غير المعروفة.
للحصول على إرشادات إضافية حول كيفية جعل تطبيقك أكثر أمانًا، راجِع الأمان لمطوّري تطبيقات Android.
الخصوصية
يجري Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) التغييرات التالية المتعلّقة بالخصوصية على النظام الأساسي.
- يتعامل النظام الأساسي الآن مع المعرّفات بشكل مختلف.
-
بالنسبة إلى التطبيقات التي تم تثبيتها قبل الإطلاق عبر الهواء لإصدار Android 8.0 (مستوى واجهة برمجة التطبيقات 26) (المستوى 26 لواجهة برمجة التطبيقات)، تظل قيمة
ANDROID_ID
كما هي ما لم يتم إلغاء تثبيتها ثم إعادة تثبيتها بعد التحديث عبر الهواء. للحفاظ على القيم في جميع عمليات إلغاء التثبيت بعد التحديث عبر الهواء، يمكن لمطوّري البرامج ربط القيم القديمة والجديدة باستخدام الاحتفاظ بنسخة احتياطية من المفتاح/القيمة. - بالنسبة إلى التطبيقات المثبّتة على جهاز يعمل بالإصدار 8.0 من نظام التشغيل Android، يتم الآن تحديد قيمة
ANDROID_ID
لكل مفتاح توقيع التطبيق ولكل مستخدم. وتكون قيمةANDROID_ID
فريدة لكل مجموعة من مفتاح توقيع التطبيق والمستخدم والجهاز. ونتيجةً لذلك، لن يظهر معرّف Android نفسه للتطبيقات التي تستخدم مفاتيح توقيع مختلفة تعمل على الجهاز نفسه (حتى للمستخدم نفسه). - لا تتغير قيمة
ANDROID_ID
عند إلغاء تثبيت الحزمة أو إعادة تثبيتها، طالما أنّ مفتاح التوقيع هو نفسه (ولم يتم تثبيت التطبيق قبل إطلاق التحديث عبر الهواء إلى الإصدار 8.0 من نظام التشغيل Android). - لن تتغيّر قيمة
ANDROID_ID
حتى إذا تسبّب تحديث النظام في تغيير مفتاح توقيع الحزمة. - على الأجهزة التي يتم شحنها باستخدام "خدمات Google Play" والمعرِّف الإعلاني،
عليك استخدام
المعرِّف الإعلاني. هو نظام بسيط وعادي لتحقيق الربح من التطبيقات،
وهو معرّف فريد يمكن للمستخدم إعادة ضبطه لأغراض الإعلان. ويتم توفيرها من خلال "خدمات Google Play".
ويجب على الشركات المصنّعة الأخرى للأجهزة مواصلة توفير السمة
ANDROID_ID
.
-
بالنسبة إلى التطبيقات التي تم تثبيتها قبل الإطلاق عبر الهواء لإصدار Android 8.0 (مستوى واجهة برمجة التطبيقات 26) (المستوى 26 لواجهة برمجة التطبيقات)، تظل قيمة
- ويؤدي إجراء طلب بحث في خاصية النظام
net.hostname
إلى ظهور نتيجة فارغة.
تسجيل الاستثناءات غير المرصودة
إذا ثبّت أحد التطبيقات Thread.UncaughtExceptionHandler
الذي
لا يستدعي Thread.UncaughtExceptionHandler
التلقائي،
لن يوقف النظام
التطبيق عند حدوث استثناء غير مرصود. بدءًا من الإصدار
Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، يسجّل النظام تتبُّع تكديس الاستثناء في هذه الحالة، ففي الإصدارات السابقة من النظام الأساسي، لم يسجّل النظام
تتبُّع تكديس الاستثناء.
ننصح دائمًا باستخدام المعالج التلقائي في عمليات تنفيذ Thread.UncaughtExceptionHandler
المخصّصة، علمًا أنّ التطبيقات التي تتبع هذا الاقتراح لا تتأثر
بالتغيير الذي تم إجراؤه في نظام التشغيل Android 8.0.
تغيير توقيع findViewById()
تعرض جميع مثيلات الطريقة findViewById()
الآن
<T extends View> T
بدلاً من View
. ينتج عن هذا التغيير ما يلي:
- قد يؤدي ذلك إلى أن يكون للرمز الحالي نوع عرض غامض الآن،
على سبيل المثال إذا كان هناك كل من
someMethod(View)
وsomeMethod(TextView)
يأخذ نتيجة الاستدعاء إلىfindViewById()
. - عند استخدام لغة مصدر Java 8، يتطلب ذلك بثًا صريحًا إلى
View
عندما يكون نوع الإرجاع غير محدود (على سبيل المثال،assertNotNull(findViewById(...)).someViewMethod())
. - في حال إلغاء طُرق
findViewById()
غير النهائية (مثلActivity.findViewById()
)، يجب تعديل نوع الإرجاع الخاص بها.
تغيير إحصاءات استخدام مزود جهات الاتصال
في الإصدارات السابقة من نظام التشغيل Android، يسمح مكوّن "مقدِّم خدمات الاتصال" للمطوّرين بالحصول على بيانات الاستخدام لكل جهة اتصال. وتعرض بيانات الاستخدام هذه معلومات كل عنوان بريد إلكتروني وكل رقم هاتف مرتبط بجهة اتصال، بما في ذلك عدد المرات التي تم فيها التواصل مع جهة الاتصال وآخر مرة تم التواصل فيها مع جهة الاتصال هذه. وبإمكان التطبيقات التي تطلب الإذن
READ_CONTACTS
قراءة هذه البيانات.
وسيظل بإمكان التطبيقات قراءة هذه البيانات إذا طلبت إذن
READ_CONTACTS
. في نظام التشغيل Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) والإصدارات الأحدث، تعرض طلبات البحث عن بيانات الاستخدام قيمًا تقريبية بدلاً من القيم الدقيقة. يحافظ نظام Android على
القيم الدقيقة داخليًا، لذلك لا يؤثر هذا التغيير في
واجهة برمجة التطبيقات الخاصة بميزة "الإكمال التلقائي".
يؤثّر هذا التغيير في السلوك في مَعلمات طلب البحث التالية:
التعامل مع المجموعة
AbstractCollection.removeAll()
وAbstractCollection.retainAll()
الآن يطرحان الآن NullPointerException
دائمًا. في السابق،
لم يتم طرح
NullPointerException
عندما كانت المجموعة فارغة. هذا التغيير يجعل السلوك متوافقًا مع الوثائق.
Android Enterprise
يغيِّر نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) سلوك بعض واجهات برمجة التطبيقات والميزات الخاصة بتطبيقات المؤسسات، بما في ذلك وحدات التحكُّم بسياسة الجهاز (DPC). وتشمل التغييرات ما يلي:
- سلوكيات جديدة لمساعدة التطبيقات في دعم الملفات الشخصية للعمل على الأجهزة المُدارة بالكامل
- تغييرات على كيفية التعامل مع تحديثات النظام والتحقّق من التطبيقات والمصادقة لزيادة سلامة النظام والجهاز.
- تحسينات على تجربة المستخدم لتوفير الإشعارات والإشعارات وشاشة "العناصر الأخيرة" والشبكة الافتراضية الخاصة (VPN) التي يتم تشغيلها دائمًا.
للاطّلاع على جميع التغييرات التي طرأت على المؤسسة في Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) ومعرفة مدى تأثيرها المحتمل في تطبيقك، يمكنك الاطّلاع على Android في Enterprise.
التطبيقات التي تستهدف الإصدار Android 8.0
تنطبق هذه التغييرات في السلوك حصريًا على التطبيقات التي تستهدف
Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث. وعلى التطبيقات التي تستخدم الترميز Android 8.0 أو التي تستخدم targetSdkVersion
على الإصدار 8.0 من نظام التشغيل Android أو الإصدارات الأحدث تعديل تلك التطبيقات بما يتوافق مع هذه السلوكيات على نحو سليم، حيثما ينطبق ذلك على التطبيق.
نوافذ التنبيهات
لن تتمكّن التطبيقات التي تستخدم الإذن SYSTEM_ALERT_WINDOW
من استخدام أنواع النوافذ التالية لعرض نوافذ التنبيه
فوق التطبيقات ونوافذ النظام الأخرى:
وبدلاً من ذلك، يجب أن تستخدم التطبيقات نوع نافذة جديدًا يُسمى
TYPE_APPLICATION_OVERLAY
.
عند استخدام نوع نافذة TYPE_APPLICATION_OVERLAY
لعرض نوافذ التنبيهات لتطبيقك، يُرجى مراعاة الخصائص التالية لنوع النافذة الجديد:
- تظهر نوافذ تنبيه التطبيق دائمًا أسفل نوافذ النظام المهمة، مثل شريط الحالة وأدوات IME.
- يمكن للنظام نقل النوافذ التي تستخدم نوع النافذة
TYPE_APPLICATION_OVERLAY
أو تغيير حجمها لتحسين عرض الشاشة. - من خلال فتح مركز الإشعارات، يمكن للمستخدمين الوصول إلى الإعدادات لحظر
تطبيق من عرض نوافذ التنبيه المعروضة باستخدام نوع
نافذة
TYPE_APPLICATION_OVERLAY
.
إشعارات تغيير المحتوى
يغيّر الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) سلوك
ContentResolver.notifyChange()
وregisterContentObserver(Uri, boolean, ContentObserver)
في التطبيقات التي تستهدف الإصدار Android 8.0.
تتطلّب واجهات برمجة التطبيقات هذه الآن تحديد قيمة ContentProvider
صالحة للمرجع في جميع معرّفات Uris. يساعد تحديد ContentProvider
صالح باستخدام الأذونات ذات الصلة في حماية تطبيقك من التغييرات في المحتوى من التطبيقات الضارة، ومنعك من تسرُّب البيانات التي يُحتمَل أن تكون خاصة إلى التطبيقات الضارة.
عرض التركيز
يمكن الآن التركيز تلقائيًا على عناصر View
القابلة للنقر. إذا أردت أن يكون الكائن View
قابلاً للنقر ولكن غير
قابل للتركيز، اضبط السمة
android:focusable
على false
في ملف التنسيق
XML الذي يحتوي على View
، أو اضبط false
على setFocusable()
في منطق واجهة المستخدم الخاصة بالتطبيق.
مطابقة وكيل المستخدم في رصد المتصفِّح
يتضمّن الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) والإصدارات الأحدث سلسلة معرّف الإصدار OPR
. قد تتسبب بعض تطابقات الأنماط
في أن يُعرِّف منطق اكتشاف المتصفِّح بشكل خاطئ أي متصفّح غير Opera على أنه Opera.
فيما يلي مثال على تطابق النمط هذا:
if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}
لتجنُّب المشاكل الناتجة عن سوء تحديد الهوية، استخدِم سلسلة غير OPR
كمطابقة نمط لمتصفّح Opera.
الأمان
تؤثّر التغييرات التالية في الأمان في الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات):
- إذا أوقفت إعدادات أمان الشبكة في تطبيقك إتاحة الزيارات الواردة من نصوص واضحة، لن تتمكّن عناصر
WebView
في تطبيقك من الوصول إلى المواقع الإلكترونية عبر HTTP. ويجب أن يستخدم كل عنصرWebView
بروتوكول HTTPS بدلاً من ذلك. - تمت إزالة الإعداد السماح بمصادر غير معروفة للنظام. بدلاً من ذلك، تتم إدارة عمليات تثبيت التطبيقات غير المعروفة من مصادر غير معروفة باستخدام الإذن تثبيت تطبيقات غير معروفة. لمزيد من المعلومات حول هذا الإذن الجديد، يُرجى الاطّلاع على دليل أذونات تثبيت التطبيقات غير المعروفة.
للحصول على إرشادات إضافية حول كيفية جعل تطبيقك أكثر أمانًا، راجِع الأمان لمطوّري تطبيقات Android.
الوصول إلى الحساب وقابلية اكتشافه
في نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، لا يمكن للتطبيقات الوصول
إلى حسابات المستخدمين ما لم تكن أداة المصادقة تملك الحسابات أو
منح المستخدم هذا الوصول. لم يعُد
إذن "GET_ACCOUNTS
"
كافيًا. ولمنح إمكانية الوصول إلى أحد الحسابات، يجب أن تستخدم التطبيقات
إما AccountManager.newChooseAccountIntent()
أو طريقة خاصة
ببرنامج المصادقة. بعد الوصول إلى الحسابات، يمكن لأي تطبيق الاتصال بـ
AccountManager.getAccounts()
للوصول إليها.
سيوقف Android 8.0
LOGIN_ACCOUNTS_CHANGED_ACTION
. وبدلاً من ذلك، يجب أن تستخدم التطبيقات
addOnAccountsUpdatedListener()
للحصول على آخر الأخبار حول الحسابات أثناء وقت التشغيل.
للحصول على معلومات عن واجهات برمجة التطبيقات والطرق الجديدة التي تمت إضافتها للوصول إلى الحساب وقابلية اكتشافه، يُرجى الاطّلاع على الوصول إلى الحساب وقابلية الاكتشاف في قسم "واجهات برمجة التطبيقات الجديدة" في هذا المستند.
الخصوصية
تؤثّر التغييرات التالية في الخصوصية في نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات).
-
لم تعُد سمات النظام
net.dns1
وnet.dns2
وnet.dns3
وnet.dns4
متوفّرة، وهو تغيير يحسِّن الخصوصية على المنصة. -
للحصول على معلومات الشبكات، مثل خوادم نظام أسماء النطاقات، يمكن للتطبيقات التي لديها إذن
ACCESS_NETWORK_STATE
تسجيل عنصرNetworkRequest
أوNetworkCallback
. تتوفّر هذه الصفوف في Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث. -
تم إيقاف Build.SERIAL نهائيًا.
بدلاً من ذلك، يجب أن تستخدم التطبيقات التي تحتاج إلى معرفة الرقم التسلسلي للجهاز طريقة
Build.getSerial()
الجديدة، والتي تتطلّب الحصول على إذنREAD_PHONE_STATE
. -
لم تعُد واجهة برمجة التطبيقات
LauncherApps
تسمح لتطبيقات الملف الشخصي للعمل بالحصول على معلومات حول الملف الشخصي الأساسي. عندما يكون المستخدم في ملف شخصي للعمل، تعمل واجهة برمجة التطبيقاتLauncherApps
API كما لو لم يتم تثبيت أي تطبيقات في ملفات شخصية أخرى ضمن مجموعة الملفات الشخصية نفسها. وكما أسلفنا، تؤدي محاولات الوصول إلى ملفات شخصية غير ذات صلة إلى SecurityExceptions.
الأذونات
قبل الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، إذا طلب تطبيق إذنًا في وقت التشغيل وتم منح الإذن، كان النظام أيضًا قد منح التطبيق بشكل غير صحيح باقي الأذونات التي تنتمي إلى مجموعة الأذونات نفسها والتي تم تسجيلها في البيان.
بالنسبة إلى التطبيقات التي تستهدف الإصدار 8.0 من نظام التشغيل Android، تم تصحيح هذا السلوك. لا يتم منح التطبيق سوى الأذونات التي طلبها صراحةً. ومع ذلك، بعد منح المستخدم إذنًا للتطبيق، يتم تلقائيًا منح جميع الطلبات اللاحقة للحصول على الأذونات في مجموعة الأذونات هذه.
على سبيل المثال، لنفترض أنّ أحد التطبيقات يدرج كلاً من READ_EXTERNAL_STORAGE
وWRITE_EXTERNAL_STORAGE
في ملف البيان الخاص به.
يطلب التطبيق READ_EXTERNAL_STORAGE
ويمنحه المستخدم. إذا كان التطبيق يستهدف المستوى 25 من واجهة برمجة التطبيقات أو مستوى أقل، يمنح النظام
أيضًا التطبيق WRITE_EXTERNAL_STORAGE
في
الوقت نفسه، لأنّه ينتمي إلى مجموعة أذونات STORAGE
نفسها وهو
مسجَّل أيضًا في البيان. إذا كان التطبيق يستهدف الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، يمنح النظام
READ_EXTERNAL_STORAGE
فقط في ذلك الوقت،
ومع ذلك،
إذا طلب التطبيق لاحقًا WRITE_EXTERNAL_STORAGE
، سيمنح النظام هذا الامتياز على الفور
بدون طلب تأكيد من المستخدم.
الوسائط
- يمكن لإطار العمل تنفيذ
تجنب التداخل التلقائي مع الصوت
بمفرده. في هذه الحالة، عندما يطلب تطبيق آخر التركيز على
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
، سيقلّل التطبيق الذي تم التركيز عليه مستوى الصوت إلا أنّه لا يتلقّى عادةً استدعاءonAudioFocusChange()
ولن يفقد التركيز على الصوت. وتتوفّر واجهات برمجة تطبيقات جديدة لإلغاء هذا السلوك في التطبيقات التي تحتاج إلى الإيقاف المؤقت بدلاً من تجنب التداخل. - عندما يجري المستخدم مكالمة هاتفية، يتم كتم صوت ساحات مشاركات الوسائط النشطة طوال مدة المكالمة.
- يجب أن تستخدم جميع واجهات برمجة التطبيقات المتعلقة بالصوت
AudioAttributes
بدلاً من أنواع البث الصوتي لوصف حالة استخدام تشغيل الصوت. مواصلة استخدام أنواع البث الصوتي لعناصر التحكّم في مستوى الصوت فقط أما الاستخدامات الأخرى لأنواع مصادر البيانات، فتظل صالحة (على سبيل المثال، الوسيطةstreamType
إلى الدالة الإنشائيةAudioTrack
المتوقّفة)، ولكن النظام يسجّل ذلك على أنه خطأ. - عند استخدام
AudioTrack
، إذا كان التطبيق يطلب مخزنًا مؤقتًا للصوت كبيرًا بما يكفي، سيحاول إطار العمل استخدام إخراج المخزن المؤقت العميق إذا كان متاحًا. - في نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، تختلف معالجة أحداث زر الوسائط:
- لم تتغيّر طريقة التعامل مع أزرار الوسائط في نشاط واجهة المستخدم: تظلّ الأنشطة التي تعمل في المقدّمة تحظى بالأولوية في التعامل مع أحداث أزرار الوسائط.
- إذا لم يعالج النشاط الذي يعمل في المقدّمة حدث زر الوسائط، سيوجِّه النظام الحدث إلى التطبيق الذي شغّل المحتوى الصوتي مؤخرًا محليًا. لا يتم أخذ الحالة النشطة والعلامات وحالة التشغيل في الاعتبار عند تحديد التطبيق الذي يتلقى أحداث أزرار الوسائط.
- إذا تم إصدار جلسة وسائط التطبيق،
يرسل النظام حدث زر الوسائط إلى
MediaButtonReceiver
في التطبيق في حال توفّره. - وفي جميع الحالات الأخرى، يتجاهل النظام حدث زر الوسائط.
المكتبات الأصلية
في التطبيقات التي تستهدف Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، لن يطول تحميل المكتبات الأصلية إذا كانت تحتوي على أي شريحة تحميل قابلة للكتابة والتنفيذ في الوقت نفسه. قد تتوقف بعض التطبيقات عن العمل بسبب هذا التغيير إذا كانت بها مكتبات أصلية بها أجزاء تحميل غير صحيحة. هذا أحد إجراءات تعزيز الأمان.
لمزيد من المعلومات، يُرجى الاطّلاع على الشرائح القابلة للكتابة والتنفيذ.
وترتبط تغييرات الروابط بمستوى واجهة برمجة التطبيقات الذي يستهدفه التطبيق. إذا كان هناك تغيير في الرابط على مستوى واجهة برمجة التطبيقات المستهدَف، لن يتمكّن التطبيق من تحميل المكتبة. إذا كنت تستهدِف مستوى واجهة برمجة تطبيقات أقل من مستوى واجهة برمجة التطبيقات الذي يحدث فيه تغيير الرابط، تعرِض logcat تحذيرًا.
التعامل مع المجموعة
في نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)،
يتم تنفيذ Collections.sort()
على
أعلى List.sort()
. والعكس صحيح في الإصدار Android 7.x (مستويان واجهة برمجة التطبيقات 24 و25):
كان التنفيذ التلقائي لـ List.sort()
يُسمى Collections.sort()
.
يسمح هذا التغيير لـ "Collections.sort()
"
بالاستفادة من عمليات تنفيذ List.sort()
المحسَّنة، ولكن تنطبق عليه القيود التالية:
ويجب ألا تؤدي عمليات تنفيذ
List.sort()
إلى استدعاءCollections.sort()
، لأنّ ذلك سيؤدي إلى تجاوز تسلسل استدعاء الدوال البرمجية بسبب التكرار اللانهائي. بدلاً من ذلك، إذا كنت تريد السلوك التلقائي في تنفيذList
، يجب تجنُّب إلغاءsort()
.إذا نفّذت إحدى الصفات الرئيسية السمة
sort()
بشكل غير ملائم، يمكنك عادةً إلغاء السمةList.sort()
باستخدام عملية تنفيذ تم تصميمها أعلىList.toArray()
وArrays.sort()
وListIterator.set()
. مثلاً:@Override public void sort(Comparator<? super E> c) { Object[] elements = toArray(); Arrays.sort(elements, c); ListIterator<E> iterator = (ListIterator<Object>) listIterator(); for (Object element : elements) { iterator.next(); iterator.set((E) element); } }
في معظم الحالات، يمكنك أيضًا إلغاء
List.sort()
باستخدام عملية تنفيذ تفوض عمليات تنفيذ تلقائية مختلفة بناءً على مستوى واجهة برمجة التطبيقات. مثلاً:@Override public void sort(Comparator<? super E> comparator) { if (Build.VERSION.SDK_INT <= 25) { Collections.sort(this); } else { super.sort(comparator); } }
إذا كنت تريد استخدام الطريقة
sort()
على جميع مستويات واجهة برمجة التطبيقات فقط، ننصحك باختيار اسم فريد لها، مثلsortCompat()
، بدلاً من تجاهلsort()
.-
يتم احتساب
Collections.sort()
الآن كتعديل هيكل في عمليات تنفيذ القوائم التي تُسمىsort()
. على سبيل المثال، في إصدارات النظام الأساسي التي تسبق الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، كان من الممكن أن يؤدي تكرارArrayList
وطلبsort()
عليه في جزء من التكرار خلال التكرار إلى عرضConcurrentModificationException
إذا تم الترتيب من خلال طلبList.sort()
. لم يقدّمCollections.sort()
استثناءً.يجعل هذا التغيير سلوك المنصة أكثر اتساقًا، فكِلا الأسلوبين يؤدي الآن إلى
ConcurrentModificationException
.
سلوك تحميل الصفوف
يتحقّق الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) للتأكّد من أنّ برامج تحميل الفئات لا تتّبع افتراضات وقت التشغيل عند تحميل فئات جديدة. يتم إجراء عمليات التحقّق هذه سواء كانت الفئة مُشار إليها من Java (من
forName()
) أو رمز بايت Davik أو JNI. لا يعترض النظام الأساسي المكالمات المباشرة من لغة Java إلى طريقة
loadClass()
، ولا يتحقق
من نتائج هذه الطلبات. ومن المفترض ألا يؤثر هذا السلوك في عمل محمّلات الفئة
ذات الأداء الجيد.
يتحقق النظام الأساسي من أن واصف الفئة التي يعرضها عامل تحميل الفئة يتطابق مع الواصف المتوقع. وإذا كان الواصف المعروض غير مطابق،
تعرض المنصة الخطأ NoClassDefFoundError
، وتخزِّن
في الاستثناء رسالة مفصّلة تشير إلى التناقض.
تتحقّق المنصّة أيضًا من أنّ الأوصاف للفئات المطلوبة صالحة. يرصد هذا
الفحص طلبات JNI التي تحمّل فئات مثل GetFieldID()
بشكل غير مباشر،
ما يؤدي إلى تمرير واصفات غير صالحة إلى تلك الفئات. على سبيل المثال، لم يتم العثور على حقل يحمل التوقيع
java/lang/String
لأنّ هذا التوقيع غير صالح،
يجب أن يكون Ljava/lang/String;
.
ويختلف هذا عن طلب JNI لـ FindClass()
حيث يكون java/lang/String
اسمًا صالحًا ومؤهلاً بالكامل.
لا يتيح نظام Android 8.0 (مستوى واجهة برمجة التطبيقات 26) إمكانية استخدام عدة برامج تحميل للفئات لتحديد الفئات
باستخدام كائن DexFile نفسه. تؤدي محاولة إجراء ذلك إلى عرض وقت تشغيل Android
للخطأ InternalError
يحتوي على الرسالة "محاولة تسجيل ملف dex <filename>
باستخدام برامج تحميل فئات متعددة".
تم إيقاف DexFile API نهائيًا، وننصحك بشدة باستخدام إحدى أدوات تحميل الفئات للنظام الأساسي، بما في ذلك PathClassLoader
أو BaseDexClassLoader
.
ملاحظة: يمكنك إنشاء برامج تحميل متعددة للفئات تشير إلى
حاوية ملف APK أو JAR نفسها من نظام الملفات. لا يؤدي ذلك عادةً إلى زيادة حجم الذاكرة: إذا تم تخزين ملفات DEX في الحاوية بدلاً من ضغطها، يمكن للنظام الأساسي تنفيذ عملية mmap
عليها بدلاً من استخراجها مباشرةً. ومع ذلك، إذا كان على النظام الأساسي استخراج ملف DEX من الحاوية، قد يستهلك الرجوع إلى ملف DEX بهذا الشكل الكثير من الذاكرة.
في نظام Android، تعتبر جميع محمّلات الفئة قادرة على التوازي. عندما تتسابق سلاسل تعليمات متعددة لتحميل نفس الفئة مع أداة تحميل الفئة نفسها، تفوز السلسلة الأولى التي تكمل العملية، ويتم استخدام النتيجة في سلاسل التعليمات الأخرى. يحدث هذا السلوك بغض النظر عما إذا كان برنامج تحميل الفئة قد أعاد نفس الفئة أو أرجع فئة مختلفة أو طرح استثناءً. يتجاهل النظام الأساسي هذه الاستثناءات بدون إزعاج.
تحذير: في إصدارات النظام الأساسي الأقدم من Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات)، يمكن أن يؤدي خرق هذه الافتراضات إلى تعريف الفئة نفسها عدة مرات، وتلف كومة الذاكرة المؤقتة بسبب تضارب الفئات والتأثيرات الأخرى غير المرغوب فيها.