عمليات قفل تفعيل جزئية متوقفة

عمليات قفل التنشيط الجزئية هي آلية في واجهة برمجة تطبيقات PowerManager تسمح للمطوّرين بإبقاء وحدة المعالجة المركزية (CPU) قيد التشغيل بعد إطفاء شاشة الجهاز (سواء بسبب انتهاء مهلة النظام أو المستخدم الذي يضغط على زر التشغيل). يشغِّل تطبيقك قفل تنشيط جزئي من خلال استدعاء acquire() باستخدام العلامة PARTIAL_WAKE_LOCK. يصبح قفل تنشيط الجهاز جزئيًا عالقًا إذا استمر لفترة طويلة أثناء تشغيل تطبيقك في الخلفية (بدون ظهور أي جزء من تطبيقك للمستخدم). يستنزف هذا الشرط بطارية الجهاز لأنه يمنع الجهاز من دخول حالات طاقة منخفضة. يجب عدم استخدام عمليات قفل التنشيط الجزئية إلا عند الضرورة ويتم رفعها في أقرب وقت ممكن عند عدم الحاجة إليها.

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

اكتشاف المشكلة

قد لا تعلم دائمًا أنّ عمليات قفل التنشيط الجزئية لتطبيقك متوقفة. إذا سبق لك نشر تطبيقك، يمكنك الاستفادة من "مؤشرات Android الحيوية" لإعلامك بالمشكلة.

مؤشرات Android الحيوية

يمكن أن تساعد "مؤشرات Android الحيوية" في تحسين أداء تطبيقك من خلال تنبيهك عبر Play Console عندما يعرض التطبيق عمليات قفل تنشيط جزئية متوقفة. تشير "مؤشرات Android الحيوية" إلى أنّ عمليات قفل التنشيط الجزئية متوقفة عندما يتم قفل تنشيط الجهاز جزئيًا لمدة ساعة واحدة على الأقل، بينما يحدث قفل التنشيط الجزئي في الخلفية خلال جلسة عمل البطارية.

يعتمد تعريف جلسة البطارية على إصدار النظام الأساسي.

  • في نظام التشغيل Android 10، تشير جلسة البطارية إلى تجميع كل تقارير البطارية التي تم تلقّيها خلال فترة 24 ساعة معيّنة. يشير تقرير البطارية إلى الفاصل الزمني بين عمليتَي شحن للبطارية تتراوح بين أقل من 20% وأعلى من 80% أو بين أي مستوى شحن وصولاً إلى 100%.
  • في نظام التشغيل Android 11، تكون مدة جلسة البطارية مدّتها 24 ساعة ثابتة.

عدد فترات عمل البطارية المعروضة هو إجمالي عدد مستخدمي التطبيق الذين تم قياسهم. وللحصول على معلومات حول الطريقة التي يجمع بها Google Play بيانات "مؤشرات Android الحيوية"، يُرجى الاطّلاع على مستندات Play Console.

إذا علِمت بأنّ تطبيقك قد واجه عددًا زائدًا من عمليات قفل التنشيط الجزئية المتوقفة، ستتمثل خطوتك التالية في معالجة المشكلة.

حل المشكلة

تم تقديم عمليات قفل التنشيط في الإصدارات السابقة من نظام Android الأساسي، ولكن مع مرور الوقت، أصبحت العديد من حالات الاستخدام التي كانت تتطلب في السابق عمليات قفل التنشيط تتم معالجتها بشكل أفضل من خلال واجهات برمجة تطبيقات أحدث مثل WorkManager.

يحتوي هذا القسم على نصائح لإصلاح عمليات قفل التنشيط، ولكن على المدى الطويل، يمكنك نقل تطبيقك لاتّباع الاقتراحات الواردة في قسم أفضل الممارسات.

يمكنك تحديد وحلّ الأماكن التي تم فيها تفعيل ميزة "قفل التنشيط" وتصحيحها في الرمز، مثل الطلبات إلى فئات newWakeLock(int, String) أو WakefulBroadcastReceiver فرعية. وفي ما يلي بعض المعلومات الإضافية:

  • نقترح عليك تضمين اسم الحزمة أو الفئة أو الطريقة في اسم علامة قفل تنشيط الجهاز حتى تتمكّن من تحديد الموقع الجغرافي في المصدر الذي تم إنشاء ميزة "قفل التنشيط" فيه بسهولة. إليك بعض النصائح الإضافية:
    • لا تضع في الاسم أي معلومات تحدّد الهوية الشخصية، مثل عنوان البريد الإلكتروني. وبخلاف ذلك، سيسجِّل الجهاز _UNKNOWN بدلاً من اسم قفل التنشيط.
    • لا تحصل على اسم الفئة أو الطريقة آليًا، على سبيل المثال عن طريق استدعاء getName()، لأنه قد يتم إخفاء مفاتيح فك تشفيرها باستخدام Proguard. بدلاً من ذلك، استخدم سلسلة غير قابلة للتغيير.
    • لا تضِف عدّادًا أو معرّفات فريدة إلى علامات قفل التنشيط. لن يتمكّن النظام من تجميع عمليات قفل التنشيط التي تم إنشاؤها بالطريقة نفسها لأنّ لها جميعًا معرّفات فريدة.
  • تأكد من أن الرمز يحرر جميع عمليات قفل التنشيط التي يكتسبها. وهذا الإجراء أكثر تعقيدًا من التأكّد من أنّ كل مكالمة واردة إلى acquire() لها مكالمة مقابلة للرقم release(). في ما يلي مثال على قفل التنشيط الذي لم يتم إصداره بسبب استثناء غير مرصود:

    Kotlin

    @Throws(MyException::class)
    fun doSomethingAndRelease() {
        wakeLock.apply {
            acquire()
            doSomethingThatThrows()
            release()  // does not run if an exception is thrown
        }
    }

    Java

        void doSomethingAndRelease() throws MyException {
            wakeLock.acquire();
            doSomethingThatThrows();
            wakeLock.release();  // does not run if an exception is thrown
        }

    في ما يلي نسخة صحيحة من الرمز:

    Kotlin

    @Throws(MyException::class)
    fun doSomethingAndRelease() {
        wakeLock.apply {
            try {
                acquire()
                doSomethingThatThrows()
            } finally {
                release()
            }
        }
    }

    Java

        void doSomethingAndRelease() throws MyException {
            try {
                wakeLock.acquire();
                doSomethingThatThrows();
            } finally {
                wakeLock.release();
            }
        }
  • احرص على إلغاء قفل التنشيط بمجرد عدم الحاجة إليه. على سبيل المثال، إذا كنت تستخدم ميزة "قفل التنشيط" للسماح بإنهاء مهمة في الخلفية، احرص على تنفيذ هذا الإجراء عند انتهاء هذه المَهمّة. إذا استغرقت عملية قفل التنشيط وقتًا أطول من المتوقع بدون إلغاء تعليقه، قد يعني ذلك أن مهمة الخلفية تستغرق وقتًا أطول من المتوقع.

بعد إصلاح المشكلة في الرمز، تحقّق من أنّ تطبيقك يزيل عمليات قفل التنشيط بشكلٍ صحيح باستخدام أدوات Android التالية:

  • dumpsys - أداة توفر معلومات حول حالة خدمات النظام على أحد الأجهزة. للاطّلاع على حالة خدمة الطاقة التي تشمل قائمة بأقفال التنشيط، شغِّل adb shell dumpsys power.

  • Battery Historian - أداة تحلّل مخرجات تقرير أخطاء Android إلى تمثيل مرئي للأحداث المتعلّقة بالطاقة.

أفضل الممارسات

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

إذا كان عليك استخدام عمليات قفل التنشيط الجزئية، اتّبِع الاقتراحات التالية:

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