بالإضافة إلى الميزات والإمكانات الجديدة، يتضمّن نظام التشغيل Android 7.0 مجموعة متنوعة من التغييرات في سلوك النظام وواجهة برمجة التطبيقات. يسلّط هذا المستند الضوء على بعض التغييرات الرئيسية التي يجب فهمها ومراعاتها في تطبيقاتك.
إذا سبق لك نشر تطبيق لنظام التشغيل Android، يُرجى العِلم أنّ تطبيقك قد يتأثر بهذه التغييرات في النظام الأساسي.
البطارية والذاكرة
يتضمّن الإصدار 7.0 من نظام التشغيل Android تغييرات في سلوك النظام تهدف إلى تحسين عمر بطارية الأجهزة والحد من استخدام ذاكرة الوصول العشوائي. يمكن أن تؤثر هذه التغييرات في إمكانية وصول تطبيقك إلى موارد النظام، بالإضافة إلى طريقة تفاعل تطبيقك مع التطبيقات الأخرى من خلال طلبات محددة ضمنية.
القيلولة
تم تقديم وضع "الاستراحة" في الإصدار 6.0 من نظام التشغيل Android (المستوى 23 لواجهة برمجة التطبيقات)، وهو يعمل على تحسين عمر البطارية من خلال تأجيل أنشطة وحدة المعالجة المركزية والشبكة عندما يترك المستخدم الجهاز غير متصل بالطاقة، غير متحرّك، وشاشة الجهاز مطفأة. يقدّم الإصدار 7.0 من نظام التشغيل Android مزيدًا من التحسينات على وضع "الاستراحة" من خلال تطبيق مجموعة فرعية من قيود وحدة المعالجة المركزية والشبكة عندما يكون الجهاز غير متصل بالطاقة وشاشة الجهاز مطفأة، ولكن ليس بالضرورة أن يكون غير متحرّك، على سبيل المثال، عندما يكون الهاتف الجوّال في جيب المستخدم.
عندما يكون مصدر طاقة الجهاز هو البطارية مع إطفاء الشاشة لفترة معيّنة، يدخل الجهاز في وضع "القيلولة" ويطبّق المجموعة الفرعية الأولى من القيود، وهي: إيقاف الوصول إلى شبكة التطبيقات وتأجيل المهام والمزامنة. إذا كان الجهاز
ثابتًا لفترة معيّنة بعد الدخول إلى وضع "القيلولة"، يطبّق النظام
بقية قيود "القيلولة" على منبّهات PowerManager.WakeLock
وAlarmManager
، ونظام تحديد المواقع العالمي (GPS)، وعمليات البحث عن شبكة Wi-Fi. بغض النظر عمّا إذا كان يتم تطبيق بعض قيود وضع "الاستراحة" أو كلها، يوقِظ النظام الجهاز لفترات صيانة قصيرة، يُسمح خلالها للتطبيقات بالوصول إلى الشبكة ويمكنها تنفيذ أي مهام أو عمليات مزامنة مؤجلة.
يُرجى العِلم أنّ تفعيل الشاشة أو توصيل الجهاز بالطاقة يؤدي إلى إيقاف وضع "الاستراحة الذكية" ويؤدي بدوره إلى إزالة هذه القيود المفروضة على المعالجة. لا يؤثر السلوك الإضافي في الاقتراحات وأفضل الممارسات المتعلّقة بتكييف تطبيقك مع الإصدار السابق من وضع "الاستراحة الذكية" الذي تم تقديمه في الإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات)، كما هو موضّح في مقالة تحسين الأداء في وضعَي "الاستراحة الذكية" و"الاستعداد" للتطبيقات. يجب اتّباع هذه الاقتراحات، مثل استخدام "المراسلة عبر السحابة الإلكترونية من Firebase" (FCM) لإرسال الرسائل واستلامها، والبدء في التخطيط للتعديلات لاستيعاب السلوك الإضافي لميزة "وضع السكون".
Project Svelte: Background Optimizations
يزيل الإصدار 7.0 من Android ثلاث عمليات بث ضمنية للمساعدة في تحسين استخدام الذاكرة واستهلاك الطاقة. هذا التغيير ضروري لأنّ عمليات البث التلقائية تبدأ غالبًا التطبيقات التي سجّلت للاستماع إليها في الخلفية. يمكن أن تؤدي إزالة هذه البثّات إلى تحسين أداء الجهاز وتجربة المستخدم بشكل كبير.
تواجه الأجهزة الجوّالة تغييرات متكررة في الاتصال، مثل التبديل
بين شبكة Wi-Fi وبيانات الجوّال. يمكن للتطبيقات حاليًا رصد التغييرات في
الاتصال عن طريق تسجيل جهاز استقبال لبث CONNECTIVITY_ACTION
الضمني في
بيان التطبيق. وبما أنّ العديد من التطبيقات مسجَّلة لتلقّي هذا البث، يمكن أن يؤدي تبديل شبكة واحد
إلى تنشيطها جميعًا ومعالجة البث في
آنٍ واحد.
وبالمثل، في الإصدارات السابقة من Android، يمكن للتطبيقات التسجيل لتلقّي رسائل بث ضمنية في ACTION_NEW_PICTURE
وACTION_NEW_VIDEO
من تطبيقات أخرى، مثل "الكاميرا". عندما يلتقط مستخدم صورة باستخدام تطبيق "الكاميرا"، يتم تفعيل هذه التطبيقات
لمعالجة البث.
للتخفيف من هذه المشاكل، يطبّق نظام Android 7.0 التحسينات التالية:
- إذا كانت التطبيقات تستهدف الإصدار 7.0 من نظام التشغيل Android (المستوى 24 لواجهة برمجة التطبيقات) والإصدارات الأحدث، لن تتلقّى عمليات بث
CONNECTIVITY_ACTION
إذا تم تضمين جهاز استقبال البث في ملف البيان. سيستمر تسجيل التطبيقات لبثّاتCONNECTIVITY_ACTION
إذا سجّلتBroadcastReceiver
معContext.registerReceiver()
وكان هذا السياق لا يزال صالحًا. - لم يعُد النظام يرسل عمليات البث
ACTION_NEW_PICTURE
أوACTION_NEW_VIDEO
. يؤثر هذا التحسين في جميع التطبيقات، وليس فقط تلك التي تستهدف الإصدار 7.0 من نظام التشغيل Android.
إذا كان تطبيقك يستخدم أيًا من هذه الأغراض، يجب إزالة التبعيات
عليها في أقرب وقت ممكن حتى تتمكن من استهداف أجهزة Android 7.0 بشكل صحيح.
يقدّم إطار عمل Android عدة حلول لتقليل الحاجة إلى
عمليات البث الضمنية هذه. على سبيل المثال، توفّر واجهة برمجة التطبيقات JobScheduler
آلية فعّالة لجدولة
عمليات الشبكة عند استيفاء شروط محدّدة، مثل الاتصال بشبكة
غير محدودة. يمكنك أيضًا استخدام JobScheduler
للتفاعل مع التغييرات التي تطرأ على مقدّمي المحتوى.
لمزيد من المعلومات عن تحسينات الخلفية في Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات) وكيفية تكييف تطبيقك، اطّلِع على تحسينات الخلفية.
تغييرات الأذونات
يتضمّن الإصدار 7.0 من نظام التشغيل Android تغييرات على الأذونات قد تؤثر في تطبيقك.
تغييرات أذونات نظام الملفات
لتحسين أمان الملفات الخاصة، تم حظر الوصول إلى الدليل الخاص
في التطبيقات التي تستهدف الإصدار 7.0 من نظام التشغيل Android أو الإصدارات الأحدث (0700
).
يمنع هذا الإعداد تسرُّب البيانات الوصفية للملفات الخاصة، مثل حجمها
أو وجودها. لهذا التغيير في الأذونات تأثيرات جانبية متعدّدة:
-
يجب أن يتوقف المالك عن تخفيف أذونات الملفات الخاصة،
وسيؤدي محاولة إجراء ذلك باستخدام
MODE_WORLD_READABLE
و/أوMODE_WORLD_WRITEABLE
إلى تشغيلSecurityException
.ملاحظة: لم يتم فرض هذا القيد بالكامل حتى الآن. قد تظل التطبيقات قادرة على تعديل الأذونات الخاصة بدليلها الخاص باستخدام واجهات برمجة التطبيقات الأصلية أو واجهة برمجة التطبيقات
File
. ومع ذلك، ننصح بشدة بعدم تخفيف القيود المفروضة على الأذونات في الدليل الخاص. -
قد يؤدي تمرير معرّفات الموارد المنتظِمة
file://
خارج نطاق الحزمة إلى ترك مسار المُستلِم فيه مسار لا يمكن الوصول إليه. وبالتالي، يتم محاولة تمرير معرِّف الموارد المنتظم (URI) الخاص بـfile://
إلىFileUriExposedException
. والطريقة المقترَحة لمشاركة محتوى ملف خاص هي استخدامFileProvider
. -
لم يعُد بإمكان
DownloadManager
مشاركة الملفات التي تم تخزينها بشكل خاص حسب اسم الملف. قد تنتهي التطبيقات القديمة بمسار لا يمكن الوصول إليه عند الوصول إلىCOLUMN_LOCAL_FILENAME
. تؤدي التطبيقات التي تستهدف نظام التشغيل Android 7.0 أو إصدار أحدث إلى تشغيلSecurityException
عند محاولة الوصول إلىCOLUMN_LOCAL_FILENAME
. بالنسبة إلى التطبيقات القديمة التي تضبط موقع التنزيل على موقع علني باستخدامDownloadManager.Request.setDestinationInExternalFilesDir()
أوDownloadManager.Request.setDestinationInExternalPublicDir()
، سيظل بإمكانها الوصول إلى المسار فيCOLUMN_LOCAL_FILENAME
، ولكن لا يُنصح باستخدام هذه المحاولة. إنّ الطريقة المفضّلة للوصول إلى ملف تم عرضه من خلالDownloadManager
هي استخدامContentResolver.openFileDescriptor()
.
مشاركة الملفات بين التطبيقات
بالنسبة إلى التطبيقات التي تستهدف الإصدار 7.0 من نظام التشغيل Android، يفرض إطار عمل Android
سياسة واجهة برمجة التطبيقات StrictMode
التي تحظر عرض معرّفات الموارد المنتظمة file://
خارج تطبيقك. إذا خرجت نية تحتوي على معرّف موارد منتظم لملف من تطبيقك، سيتعطّل التطبيق
باستثناء FileUriExposedException
.
لمشاركة الملفات بين التطبيقات، عليك إرسال عنوان URI content://
ومنح إذن وصول مؤقت إلى عنوان URI. إنّ أسهل طريقة لمنح هذا الإذن هي
باستخدام فئة FileProvider
. لمزيد من المعلومات
حول الأذونات ومشاركة الملفات،
راجع مشاركة الملفات.
تحسينات تسهّل الاستخدام
يشمل الإصدار Android 7.0 تغييرات تهدف إلى تحسين سهولة استخدام النظام الأساسي للمستخدمين الذين يعانون من ضعف أو ضعف في النظر. من المفترض أنّ هذه التغييرات لا تتطلّب بشكل عام إجراء تغييرات على الرمز في تطبيقك، ولكن عليك مراجعة هذه الميزات واختبارها مع تطبيقك لتقييم التأثيرات المحتملة على تجربت المستخدم.
تكبير/تصغير الشاشة
يتيح نظام التشغيل Android 7.0 للمستخدمين ضبط حجم الشاشة الذي يكبِّر أو يصغر جميع العناصر على الشاشة، ما يُحسِّن بالتالي إمكانية استخدام الجهاز لدى المستخدمين الذين يعانون من ضعف في البصر. لا يمكن للمستخدمين تكبير الشاشة إلى أكثر من الحد الأدنى لعرض الشاشة الذي يبلغ sw320dp، وهو عرض هاتف Nexus 4، وهو هاتف شائع متوسط الحجم.
عند تغيُّر كثافة الجهاز، يرسل النظام إشعارات إلى التطبيقات قيد التشغيل بالطرق التالية:
- إذا كان التطبيق يستهدف المستوى 23 أو أقل لواجهة برمجة التطبيقات، يوقف النظام تلقائيًا جميع عملياته التي تعمل في الخلفية. وهذا يعني أنّه إذا غيّر المستخدم تركيزه عن تطبيق مماثل لفتح شاشة الإعدادات وغيّر إعداد حجم الشاشة، سيغلق النظام التطبيق بالطريقة نفسها التي سيغلق بها التطبيق في حال انخفاض ذاكرة الجهاز. وإذا كان التطبيق يحتوي على أي عمليات تعمل في المقدّمة، يرسل النظام إشعارًا إلى هذه العمليات المتعلقة بتغيير الإعدادات على النحو الموضّح في قسم التعامل مع التغييرات في وقت التشغيل، كما لو كان اتجاه الجهاز قد تغيّر.
- إذا كان التطبيق يستهدف الإصدار 7.0 من نظام التشغيل Android، يتم إشعار جميع عملياته (في المقدّمة والخلفية) بتغيير الإعدادات كما هو описан في معالجة تغييرات وقت التشغيل.
لا تحتاج معظم التطبيقات إلى إجراء أي تغييرات لتفعيل هذه الميزة، شرط أن تلتزم التطبيقات بأفضل ممارسات Android. وفي ما يلي بعض النقاط المحدّدة التي يجب التحقّق منها:
- اختبِر تطبيقك على جهاز بعرض شاشة
sw320dp
وتأكَّد من أنّه يعمل بشكلٍ ملائم. - عند تغيير إعدادات الجهاز، عدِّل أي معلومات محفوظة مؤقتًا في ذاكرة التخزين المؤقت
تعتمد على الكثافة، مثل ملفات الأشكال المرقّطة أو الموارد المحفوظة مؤقتًا في ذاكرة التخزين المؤقت والتي تم تحميلها من
الشبكة. تحقَّق من حدوث تغييرات في الإعدادات عند استئناف تشغيل التطبيق من حالة الإيقاف المؤقت.
ملاحظة: إذا كنت تخزِّن مؤقتًا البيانات التي تعتمد على الإعدادات، من الجيد تضمين البيانات الوصفية ذات الصلة، مثل حجم الشاشة المناسب أو كثافة البكسل لهذه البيانات. يتيح لك حفظ هذه البيانات الوصفية تحديد ما إذا كنت بحاجة إلى إعادة تحميل البيانات المخزّنة مؤقتًا بعد تغيير إعدادات.
- تجنَّب تحديد الأبعاد باستخدام وحدات البكسل، لأنّها لا تقيس كثافة الشاشة. بدلاً من ذلك، حدِّد الأبعاد باستخدام وحدات بكسل
مستقلة الكثافة (
dp
).
إعدادات الرؤية في معالج الإعداد
يشتمل الإصدار Android 7.0 على "إعدادات الرؤية" على شاشة الترحيب، حيث يمكن للمستخدمين ضبط إعدادات تسهيل الاستخدام التالية على جهاز جديد: إيماءة التكبير وحجم الخط وحجم العرض وTalkBack. يؤدي هذا التغيير إلى زيادة مستوى ظهور الأخطاء المرتبطة بإعدادات الشاشة المختلفة. لتقييم تأثير هذه الميزة، عليك اختبار تطبيقاتك مع تفعيل هذه الإعدادات. يمكنك العثور على الإعدادات ضمن الإعدادات > تسهيل الاستخدام.
ربط تطبيقات NDK بمكتبات النظام الأساسي
بدءًا من الإصدار Android 7.0، يمنع النظام التطبيقات من الربط الديناميكي بمكتبات غير NDK، ما قد يؤدي إلى تعطُّل تطبيقك. ويهدف هذا التغيير في السلوك إلى توفير تجربة متّسقة على التطبيق في جميع تحديثات النظام الأساسي والأجهزة المختلفة. على الرغم من أنّ رمزك البرمجي قد لا يرتبط بالمكتبات الخاصة، من الممكن أن تؤدي مكتبة ثابتة تابعة لجهة خارجية في تطبيقك إلى ذلك. لذلك، على جميع المطوّرين التحقّق مما إذا كانت تطبيقاتهم لا تتعطل على الأجهزة التي تعمل بنظام التشغيل Android 7.0. إذا كان تطبيقك يستخدم رمزًا أصليًا، يجب استخدام واجهات برمجة التطبيقات العامة لـ NDK فقط.
هناك ثلاث طُرق قد يحاول تطبيقك من خلالها الوصول إلى واجهات برمجة التطبيقات الخاصة بمنصّة:
- يصل تطبيقك مباشرةً إلى مكتبات المنصات الخاصة. عليك تحديث تطبيقك لتضمين نسخة خاصة به من هذه المكتبات أو استخدام واجهات برمجة التطبيقات المتاحة للجميع في حزمة NDK.
- يستخدم تطبيقك مكتبة تابعة لجهة خارجية تحصل على إذن بالوصول إلى مكتبات منصّة خاصة. حتى إذا كنت متأكدًا من أنّ تطبيقك لا يصل إلى المكتبات الخاصة مباشرةً، يجب اختبار تطبيقك لهذا السيناريو.
- يشير تطبيقك إلى مكتبة غير مضمّنة في حزمة APK. على سبيل المثال، قد يحدث ذلك إذا حاولت استخدام نسختك الخاصة من مكتبة OpenSSL ولكنكลืม تجميعها مع حِزمة APK لتطبيقك. قد يعمل التطبيق بشكلٍ طبيعي على إصدارات
من نظام التشغيل Android التي تتضمّن
libcrypto.so
. ومع ذلك، قد يتعطّل التطبيق في الإصدارات الأحدث من نظام التشغيل Android التي لا تتضمن هذه المكتبة (مثل Android 6.0 والإصدارات الأحدث). لإصلاح هذه المشكلة، تأكَّد من تجميع جميع المكتبات التي لا تستخدم تنسيق NDK مع حزمة APK.
يجب ألا تستخدم التطبيقات مكتبات برمجية أصلية غير مضمّنة في حزمة NDK لأنّه قد يتم تغييرها أو إزالتها بين إصدارات Android المختلفة. يُعدّ التبديل من OpenSSL إلى BoringSSL مثالاً على هذا التغيير. بالإضافة إلى ذلك، بسبب عدم توفّر متطلبات التوافق لمكتبات النظام الأساسي التي لم يتم تضمينها في NDK، قد توفّر الأجهزة المختلفة مستويات مختلفة من التوافق.
لتقليل التأثير الذي قد يتركه هذا التقييد على التطبيقات التي تم طرحها
حاليًا، يمكن استخدام مجموعة من المكتبات التي يتم استخدامها بشكل كبير، مثل
libandroid_runtime.so
وlibcutils.so
وlibcrypto.so
وlibssl.so
،
مؤقتًا على الإصدار 7.0 من Android (المستوى 24 لواجهة برمجة التطبيقات) للتطبيقات التي تستهدِف المستوى 23 لواجهة برمجة التطبيقات أو
إصدارًا أقل. إذا كان تطبيقك يحمِّل إحدى هذه المكتبات، يُنشئ Logcat تحذيرًا
ويظهر إشعار منبثق على الجهاز المستهدف لإشعارك بذلك. إذا ظهرت لك هذه
التحذيرات، يجب تحديث تطبيقك إما لتضمين نسخته الخاصة من هذه المكتبات أو استخدام واجهات برمجة تطبيقات NDK العامة فقط. قد تفرض الإصدارات المستقبلية من منصة Android
قيودًا على استخدام المكتبات الخاصة تمامًا وتؤدي إلى تعطُّل
تطبيقك.
تُنشئ جميع التطبيقات خطأً في وقت التشغيل عند طلب بيانات من واجهة برمجة تطبيقات ليست
متاحة للجميع أو متاحة مؤقتًا. والنتيجة هي أنّ كلاً من
System.loadLibrary
وdlopen(3)
يعرضان
NULL
، وقد يؤدي ذلك إلى تعطُّل تطبيقك. عليك مراجعة رمز
تطبيقك لإزالة استخدام واجهات برمجة التطبيقات الخاصة بالنظام الأساسي واختبار تطبيقاتك بدقّة
باستخدام جهاز أو محاكي يعمل بنظام التشغيل Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات). إذا كنت
غير متأكّد مما إذا كان تطبيقك يستخدم مكتبات خاصة، يمكنك الاطّلاع على logcat لتحديد خطأ وقت التشغيل.
يوضّح الجدول التالي السلوك الذي من المفترض أن يظهر من
التطبيق استنادًا إلى استخدامه للمكتبات الأصلية الخاصة ومستوى
واجهة برمجة التطبيقات المستهدَف (android:targetSdkVersion
).
المكتبات | مستوى واجهة برمجة التطبيقات المستهدف | الوصول إلى وقت التشغيل من خلال أداة ربط ديناميكية | سلوك Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات) | سلوك نظام Android الأساسي في المستقبل |
---|---|---|---|---|
NDK Public | هل مِن | تسهيل الاستخدام | يعمل على النحو المتوقع | يعمل على النحو المتوقع |
خاصة (مكتبات خاصة يمكن الوصول إليها مؤقتًا) | 23 أو أقل | متاح مؤقتًا | يعمل التطبيق على النحو المتوقّع، ولكنّك تتلقّى تحذيرًا من logcat. | حدث خطأ في وقت التشغيل |
خاصة (مكتبات خاصة يمكن الوصول إليها مؤقتًا) | 24 أو إصدار أحدث | محظور | حدث خطأ في وقت التشغيل | حدث خطأ في وقت التشغيل |
خاص (غير ذلك) | هل مِن | محظور | حدث خطأ في وقت التشغيل | خطأ في بيئة التشغيل |
التحقّق مما إذا كان تطبيقك يستخدم مكتبات خاصة
لمساعدتك في تحديد المشاكل المتعلّقة بتحميل المكتبات الخاصة، قد يُنشئ logcat تحذيرًا أو خطأ وقت التشغيل. على سبيل المثال، إذا كان تطبيقك يستهدف المستوى 23 من واجهة برمجة التطبيقات أو أقل، وحاول الوصول إلى مكتبة خاصة على جهاز يعمل بنظام التشغيل Android 7.0، قد يظهر لك تحذير مشابه لما يلي:
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so" ("/system/lib/libandroid_runtime.so") needed or dlopened by "/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120
تُعلمك تحذيرات logcat هذه بالمكتبة التي تحاول الوصول إلى واجهة برمجة تطبيقات خاصة بالمنصة، ولكنها لن تؤدي إلى تعطُّل تطبيقك. إذا كان التطبيق يستهدف المستوى 24 من واجهة برمجة التطبيقات أو الإصدارات الأحدث، يُنشئ logcat خطأ وقت التشغيل التالي وقد يتعطّل تطبيقك:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace" at java.lang.Runtime.loadLibrary0(Runtime.java:977) at java.lang.System.loadLibrary(System.java:1602)
قد تظهر لك أيضًا نتائج logcat هذه إذا كان تطبيقك يستخدم مكتبات تابعة لجهات خارجية
ترتبط ديناميكيًا بواجهات برمجة تطبيقات المنصة الخاصة. تسمح لك أداة readelf في الإصدار 7.0DK من Android بإنشاء قائمة بجميع المكتبات المشتركة المرتبطة ديناميكيًا لملف .so
معيّن من خلال تنفيذ الأمر التالي:
aarch64-linux-android-readelf -dW libMyLibrary.so
تحديث تطبيقك
في ما يلي بعض الخطوات التي يمكنك اتّخاذها لحلّ هذه الأنواع من الأخطاء والتأكّد من أنّ تطبيقك لا يتعطّل عند تحديثات النظام الأساسي المستقبلية:
- إذا كان تطبيقك يستخدم مكتبات نظام أساسي خاصة، عليك تحديثه لتضمين نسخته الخاصة من هذه المكتبات أو استخدام واجهات برمجة التطبيقات المتاحة للجميع في NDK.
- إذا كان تطبيقك يستخدم مكتبة تابعة لجهة خارجية تحصل على رموز خاصة، يُرجى التواصل مع مؤلف المكتبة لتعديلها.
- تأكَّد من حزم جميع مكتباتك غير التابعة لمجموعة تطوير البرامج (NDK) مع حِزمة APK.
- استخدام دوال JNI العادية بدلاً من
getJavaVM
وgetJNIEnv
منlibandroid_runtime.so
:AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
- استخدِم
__system_property_get
بدلاً من رمزproperty_get
الخاص منlibcutils.so
. لإجراء ذلك، استخدِم__system_property_get
مع تضمين ما يلي:#include <sys/system_properties.h>
ملاحظة: لا يتم اختبار مدى توفّر خصائص النظام ومحتواها من خلال CTS. وأفضل حلّ هو تجنُّب استخدام هذه السمات تمامًا.
- استخدِم نسخة محلية من رمز
SSL_ctrl
منlibcrypto.so
. على سبيل المثال، يجب ربطlibcyrpto.a
بشكل ثابت في ملف.so
، أو تضمين إصدار مرتبط ديناميكيًا منlibcrypto.so
من BoringSSL/OpenSSL وتجميعه في حزمة APK.
Android for Work
يتضمّن الإصدار 7.0 من نظام التشغيل Android تغييرات على التطبيقات التي تستهدف برنامج "Android للعمل"، بما في ذلك تغييرات على تثبيت الشهادة وإعادة ضبط كلمة المرور وإدارة المستخدم الثانوي والوصول إلى معرّفات الجهاز. وإذا كنت تنشئ تطبيقات لبيئات Android for Work، ينبغي لك مراجعة هذه التغييرات وتعديل تطبيقك وفقًا لذلك.
- يجب تثبيت أداة تثبيت شهادات مفوَّضة حتى تتمكّن وحدة التحكّم بسياسة الجهاز من ضبطها. بالنسبة إلى كلٍّ من تطبيقات الملف الشخصي وتطبيقات مالك الجهاز التي تستهدف الإصدار 7.0 من نظام التشغيل Android (المستوى 24 لواجهة برمجة التطبيقات)،
عليك تثبيت أداة تثبيت الشهادات المفوَّضة قبل أن تُجري "وحدة التحكّم بسياسة الجهاز" (DPC) مكالمات
DevicePolicyManager.setCertInstallerPackage()
. إذا لم تكن أداة التثبيت مثبّتة، سيعرض النظام الرمزIllegalArgumentException
. - تنطبق الآن قيود إعادة ضبط كلمة المرور لمشرفي الجهاز على مالكي الملف الشخصي. لم يعُد بإمكان مشرفي الجهاز استخدام
DevicePolicyManager.resetPassword()
لمحو كلمات المرور أو تغيير الكلمات التي سبق ضبطها. سيظل بإمكان مشرفي الجهاز ضبط كلمة مرور، ولكن فقط عندما لا يتضمن الجهاز كلمة مرور أو رقم تعريف شخصي أو نقش. - يمكن لمالكي الأجهزة والملفات الشخصية إدارة الحسابات حتى في حال تم ضبط القيود. يمكن لمالكي الأجهزة وأصحاب الملفات التجارية استدعاء واجهات برمجة التطبيقات لإدارة الحسابات
حتى في حال فرض قيود على
DISALLOW_MODIFY_ACCOUNTS
المستخدم. - يمكن لمالكي الأجهزة إدارة المستخدمين الثانويين بسهولة أكبر. عندما يكون الجهاز
يعمل في وضع مالك الجهاز، يتم ضبط القيود
DISALLOW_ADD_USER
تلقائيًا. ويمنع ذلك المستخدمين من إنشاء مستخدمين ثانويين غير مُدارين. بالإضافة إلى ذلك، تم إيقاف الطريقتَينCreateUser()
وcreateAndInitializeUser()
نهائيًا، وتم استبدالهما بالطريقة الجديدةDevicePolicyManager.createAndManageUser()
. - يمكن لمالكي الأجهزة الوصول إلى معرّفات الأجهزة. يمكن لمالك الجهاز الوصول إلى
عنوان MAC لشبكة Wi-Fi الخاصة بالجهاز باستخدام
DevicePolicyManager.getWifiMacAddress()
. إذا لم يتم تفعيل Wi-Fi مطلقًا على الجهاز، تُرجع هذه الطريقة القيمةnull
. - يتحكّم إعداد "وضع العمل" في الوصول إلى تطبيقات العمل. عندما يكون وضع العمل غير مفعّل، يشير مشغّل النظام إلى أنّ تطبيقات العمل غير متاحة من خلال جعلها تظهر باللون الرمادي. ويؤدي تفعيل وضع العمل مرة أخرى إلى استعادة السلوك العادي.
- عند تثبيت ملف PKCS #12 يحتوي على سلسلة شهادات العميل والمفتاح الخاص المقابل من واجهة مستخدم الإعدادات، لن يتم تثبيت شهادة CA في السلسلة في وحدة تخزين بيانات الاعتماد الموثوق بها. لا يؤثر
ذلك في نتيجة
KeyChain.getCertificateChain()
عندما تحاول التطبيقات استرداد سلسلة شهادات العميل لاحقًا. يجب تثبيت شهادة هيئة إصدار الشهادات، إذا لزم الأمر، في وحدة تخزين بيانات الاعتماد الموثوق بها من خلال واجهة مستخدم الإعدادات بشكل منفصل، باستخدام تنسيق بترميز DER ضمن امتداد ملف .crt أو .cer. - اعتبارًا من الإصدار 7.0 من Android، يتم إدارة تسجيل بصمة الإصبع وتخزينها لكل مستخدم. إذا كان برنامج Device Policy Client (عميل سياسة الجهاز) الخاص بصاحب الملف الشخصي يستهدف مستوى واجهة برمجة التطبيقات 23 (أو إصدارًا أقدم) على جهاز يعمل بالإصدار 7.0 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 24)، سيظل بإمكان المستخدم ضبط بصمة الجهاز، ولكن لا يمكن لتطبيقات العمل الوصول إلى بصمة الجهاز. عندما يستهدف DPC مستوى واجهة برمجة التطبيقات 24 والإصدارات الأحدث، يمكن للمستخدم ضبط بصمة أمان ملف العمل تحديدًا من خلال الانتقال إلى الإعدادات > الأمان > أمان ملف العمل.
- يعرض
DevicePolicyManager.getStorageEncryptionStatus()
حالة تشفير جديدةENCRYPTION_STATUS_ACTIVE_PER_USER
للإشارة إلى أنّ التشفير مفعَّل وأنّ مفتاح التشفير مرتبط بالمستخدم. لا يتم عرض الحالة الجديدة إلا إذا كان "الإصدار القابل للحمل" يستهدف المستوى 24 من واجهة برمجة التطبيقات أو المستويات الأحدث. بالنسبة إلى التطبيقات التي تستهدف مستويات واجهة برمجة التطبيقات السابقة، يتم عرضENCRYPTION_STATUS_ACTIVE
حتى إذا كان مفتاح التشفير خاصًا بالمستخدم أو الملف الشخصي. - في نظام التشغيل Android 7.0، تختلف طريقة عمل العديد من الطرق التي تؤثر عادةً في
الجهاز بالكامل إذا كان الجهاز يحتوي على ملف عمل تم تثبيته باستخدام
تحدّي عمل منفصل. بدلاً من التأثير في الجهاز بالكامل، تنطبق هذه
الطرق على الملف الشخصي للعمل فقط. (القائمة الكاملة بهذه الطرق مدرَجة في مستندات
DevicePolicyManager.getParentProfileInstance()
.) على سبيل المثال، يؤدي استخدامDevicePolicyManager.lockNow()
إلى قفل الملف الشخصي للعمل فقط، بدلاً من قفل الجهاز بالكامل. بالنسبة إلى كلّ من هذه الطرق، يمكنك الحصول على السلوك القديم من خلال استدعاء الطريقة في مثيل العنصر الرئيسي لمحاولةDevicePolicyManager
، ويمكنك الحصول على هذا العنصر الرئيسي من خلال استدعاءDevicePolicyManager.getParentProfileInstance()
. على سبيل المثال، في حال استدعاء طريقةlockNow()
للمثيل الرئيسي، يتم قفل الجهاز بالكامل.
الاحتفاظ بالتعليقات التوضيحية
يعالج نظام التشغيل Android 7.0 خللًا كان يؤدي إلى تجاهل مستوى ظهور التعليقات التوضيحية. سمحت هذه المشكلة لوقت التشغيل بالوصول إلى التعليقات التوضيحية التي لم يكن من المفترض أن يتم الوصول إليها. وتشمل هذه التعليقات التوضيحية ما يلي:
VISIBILITY_BUILD
: من المفترض أن تكون مرئية في وقت الإنشاء فقط.-
VISIBILITY_SYSTEM
: يُفترض أن تكون مرئية في وقت التشغيل، ولكن للنظام الأساسي فقط.
إذا كان تطبيقك يعتمد على هذا السلوك، يُرجى إضافة سياسة الاحتفاظ بالبيانات إلى التعليقات التوضيحية التي يجب أن تكون متوفرة أثناء التشغيل. يمكنك إجراء ذلك باستخدام @Retention(RetentionPolicy.RUNTIME)
.
تغييرات الإعدادات التلقائية لبروتوكول أمان طبقة النقل (TLS) أو طبقة المقابس الآمنة (SSL)
يُجري نظام التشغيل Android 7.0 التغييرات التالية على الإعدادات التلقائية لبروتوكول أمان طبقة النقل (TLS)/طبقة المقابس الآمنة (SSL) التي تستخدمها التطبيقات في بروتوكول HTTPS وعمليات نقل البيانات الأخرى عبر بروتوكول أمان طبقة النقل (TLS)/طبقة المقابس الآمنة:
- تم إيقاف مجموعات ترميز RC4 الآن.
- تم تفعيل مجموعات رموز التشفير CHACHA20-POLY1305 الآن.
قد يؤدي إيقاف RC4 تلقائيًا إلى حدوث انقطاعات في الاتصال عبر HTTPS أو بروتوكول أمان طبقة النقل (TLS)/طبقة المقابس الآمنة (SSL) عندما لا يتفاوض الخادم مع مجموعات التشفير الحديثة. الإجراء المفضّل هو تحسين إعدادات الخادم لتفعيل مجموعات الرموز البرمجية والبروتوكولات الأكثر أمانًا وحداثة. ومن المفترض أن يتم تفعيل TLSv1.2 وAES-GCM، وتفعيل مجموعات رموز خوارزمية "السرية لإعادة التوجيه" (ECDHE) وتفضيلها.
هناك بديل وهو تعديل التطبيق لاستخدام SSLSocketFactory
مخصّص للتواصل مع الخادم. يجب تصميم مصنع
لإنشاء مثيلات SSLSocket
تتضمّن بعض مجموعات التشفير المطلوبة من قبل المعالج
بالإضافة إلى مجموعات التشفير التلقائية.
ملاحظة: لا تتعلّق هذه التغييرات بـ WebView
.
التطبيقات التي تستهدف الإصدار 7.0 من Android
تنطبق تغييرات السلوك هذه حصريًا على التطبيقات التي تستهدف
الإصدار 7.0 من نظام التشغيل Android (المستوى 24 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث. بالنسبة إلى التطبيقات التي يتم تجميعها لنظام التشغيل Android 7.0
أو التي تم ضبط targetSdkVersion
فيها على Android 7.0 أو إصدار أحدث، يجب تعديل
هذه التطبيقات لتتوافق مع هذه السلوكيات بشكل صحيح، حيثما ينطبق ذلك على التطبيق.
تغييرات على التسلسل
تم إصلاح خلل في Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) في عملية احتساب القيمة التلقائية لملف serialVersionUID حيث لم تكن مطابقة للمواصفات.
إنّ الفصول التي تنفِّذ Serializable
ولا تحدِّد حقل serialVersionUID
صريحًا قد تلاحظ
تغييرًا في serialVersionUID التلقائي الذي قد يؤدي إلى طرح استثناء
عند محاولة تحويل ترميز نُسخ من الفئة تم تحويل ترميزها
في إصدار سابق أو تم تحويل ترميزها بواسطة تطبيق يستهدف إصدارًا سابقًا. ستظهر رسالة الخطأ على النحو التالي:
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
ولحلّ هذه المشاكل، يجب إضافة الحقل serialVersionUID
إلى
أي فئة متأثرة باستخدام القيمة stream classdesc
serialVersionUID
الواردة في رسالة الخطأ، مثل 1234
في
هذه الحالة. يلتزم هذا التغيير بجميع اقتراحات أفضل الممارسات لكتابة رمز التسلسل وسيعمل على جميع إصدارات Android.
كان الخطأ المحدّد الذي تم إصلاحه مرتبطًا بتوفّر
طرق أداة الإعداد الثابتة، مثل <clinit>
. وفقًا للمواصفات، سيؤثر توفُّر طريقة الإعداد الثابتة أو عدم توفّرها في الفئة على الرقم التسلسلي التسلسلي الافتراضي الذي يتم احتسابه لهذه الفئة.
قبل إصلاح الخطأ، كانت العملية الحسابية تتحقّق أيضًا من فئة السوبر بحثًا عن ملف بدء static
إذا لم تكن الفئة تتضمّن ملفًا.
للتوضيح، لا يؤثر هذا التغيير في التطبيقات التي تستهدف المستوى 23 من واجهة برمجة التطبيقات أو المستويات الأقل، أو الفئات التي تحتوي على حقل serialVersionUID
أو الفئات التي تستخدم طريقة أداة الإعداد الثابتة.
نقاط مهمة أخرى
- عندما يعمل تطبيق على الإصدار 7.0 من نظام التشغيل Android، ولكنه يستهدف مستوى واجهة برمجة تطبيقات أقل،
ويغيّر المستخدم حجم العرض، تنتهي عملية التطبيق. يجب أن يكون التطبيق
قادرًا على التعامل مع هذا السيناريو بسلاسة. بخلاف ذلك، سيتعطّل التطبيق
عند استعادته من "التطبيقات المستخدَمة مؤخرًا".
عليك اختبار تطبيقك للتأكّد من عدم حدوث هذا السلوك. يمكنك إجراء ذلك عن طريق التسبب في حدوث عطل مماثل عند إغلاق التطبيق يدويًا من خلال DDMS.
لا يتم تلقائيًا إغلاق التطبيقات التي تستهدف الإصدار 7.0 من نظام التشغيل Android (المستوى 24 لواجهة برمجة التطبيقات) والإصدارات الأحدث عند حدوث تغييرات في الكثافة، ولكن قد لا تستجيب بشكل جيد لتغييرات الإعدادات.
- من المفترض أن تتمكّن التطبيقات على نظام التشغيل Android 7.0 من التعامل بسلاسة مع تغييرات الضبط، وأن لا تتعطل عند عمليات البدء اللاحقة. يمكنك التحقق من سلوك التطبيق من خلال تغيير حجم الخط (الإعدادات > الشاشة > حجم الخط)، ثم استعادة التطبيق من "التطبيقات الأخيرة".
-
نتيجة لخطأ في الإصدارات السابقة من Android، لم يضع النظام علامة على الكتابة في مقبس بروتوكول التحكم بالنقل في سلسلة التعليمات الرئيسية كانتهاك للوضع الصارم. يعالج الإصدار 7.0 من Android هذا الخطأ.
تعرض التطبيقات التي تعرض هذا السلوك الآن
android.os.NetworkOnMainThreadException
. بشكل عام، يُعدّ إجراء عمليات على الشبكة على سلسلة التعليمات الرئيسية فكرة سيئة، لأنّ هذه العمليات لها وقت استجابة طويل عادةً، ما يؤدي إلى حدوث أخطاء ANR وحالات تعطّل الخدمة. -
أصبحت مجموعة طُرق
Debug.startMethodTracing()
تستخدم الآن تلقائيًا طريقة تخزين الإخراج في الدليل الخاص بالحزمة على مساحة التخزين المشتركة، بدلاً من تخزينه في المستوى الأعلى من بطاقة SD. يعني ذلك أنّ التطبيقات لم تعد بحاجة إلى طلب إذنWRITE_EXTERNAL_STORAGE
لاستخدام واجهات برمجة التطبيقات هذه. -
بدأت العديد من واجهات برمجة التطبيقات للمنصات الآن في التحقّق من الأحمال الكبيرة التي يتم إرسالها
في
Binder
معاملة، ويقوم ال system الآن بإعادة طرحTransactionTooLargeExceptions
بصفتهاRuntimeExceptions
، بدلاً من تسجيلها أو قمعها بصمت. ومن أحد مثالي الشائعين تخزين بيانات كثيرة جدًا فيActivity.onSaveInstanceState()
، مما يؤدي إلى ظهور خطأRuntimeException
فيActivityThread.StopInfo
عندما يستهدف تطبيقك الإصدار 7.0 من نظام التشغيل Android. -
إذا نشر تطبيق مهام
Runnable
فيView
، ولم يكنView
مرفقًا بنوافذ، يضِف النظامRunnable
إلى "قائمة الانتظار" معView
، ولا يتم تنفيذRunnable
إلى أن يتم إرفاقView
بنوافذ. يؤدي هذا الإجراء إلى إصلاح الأخطاء التالية: -
إذا حاول تطبيق على Android 7.0 حاصل على
DELETE_PACKAGES
إذن حذف حزمة، لكنّ تطبيقًا آخر ثبّت هذه الحزمة، يتطلّب النظام تأكيدًا من المستخدم. في هذا السيناريو، من المفترض أن تتوقع التطبيقاتSTATUS_PENDING_USER_ACTION
كحالة الإرجاع عند استدعاءPackageInstaller.uninstall()
. - تم إيقاف مقدّم بنية تشفير جافا (JCA) المُسمى Crypto نهائيًا، لأنّ خوارزميته الوحيدة SHA1PRNG ضعيفة من الناحية التشفيرية. لم تعُد التطبيقات قادرة على استخدام SHA1PRNG لإنشاء مفاتيح (بشكل غير آمن) لأنّ مقدّم الخدمة هذا لم يعُد متاحًا. لمزيد من المعلومات، يُرجى الاطّلاع على مشاركة المدونة إيقاف مقدّم خدمة "التشفير" للأمان نهائيًا في Android N.