تغييرات في السلوك في Android 7.0

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

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

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

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

القيلولة

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

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

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

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

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

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

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

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