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

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

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

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

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

القيلولة

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

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

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

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

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

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

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

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

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

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

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

تعرض جميع التطبيقات خطأً في وقت التشغيل عند استدعاء واجهة برمجة تطبيقات لا يمكن للجميع الوصول إليها مؤقتًا ولا يمكن الوصول إليها مؤقتًا. ونتيجة لذلك، يعرض System.loadLibrary وdlopen(3) القيمة NULL، ما قد يتسبّب في تعطُّل تطبيقك. يجب مراجعة رمز تطبيقك لإزالة استخدام واجهات برمجة التطبيقات الخاصة بالنظام الأساسي الأساسي واختبار تطبيقاتك بدقة باستخدام جهاز أو محاكي يعمل بالإصدار Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات). إذا لم تكن متأكدًا مما إذا كان تطبيقك يستخدم المكتبات الخاصة أم لا، يمكنك التحقق من logcat لتحديد خطأ وقت التشغيل.

يوضّح الجدول التالي السلوك الذي من المتوقّع أن يتم رصده من تطبيق ما استنادًا إلى استخدامه للمكتبات الأصلية الخاصة ومستوى واجهة برمجة التطبيقات المستهدَف (android:targetSdkVersion).

مكتبات مستوى واجهة برمجة التطبيقات المستهدف الوصول إلى وقت التشغيل من خلال الرابط الديناميكي سلوك Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) السلوك المستقبلي لنظام Android الأساسي
موقع NDK عام أيّ موقع جغرافي تسهيل الاستخدام يعمل على النحو المتوقّع يعمل على النحو المتوقّع
خاصة (مكتبات خاصة يمكن الوصول إليها مؤقتًا) 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 في نظام التشغيل Android 7.0DK إنشاء قائمة بجميع المكتبات المشتركة المرتبطة ديناميكيًا لملف .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 مرتبط ديناميكيًا من BoingSSL/OpenSSL ووضعه في حزمة APK.

Android for Work

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

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

تغييرات الإعدادات التلقائية لطبقة النقل الآمنة/طبقة المقابس الآمنة

يُجري نظام التشغيل Android 7.0 التغييرات التالية على الإعدادات التلقائية لبروتوكول أمان طبقة النقل (TLS)/طبقة المقابس الآمنة التي تستخدمها التطبيقات مع حركة بيانات HTTPS وزيارات بروتوكول أمان طبقة النقل أو طبقة المقابس الآمنة الأخرى:

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

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

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

ملاحظة: لا تنطبق هذه التغييرات على WebView.

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

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

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

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

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

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

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

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

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

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

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

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

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

  • يجب أن تتمكن التطبيقات التي تعمل بنظام التشغيل Android 7.0 من التعامل مع تغييرات الإعدادات بشكل سلس، ويجب ألا تتعطل في عمليات التشغيل اللاحقة. يمكنك التحقق من سلوك التطبيق من خلال تغيير حجم الخط (الإعدادات > الشاشة > حجم الخط)، ثم استعادة التطبيق من "التطبيقات الأخيرة".
  • بسبب خطأ في الإصدارات السابقة من Android، لم يضع النظام علامة على الكتابة في مقبس بروتوكول التحكم بالنقل على سلسلة التعليمات الرئيسية باعتبارها انتهاكًا صارمًا للوضع الصارم. يُصلح الإصدار 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.
  • إذا حاول تطبيق على الإصدار 7.0 من نظام التشغيل Android حاصل على إذن DELETE_PACKAGES حذف حزمة، ولكن تم تثبيت تلك الحزمة على تطبيق مختلف، يتطلب النظام تأكيدًا من المستخدم. في هذا السيناريو، من المفترض أن يكون STATUS_PENDING_USER_ACTION كحالة الإرجاع عند استدعاء PackageInstaller.uninstall().
  • إنّ مقدّم خدمة JCA المسمى Crypto تم إيقافه نهائيًا، لأنّ خوارزميته الوحيدة، SHA1PRNG، ضعيفة من ناحية التشفير. لم يعد بإمكان التطبيقات استخدام SHA1PRNG للحصول على المفاتيح (بشكل غير آمن)، لأنّ مقدّم الخدمة لم يعُد متوفرًا. لمزيد من المعلومات، يمكنك الاطّلاع على مشاركة المدونة تم إيقاف مقدّم خدمة "التشفير" للأمان في نظام التشغيل Android N.