تطبيقات قيد التشغيل دائمًا وميزة "وضع الإضاءة السينمائية"

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

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

المفاهيم الرئيسية

عند عرض تطبيق Wear OS على الشاشة الكاملة، يكون في إحدى حالتَي استهلاك الطاقة التاليتَين:

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

ويتحكّم نظام التشغيل في الانتقال بين هذه الحالات.

التطبيقات المعروضة على الشاشة دائمًا هي تطبيقات تعرض المحتوى في كل من حالتَي التفاعل والعرض على الشاشة.

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

عمليات النقل في النظام والسلوك التلقائي

عندما يكون أحد التطبيقات في المقدّمة، يدير النظام عمليات النقل بين حالات الطاقة استنادًا إلى مهلتَين يتم تفعيلهما بسبب عدم نشاط المستخدم.

  • المهلة الأولى: من الحالة التفاعلية إلى الحالة "الإضاءة السينمائية": بعد فترة من عدم نشاط المستخدم، يدخل الجهاز إلى الحالة الإضاءة السينمائية.
  • المهلة الثانية: الرجوع إلى خلفية شاشة الساعة: بعد مرور فترة أخرى من عدم النشاط، قد يخفي النظام التطبيق الحالي ويعرض خلفية شاشة الساعة.

بعد أن ينتقل النظام إلى حالة الإضاءة السينمائية لأول مرة، يعتمد السلوك التلقائي على إصدار Wear OS وإعدادات تطبيقك:

  • في نظام التشغيل Wear OS 5 والإصدارات الأقدم، يعرض النظام لقطة شاشة مموّهة لتطبيقك الذي تم إيقافه مؤقتًا، مع عرض الوقت فوقها.
  • في Wear OS 6 والإصدارات الأحدث، إذا كان التطبيق يستهدف الإصدار 36 من حزمة تطوير البرامج (SDK) أو إصدارًا أحدث، يتم اعتباره قيد التشغيل دائمًا. يتم تعتيم الشاشة، ولكن يستمر تطبيقك في التشغيل ويظل مرئيًا. (قد لا يتم إجراء التحديثات إلا مرة واحدة كل دقيقة).

تخصيص السلوك لحالة "الإضاءة السينمائية"

بغض النظر عن السلوك التلقائي للنظام، يمكنك في جميع إصدارات Wear OS تخصيص مظهر تطبيقك أو سلوكه أثناء تشغيله في حالة الإضاءة السينمائية من خلال استخدام AmbientLifecycleObserver للاستماع إلى طلبات إعادة الاتصال عند التحولات في الحالة.

استخدام AmbientLifecycleObserver

للتفاعل مع أحداث "وضع الإضاءة السينمائية"، استخدِم فئة AmbientLifecycleObserver:

  1. نفِّذ واجهة AmbientLifecycleObserver.AmbientLifecycleCallback. استخدِم الطريقة onEnterAmbient() لضبط واجهة المستخدم في حالة انخفاض الطاقة، واستخدِم onExitAmbient() لإعادتها إلى الشاشة التفاعلية بالكامل.

    val ambientCallback = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
        override fun onEnterAmbient(ambientDetails: AmbientLifecycleObserver.AmbientDetails) {
            // ... Called when moving from interactive mode into ambient mode.
            // Adjust UI for low-power state: dim colors, hide non-essential elements.
        }
    
        override fun onExitAmbient() {
            // ... Called when leaving ambient mode, back into interactive mode.
            // Restore full UI.
        }
    
        override fun onUpdateAmbient() {
            // ... Called by the system periodically (typically once per minute)
            // to allow the app to update its display while in ambient mode.
        }
    }
    
  2. أنشئ AmbientLifecycleObserver وسجِّله باستخدام دورة حياة نشاطك أو العنصر القابل للتجميع.

    private val ambientObserver = AmbientLifecycleObserver(activity, ambientCallback)
    
    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(ambientObserver)
    
        // ...
    }
    
  3. يُرجى الاتصال برقم removeObserver() لإزالة المُراقب في onDestroy().

بالنسبة إلى المطوّرين الذين يستخدمون Jetpack Compose، توفّر مكتبة Horologist أداة مفيدة، وهي العنصر القابل للتجميع AmbientAware، ما يسهّل تنفيذ هذا النمط.

TimeText معيّن حسب الإضاءة

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

التحكّم في مدّة تشغيل الشاشة

توضّح الأقسام التالية كيفية إدارة مدّة بقاء تطبيقك على الشاشة.

منع الرجوع إلى خلفية شاشة الساعة عندما يكون هناك نشاط جاري

بعد مرور فترة من الوقت في حالة الإضاءة السينمائية (المهلة الثانية)، سيعود النظام عادةً إلى خلفية شاشة الساعة. يمكن للمستخدم ضبط مدة المهلة في إعدادات النظام. في بعض حالات الاستخدام، مثل تتبُّع المستخدم لجلسة تدريب، قد يحتاج التطبيق إلى البقاء مرئيًا لفترة أطول.

في Wear OS 5 والإصدارات الأحدث، يمكنك منع ذلك من خلال تنفيذ نشاط مستمر. إذا كان تطبيقك يعرض معلومات عن مهمة مستخدم جارية، مثل جلسة تدريب، يمكنك استخدام واجهة برمجة التطبيقات Ongoing Activity API لإبقاء تطبيقك مرئيًا إلى أن تنتهي المهمة. إذا عاد المستخدم يدويًا إلى خلفية شاشة الساعة، يقدّم مؤشر النشاط الجاري طريقة بنقرة واحدة للمستخدمين للعودة إلى تطبيقك.

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

private fun createNotification(): Notification {
    val activityIntent =
        Intent(this, AlwaysOnActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
        }

    val pendingIntent =
        PendingIntent.getActivity(
            this,
            0,
            activityIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
        )

    val notificationBuilder =
        NotificationCompat.Builder(this, CHANNEL_ID)
            // ...
            // ...
            .setOngoing(true)

    // ...

    val ongoingActivity =
        OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder)
            // ...
            // ...
            .setTouchIntent(pendingIntent)
            .build()

    ongoingActivity.apply(applicationContext)

    return notificationBuilder.build()
}

إبقاء الشاشة مفعّلة ومنع ظهور "حالة الإضاءة السينمائية"

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

اقتراحات حول "وضع الإضاءة السينمائية"

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

  • استخدام شاشة بسيطة وموفّرة للطاقة
    • يجب أن يكون 85% على الأقل من الشاشة باللون الأسود.
    • استخدِم الخطوط الخارجية للرموز أو الأزرار الكبيرة بدلاً من ألوان التعبئة الكاملة.
    • عرض المعلومات الأكثر أهمية فقط، مع نقل التفاصيل الثانوية إلى الشاشة المتفاعلة
    • تجنَّب استخدام الكتل الكبيرة من الألوان الموحّدة والعلامات التجارية أو الصور الخلفية غير المفيدة.
  • التأكّد من تعديل المحتوى بشكلٍ مناسب
    • بالنسبة إلى البيانات التي تتغيّر بشكل متكرّر، مثل ساعة توقيت أو مسافة تمرين أو وقت، يمكنك عرض محتوى نائب مثل -- لتجنّب إعطاء انطباع بأنّ المحتوى حداثي.
    • إزالة مؤشرات التقدّم التي يتم تعديلها باستمرار، مثل إشارة التنازلي وجلسات الوسائط
    • يجب استخدام طلب إعادة الاتصال onUpdateAmbient() فقط للرسائل المهمة، عادةً مرة واحدة في الدقيقة.
  • الحفاظ على تنسيق موحّد
    • يجب إبقاء العناصر في الموضع نفسه في الوضعَين التفاعلي والإضاءة السينمائية لتحقيق انتقال سلس.
    • عرض الوقت دائمًا
  • أن تكون على دراية بالسياق
    • إذا كان المستخدم على شاشة إعدادات أو شاشة ضبط عندما يدخل الجهاز إلى الوضع السينمائي، ننصحك بعرض شاشة أكثر صلة من تطبيقك بدلاً من عرض إعدادات التطبيق.
  • معالجة المتطلبات الخاصة بالأجهزة
    • في عنصر AmbientDetails الذي تم تمريره إلى onEnterAmbient():
      • إذا كان deviceHasLowBitAmbient هو true، أوقِف ميزة تمويه الحواف كلما أمكن ذلك.
      • إذا كان burnInProtectionRequired هو true، حرِّك عناصر واجهة المستخدم بشكل دوري قليلاً وتجنَّب المناطق البيضاء الخالصة لمنع احتراق الشاشة.

تصحيح الأخطاء والاختبار

قد تكون أوامر adb هذه مفيدة عند تطوير تطبيقك أو اختباره والتحقّق من سلوكه عندما يكون الجهاز في وضع الإضاءة السينمائية:

# put device in ambient mode if the always on display is enabled in settings
# (and not disabled by other settings, such as theatre mode)
$ adb shell input keyevent KEYCODE_SLEEP

# put device in interactive mode
$ adb shell input keyevent KEYCODE_WAKEUP

مثال: تطبيق للتمارين الرياضية

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

لتحقيق ذلك، على المطوّر تنفيذ ما يلي:

  1. نفِّذ AmbientLifecycleObserver للتعامل مع تغييرات واجهة المستخدم بين حالتَي التفاعل والإضاءة السينمائية، مثل تعتيم الشاشة وإزالة البيانات غير الأساسية.
  2. أنشئ تنسيقًا جديدًا يستهلك طاقة منخفضة لحالة الإضاءة السينمائية يتّبع أفضل الممارسات.
  3. استخدِم واجهة برمجة التطبيقات Ongoing Activity API طوال مدة التمرين لمنع System من الرجوع إلى خلفية شاشة الساعة.

للحصول على تنفيذ كامل، اطّلِع على نموذج التمرين المستنِد إلى الإنشاء على GitHub. يوضّح هذا المثال أيضًا استخدام العنصر القابل للتجميع AmbientAware من مكتبة Horologist لتبسيط معالجة الوضع السينمائي في أداة Compose.