التغييرات في سلوك الإصدار 7.0 من نظام التشغيل Android

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

إذا سبق لك نشر تطبيق لنظام التشغيل Android، يُرجى العلم بأنّ تطبيقك قد يتأثّر بهذه التغييرات في النظام الأساسي.

البطارية والذاكرة

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

القيلولة

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

صورة توضيحية تبيّن كيف تطبّق ميزة "قيلولة" المستوى الأول من قيود
  نشاط النظام لتحسين عمر البطارية

الشكل 1. صورة توضيحية لكيفية تطبيق ميزة "قيلولة" على المستوى الأول من قيود نشاط النظام لتحسين عمر البطارية

عندما يكون مصدر طاقة بطارية جهاز، والشاشة مطفأة لفترة معينة، يدخل الجهاز إلى القيلولة ويطبّق المجموعة الفرعية الأولى من القيود: يوقف الوصول إلى شبكة التطبيقات ويؤجل المهام والمزامنة. إذا كان الجهاز ثابتًا لفترة معيّنة بعد الدخول إلى القيلولة، يطبّق النظام باقي قيود القيلولة على منبّهات PowerManager.WakeLock وAlarmManager ونظام تحديد المواقع العالمي (GPS) وعمليات البحث عن شبكات Wi-Fi. بغض النظر عما إذا كان يتم تطبيق بعض قيود القيلولة أو جميعها، ينشّط النظام الجهاز لفترات صيانة قصيرة، يتم خلالها السماح للتطبيقات بالوصول إلى الشبكة، ويمكنه تنفيذ أي مهام أو عمليات مزامنة مؤجلة.

صورة توضيحية لكيفية تطبيق Doze لمستوى ثانٍ من قيود نشاط النظام بعد أن يكون الجهاز ثابتًا لفترة معيّنة

الشكل 2. صورة توضيحية لكيفية تطبيق Doze لمستوى ثانٍ من قيود نشاط النظام بعد أن يكون الجهاز ثابتًا لفترة معيّنة

يُرجى العِلم أنّ تفعيل الشاشة أو توصيلها بالجهاز يؤدي إلى الخروج من وضع "القيلولة" وإزالة قيود المعالجة هذه. ولا يؤثر السلوك الإضافي في الاقتراحات وأفضل الممارسات المتعلقة بتعديل تطبيقك حسب الإصدار السابق من Doze الذي تم طرحه في Android 6.0 (المستوى 23 من واجهة برمجة التطبيقات)، وفقًا لما تمت مناقشته في تحسين القيلولة وتطبيقات وضع الاستعداد. عليك مواصلة اتّباع هذه الاقتراحات، مثل استخدام خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" (FCM) لإرسال الرسائل وتلقّيها، والبدء في التخطيط لتلقّي التحديثات من أجل استيعاب سلوك القيلولة الإضافي.

مشروع سفليت: تحسينات الخلفية

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

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

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

لمزيد من المعلومات حول تحسينات الخلفية في Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات) وكيفية تعديل تطبيقك، يمكنك الاطّلاع على تحسينات الخلفية.

التغييرات في الأذونات

يتضمن Android 7.0 تغييرات على الأذونات التي قد تؤثر في تطبيقك.

التغييرات في أذونات نظام الملفات

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

  • يجب ألا يشعر المالك بعد الآن بالإرهاق في أذونات الملفات الخاصة، وستؤدي محاولة إجراء ذلك باستخدام MODE_WORLD_READABLE و/أو MODE_WORLD_WRITEABLE إلى عرض SecurityException.

    ملاحظة: حتى الآن، لم يتم فرض هذا التقييد بالكامل. بإمكان التطبيقات تعديل الأذونات إلى دليلها الخاص باستخدام واجهات برمجة التطبيقات الأصلية أو واجهة برمجة التطبيقات File. مع ذلك، ننصح بشدة بعدم تخفيف الأذونات المؤدية إلى الدليل الخاص.

  • قد يؤدي تمرير معرّفات الموارد المنتظمة (URI) file:// خارج نطاق الحزمة إلى ترك مسار لا يمكن الوصول إليه للمستلِم. لذلك، تؤدي محاولة تمرير معرّف الموارد المنتظم (URI) file:// إلى تشغيل FileUriExposedException. والطريقة التي يُنصح بها لمشاركة محتوى ملف خاص هي استخدام السمة FileProvider.
  • لم يعُد بإمكان "DownloadManager" مشاركة الملفات المخزَّنة بشكل خاص حسب اسم الملف. قد ينتهي الوصول إلى التطبيقات القديمة بمسار لا يمكن الوصول إليه عند الوصول إلى COLUMN_LOCAL_FILENAME. وتؤدي التطبيقات التي تستهدف الإصدار 7.0 من نظام التشغيل Android أو الإصدارات الأحدث إلى تشغيل SecurityException عند محاولة الوصول إلى COLUMN_LOCAL_FILENAME. سيظل بإمكان التطبيقات القديمة التي تضبط موقع التنزيل على موقع علني باستخدام DownloadManager.Request.setDestinationInExternalFilesDir() أو DownloadManager.Request.setDestinationInExternalPublicDir() الوصول إلى المسار في COLUMN_LOCAL_FILENAME، ولكن لا يُنصح باستخدام هذه الطريقة أبدًا. والطريقة المفضّلة للوصول إلى ملف تم عرضه من خلال DownloadManager هي استخدام ContentResolver.openFileDescriptor().

مشاركة الملفات بين التطبيقات

بالنسبة إلى التطبيقات التي تستهدف الإصدار 7.0 من نظام التشغيل Android، يفرض إطار عمل Android سياسة واجهة برمجة التطبيقات StrictMode التي تحظر الكشف عن معرّفات الموارد المنتظمة (URI) file:// خارج تطبيقك. وإذا غادر تطبيقك غرضًا يحتوي على معرّف موارد منتظم (URI) لملف، سيتعذّر التطبيق باستثناء FileUriExposedException.

لمشاركة الملفات بين التطبيقات، يجب إرسال معرّف الموارد المنتظم (URI) content:// ومنح إذن وصول مؤقت على معرّف الموارد المنتظم (URI). إنّ أسهل طريقة لمنح هذا الإذن هي باستخدام الفئة FileProvider. لمزيد من المعلومات حول الأذونات ومشاركة الملفات، راجع مشاركة الملفات.

التحسينات المتعلّقة بتسهيل الاستخدام

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

تكبير/تصغير الشاشة

يتيح نظام التشغيل Android 7.0 للمستخدمين ضبط حجم الشاشة الذي يكبّر جميع العناصر على الشاشة أو يقللها، ما يؤدي إلى تحسين إمكانية وصول المستخدمين الذين يعانون من ضعف في النظر إلى الأجهزة. ولا يمكن للمستخدمين تكبير حجم الشاشة لتجاوز الحد الأدنى لعرض الشاشة sw320dp، وهو عرض جهاز Nexus 4، وهو هاتف شائع متوسط الحجم.

شاشة تعرض حجم عرض لم يتم تكبيره أو تصغيره لجهاز يعمل بصورة نظام Android 7.0
شاشة تعرض تأثير زيادة حجم العرض على جهاز يستخدم صورة نظام Android 7.0

الشكل 3. تعرض الشاشة على اليمين تأثير زيادة حجم العرض لجهاز يعمل بصورة نظام Android 7.0.

عند تغيّر كثافة الجهاز، يرسل النظام إشعارات إلى التطبيقات قيد التشغيل بالطرق التالية:

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

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

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

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

  • تجنَّب تحديد الأبعاد بوحدات بكسل، لأنّها لا تتغير بكثافة الشاشة. بدلاً من ذلك، حدِّد السمات باستخدام وحدات بكسل مستقلة الكثافة (dp).

إعدادات الرؤية في معالج الإعداد

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

ربط NDK Apps بمكتبات النظام الأساسي

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

هناك ثلاث طرق قد يحاول تطبيقك الوصول من خلالها إلى واجهات برمجة التطبيقات الخاصة بالنظام الأساسي:

  • يمكن لتطبيقك الوصول مباشرةً إلى مكتبات الأنظمة الأساسية الخاصة. وعليك تحديث تطبيقك لتضمين نسخته الخاصة من تلك المكتبات أو استخدام واجهات برمجة تطبيقات NDK العامة.
  • يستخدم تطبيقك مكتبة تابعة لجهة خارجية يمكنها الوصول إلى مكتبات الأنظمة الأساسية الخاصة. حتى إذا كنت متأكّدًا من أنّ تطبيقك لا يصل إلى المكتبات الخاصة مباشرةً، عليك اختبار تطبيقك لمعرفة ذلك.
  • يشير تطبيقك إلى مكتبة غير مضمّنة في حزمة APK الخاصة به. على سبيل المثال، قد يحدث ذلك إذا حاولت استخدام نسختك الخاصة من OpenSSL ولكنك نسيت تجميعها مع حزمة APK لتطبيقك. وقد يعمل التطبيق بشكل طبيعي على إصدارات نظام Android الأساسي التي تشمل libcrypto.so. ومع ذلك، قد يتعطّل التطبيق على الإصدارات الأحدث من نظام التشغيل Android والتي لا تتضمّن هذه المكتبة (مثل الإصدار 6.0 من نظام التشغيل Android والإصدارات الأحدث). لحل هذه المشكلة، يجب التأكُّد من تجميع جميع المكتبات التي لا تستخدم NDK مع حزمة APK.

يجب ألا تستخدم التطبيقات مكتبات أصلية غير مضمّنة في "NDK" لأنّها قد تتغير أو تتم إزالتها من بين إصدارات Android المختلفة. ويُعدّ التبديل من OpenSSL إلى BuringSSL مثالاً على هذا التغيير. بالإضافة إلى ذلك، بسبب عدم فرض متطلبات توافق لمكتبات الأنظمة الأساسية غير المضمّنة في NDK، قد توفر الأجهزة المختلفة مستويات توافق مختلفة.

للحد من التأثير الذي قد يُحدثه هذا التقييد على التطبيقات التي تم إصدارها حاليًا، يمكن الوصول مؤقتًا إلى مجموعة من المكتبات التي تشهد استخدامًا كبيرًا، مثل libandroid_runtime.so وlibcutils.so وlibcrypto.so وlibssl.so، على التطبيقات التي تستهدف المستوى 23 من واجهة برمجة التطبيقات أو أقل، وذلك على نظام التشغيل Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات). في حال حمّل تطبيقك إحدى هذه المكتبات، تنشئ أداة 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 من واجهة برمجة التطبيقات أو المستويات الأدنى، ويحاول الوصول إلى مكتبة خاصة على جهاز يعمل بالإصدار 7.0 من نظام التشغيل Android، قد يظهر لك تحذير مشابه لما يلي:

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 مرتبط ديناميكيًا من BuringSSL/OpenSSL وتجميعه في حزمة APK.

Android for Work

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

  • يجب تثبيت أداة تثبيت شهادة مفوَّضة قبل أن تتمكّن وحدة التحكّم بسياسة الجهاز من ضبطها. بالنسبة إلى تطبيقات الملف الشخصي وتطبيقات مالك الجهاز والتي تستهدف الإصدار 7.0 من نظام التشغيل Android (المستوى 24 لواجهة برمجة التطبيقات)، عليك تثبيت أداة تثبيت الشهادات المفوَّض قبل طلب وحدة التحكّم بسياسة الجهاز 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() عندما تحاول التطبيقات استرداد سلسلة شهادة العميل لاحقًا. وإذا لزم الأمر، يجب تثبيت شهادة CA في وحدة تخزين بيانات الاعتماد الموثوق بها من خلال واجهة مستخدم الإعدادات بشكل منفصل، وبتنسيق بترميز DER ضمن امتداد الملف crt .أو cer..
  • بدءًا من الإصدار 7.0 من نظام التشغيل Android، تتم إدارة إمكانية تسجيل بصمة الإصبع ومساحة التخزين لكل مستخدم. إذا كان برنامج Device Policy (DPC) التابع لمالك الملف الشخصي يستهدف المستوى 23 (أو أقل) لواجهة برمجة التطبيقات على جهاز يعمل بالإصدار 7.0 من نظام التشغيل Android (المستوى 24 من واجهة برمجة التطبيقات)، سيظل المستخدم قادرًا على ضبط بصمة الإصبع على الجهاز، ولكن لا يمكن لتطبيقات العمل الوصول إلى الملف المرجعي للجهاز. عندما تستهدف وحدة التحكّم بسياسة الجهاز مستوى واجهة برمجة التطبيقات 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) أو طبقة المقابس الآمنة (SSL) الأخرى:

  • مجموعات تشفير RC4 غير مفعّلة الآن.
  • تم تفعيل مجموعات رموز CHACHA20-POLY1305 الآن.

قد يؤدي إيقاف RC4 تلقائيًا إلى حدوث أعطال في اتصال HTTPS أو بروتوكول أمان طبقة النقل (TLS) أو طبقة المقابس الآمنة (SSL) عندما لا يتفاوض الخادم مع مجموعات الرموز الحديثة. والحل المفضَّل هو تحسين ضبط الخادم لإتاحة مجموعات رموز وبروتوكولات ترميز أقوى وأكثر حداثة. من الناحية المثالية، يجب تفعيل TLSv1.2 وAES-GCM، كما يجب تفعيل مجموعة رموز إعادة التوجيه (ECDHE) وتفضيلها.

ويمكن بدلاً من ذلك تعديل التطبيق لاستخدام SSLSocketFactory مخصّص للاتصال بالخادم. يجب تصميم المصنع لإنشاء مثيلات SSLSocket التي يتم فيها تفعيل بعض مجموعات الرموز التي يتطلبها الخادم بالإضافة إلى مجموعات الرموز التلقائية.

ملاحظة: لا ترتبط هذه التغييرات بـ WebView.

التطبيقات التي تستهدف الإصدار Android 7.0

وتنطبق هذه التغييرات في السلوك حصريًا على التطبيقات التي تستهدف Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث. أمّا التطبيقات التي تعمل على نظام التشغيل Android 7.0 أو التي تضبط targetSdkVersion على الإصدار 7.0 أو الإصدارات الأحدث من نظام التشغيل Android، فيجب تعديل تطبيقاتها لإتاحة هذه السلوكيات بشكل صحيح، حيثما ينطبق ذلك على التطبيق.

تغييرات التسلسل

أصلح نظام التشغيل Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) خطأً في عملية احتساب قيمة SerialVersionUID التلقائية التي كانت لا تتطابق فيها مع المواصفات.

إنّ الفئات التي تنفّذ Serializable ولا تحدِّد حقل serialVersionUID صريحًا قد تشهد تغييرًا في رقم تعريف المحتوى التسلسلي التلقائي الخاص بها، ما قد يؤدي إلى طرح استثناء عند محاولة إلغاء ترتيب مثيلات الفئة التي تحمل تسلسلًا على إصدار سابق أو التي تم نشرها على نحو تسلسلي من خلال تطبيق يستهدف إصدارًا سابقًا. ستبدو رسالة الخطأ كما يلي:

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

يتطلّب حلّ هذه المشاكل إضافة حقل serialVersionUID إلى أي فئة متأثرة بالقيمة stream classdesc serialVersionUID من رسالة الخطأ، على سبيل المثال 1234 في هذه الحالة. يتوافق هذا التغيير مع جميع توصيات الممارسات الجيدة لكتابة الرمز التسلسلي، وسيتم تطبيق هذا التغيير على جميع إصدارات Android.

ويرتبط الخطأ المحدّد الذي تم إصلاحه بوجود طرق ثابتة لضبط الإعدادات، مثل <clinit>. وفقًا للمواصفات، إنّ وجود طريقة إعداد ثابتة أو عدم توفّرها في الفئة سيؤثر في المعرّف التسلسلي التلقائي الذي يتم احتسابه لتلك الفئة. قبل إصلاح الخطأ، كان يتم أيضًا إجراء العملية الحسابية للفئة الفائقة بحثًا عن معدِّل ثابت إذا لم تتوفّر في الفئة أي مُهيئات.

للتوضيح، لا يؤثّر هذا التغيير في التطبيقات التي تستهدف المستوى 23 أو أقل لواجهة برمجة التطبيقات، أو الفئات التي تحتوي على حقل serialVersionUID، أو الفئات التي تتضمّن طريقة إعداد ثابتة.

نقاط مهمة أخرى

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

    يجب اختبار تطبيقك لضمان عدم حدوث هذا السلوك يمكنك إجراء ذلك عن طريق التسبب في عطل مماثل عند إغلاق التطبيق يدويًا عبر DDMS.

    وعند حدوث تغيّرات في الكثافة، لا يتم إيقاف التطبيقات التي تستهدف الإصدار 7.0 من نظام التشغيل Android (المستوى 24 لواجهة برمجة التطبيقات) والإصدارات الأحدث، إلا أنّها قد تستجيب بشكل سيئ لتغييرات الإعدادات.

  • من المفترض أن تتمكن التطبيقات التي تعمل بالإصدار 7.0 من نظام التشغيل Android من التعامل مع تغييرات الإعدادات بسلاسة، ويجب ألا تتعطل عند بدء التشغيل لاحقًا. يمكنك التحقق من سلوك التطبيق من خلال تغيير حجم الخط (الإعداد > الشاشة > حجم الخط)، ثم استعادة التطبيق من "التطبيقات الأخيرة".
  • بسبب خطأ في الإصدارات السابقة من Android، لم يصنِّف النظام الكتابة على مقبس بروتوكول التحكم بالنقل (TCP) على سلسلة التعليمات الرئيسية باعتبارها مخالفة للوضع الصارم. يُصلح نظام Android 7.0 هذا الخطأ. تعرض الآن التطبيقات التي تعرض هذا السلوك علامة android.os.NetworkOnMainThreadException. بشكل عام، يُعدّ إجراء عمليات الشبكة على سلسلة التعليمات الرئيسية فكرة سيئة لأنّ هذه العمليات يكون عادةً فيها وقت استجابة عالٍ يتسبب في حدوث أخطاء ANR وتوقُّف مؤقت لعرض البيانات.
  • يتم الآن ضبط مجموعة الطرق Debug.startMethodTracing() تلقائيًا على تخزين الإخراج في الدليل الخاص بالحزمة على مساحة التخزين المشتركة، بدلاً من المستوى الأعلى من بطاقة SD. ويعني هذا أنّ التطبيقات لم تعُد بحاجة إلى طلب إذن WRITE_EXTERNAL_STORAGE لاستخدام واجهات برمجة التطبيقات هذه.
  • بدأت العديد من واجهات برمجة التطبيقات للأنظمة الأساسية الآن في التحقّق من الحمولات الكبيرة التي يتم إرسالها عبر معاملات Binder، وأصبح النظام الآن يعيد استخدام TransactionTooLargeExceptions باسم RuntimeExceptions، بدلاً من تسجيل هذه الحمولات أو إيقافها بدون تنبيه. أحد الأمثلة الشائعة هو تخزين الكثير من البيانات في Activity.onSaveInstanceState()، ما يؤدي إلى أن يعرض ActivityThread.StopInfo RuntimeException عندما يستهدف تطبيقك الإصدار 7.0 من نظام Android.
  • إذا نشر أحد التطبيقات مهام Runnable على View، وكانت View غير مرتبطة بنافذة، يضيف النظام المهمة Runnable إلى "View" في قائمة انتظار، ولن يتم تنفيذ مهمة Runnable إلى أن يتم إرفاق View بالنافذة. يُصلح هذا السلوك الأخطاء التالية:
    • إذا تم نشر تطبيق في View من سلسلة محادثات غير سلسلة محادثات واجهة المستخدم الخاصة بالنافذة المقصودة، قد يتم تنفيذ Runnable على سلسلة المحادثات غير الصحيحة نتيجةً لذلك.
    • إذا تم نشر المهمة Runnable من سلسلة محادثات غير سلسلة محادثات فيديو بتكرار، قد يعرض التطبيق المهمة Runnable.
  • إذا حاول تطبيق على Android 7.0 لديه إذن "DELETE_PACKAGES" حذف حزمة، ولكن ثبَّت تطبيق مختلف هذه الحزمة، يطلب النظام تأكيدًا من المستخدم. في هذا السيناريو، من المفترض أن تتوقّع التطبيقات STATUS_PENDING_USER_ACTION كحالة الإرجاع عند استدعاء PackageInstaller.uninstall().
  • تم إيقاف مقدّم خدمة JCA الذي يُطلق عليه اسم Crypto نهائيًا، لأنّ خوارزميته الوحيدة، SHA1PRNG، ضعيفة التشفير. لم يعُد بإمكان التطبيقات استخدام خوارزمية SHA1PRNG لاشتقاء المفاتيح (بشكل غير آمن)، لأنّ مقدّم الخدمة هذا لم يعُد متوفّرًا. لمزيد من المعلومات، يمكنك الاطّلاع على مشاركة المدونة تم إيقاف مزوِّد خدمة "التشفير من جهة العميل" مع نظام التشغيل Android N.