برنامه های همیشه روشن و حالت محیطی سیستم

این راهنما توضیح می‌دهد که چگونه برنامه خود را همیشه روشن نگه دارید، چگونه به تغییر وضعیت باتری واکنش نشان دهید و چگونه رفتار برنامه را مدیریت کنید تا ضمن صرفه‌جویی در مصرف باتری ، تجربه کاربری خوبی ارائه دهید.

قابل مشاهده بودن دائمی یک برنامه، تأثیر قابل توجهی بر عمر باتری دارد، بنابراین هنگام افزودن این ویژگی، تأثیر آن بر مصرف برق را در نظر بگیرید.

مفاهیم کلیدی

وقتی یک برنامه Wear OS در حالت تمام صفحه نمایش داده می‌شود، در یکی از دو حالت زیر قرار دارد:

  • تعاملی : حالتی با قدرت بالا که در آن صفحه نمایش در روشنایی کامل قرار دارد و امکان تعامل کامل کاربر را فراهم می‌کند.
  • Ambient : حالتی از کم‌مصرف که در آن نمایشگر برای صرفه‌جویی در مصرف انرژی کم‌نور می‌شود. در این حالت، رابط کاربری برنامه شما هنوز تمام صفحه را اشغال می‌کند، اما سیستم ممکن است ظاهر آن را با تار کردن یا نمایش محتوای رویی مانند زمان تغییر دهد. به این حالت، حالت Ambient نیز گفته می‌شود.

سیستم عامل، انتقال بین این حالت‌ها را کنترل می‌کند.

یک برنامه همیشه روشن، برنامه‌ای است که محتوا را در هر دو حالت تعاملی و محیطی نمایش می‌دهد.

وقتی یک برنامه‌ی همیشه روشن، رابط کاربری خود را نمایش می‌دهد، در حالی که دستگاه در حالت کم‌مصرف Ambient قرار دارد، به آن حالت ambiactive می‌گویند.

انتقال سیستم و رفتار پیش‌فرض

وقتی یک برنامه در پیش‌زمینه است، سیستم انتقال وضعیت روشن/خاموش را بر اساس دو وقفه زمانی که به دلیل عدم فعالیت کاربر ایجاد می‌شود، مدیریت می‌کند.

  • وقفه شماره ۱: حالت تعاملی به حالت محیطی: پس از مدتی عدم فعالیت کاربر، دستگاه وارد حالت محیطی می‌شود.
  • مهلت شماره ۲: بازگشت به صفحه ساعت: پس از یک دوره عدم فعالیت بیشتر، سیستم ممکن است برنامه فعلی را پنهان کرده و صفحه ساعت را نمایش دهد.

بلافاصله پس از اینکه سیستم از اولین گذار به حالت Ambient عبور کرد، رفتار پیش‌فرض به نسخه Wear OS و پیکربندی برنامه شما بستگی دارد:

  • در Wear OS 5 و پایین‌تر ، سیستم یک اسکرین‌شات تار از برنامه‌ی متوقف‌شده‌ی شما نمایش می‌دهد که زمان آن در بالا قرار گرفته است. این حالت با گره‌ی «AOD Lite» در فلوچارت زیر نشان داده شده است.
  • در Wear OS 6 و بالاتر ، اگر برنامه‌ای SDK 36 یا جدیدتر را هدف قرار دهد، همیشه روشن در نظر گرفته می‌شود. صفحه نمایش کم‌نور می‌شود، اما برنامه همچنان در حال اجرا است و قابل مشاهده باقی می‌ماند. (به‌روزرسانی‌ها ممکن است به ندرت، مثلاً یک بار در دقیقه، انجام شوند.) این حالت توسط گره "Global AOD" در فلوچارت زیر نشان داده شده است.

سفارشی‌سازی رفتار برای حالت Ambient

صرف نظر از رفتار پیش‌فرض سیستم، در تمام نسخه‌های Wear OS می‌توانید ظاهر یا رفتار برنامه خود را در حالت Ambient با استفاده از LocalAmbientModeManager برای مشاهده انتقال حالت‌ها در Jetpack Compose در Wear OS سفارشی کنید. این حالت با گره "Ambiactive Mode" در فلوچارت زیر نشان داده شده است.

مشاهده وضعیت محیط

برای واکنش به رویدادهای حالت محیطی در Jetpack Compose در Wear OS:

  1. از LocalAmbientModeManager برای مشاهده تغییرات در وضعیت حالت محیطی سیستم استفاده کنید و composable های خود را بر اساس آن تنظیم کنید. کامپوننت خود را طوری پیکربندی کنید که در حالت AmbientMode.Ambient به حالت مصرف انرژی کمتر تنظیم شود و در حالت AmbientMode.Interactive آن را به یک نمایشگر تعاملی کامل بازگردانید.

    // In a production application, the AmbientModeManager should be instantiated and provided at
    // the highest level of the Compose hierarchy (typically in the host Activity's setContent
    // block) using a CompositionLocalProvider. This ensures proper lifecycle management and
    // broad accessibility.
    
    // For this self-contained demo, AmbientModeManager is created and provided locally:
    val activityAmbientModeManager = rememberAmbientModeManager()
    CompositionLocalProvider(LocalAmbientModeManager provides activityAmbientModeManager) {
        val ambientModeManager = LocalAmbientModeManager.current
        val ambientMode = ambientModeManager?.currentAmbientMode
    
        if (ambientModeManager != null) {
            ambientModeManager.AmbientTickEffect {
                // While device is in ambient mode, update properties every minute or so
                // ...
            }
        }
    
        // ...
            val ambientModeName =
                when (ambientMode) {
                    is AmbientMode.Interactive -> "Interactive"
                    is AmbientMode.Ambient -> "Ambient"
                    else -> "Unknown"
                }
    
            Text(text = "$ambientModeName Mode")
            // ...
    }

برای توسعه‌دهندگانی که از Jetpack Compose استفاده می‌کنند، LocalAmbientModeManager استفاده کنید که پیاده‌سازی این الگو را ساده می‌کند.

فلوچارت رفتار محیطی

فلوچارت زیر نشان می‌دهد که چگونه سیستم رفتار محیط را بر اساس نسخه Wear OS دستگاه، targetSdkVersion برنامه شما و اینکه آیا AmbientLifecycleCallback را پیاده‌سازی می‌کند یا خیر، تعیین می‌کند.

فلوچارتی که منطق تصمیم‌گیری برای حالت محیطی Wear OS را نشان می‌دهد. این فلوچارت نشان می‌دهد که چگونه نسخه سیستم عامل دستگاه و پیکربندی برنامه، یکی از سه نتیجه را تعیین می‌کند: یک پوشش تار، نمایشگر همیشه روشن سراسری (Global AOD) یا حالت Ambiactive Mode تحت مدیریت برنامه.
شکل ۱. فلوچارتی که منطق تصمیم‌گیری برای حالت محیطی Wear OS را نشان می‌دهد.

مدت زمان روشن بودن صفحه نمایش را کنترل کنید

بخش‌های بعدی نحوه مدیریت مدت زمان نمایش برنامه روی صفحه را شرح می‌دهند.

جلوگیری از بازگشت به صفحه ساعت با فعالیت در حال انجام یا به‌روزرسانی زنده

پس از مدتی در حالت محیطی (Timeout #2)، سیستم معمولاً به صفحه ساعت برمی‌گردد. کاربر می‌تواند مدت زمان وقفه را در تنظیمات سیستم پیکربندی کند. برای موارد استفاده خاص، مانند کاربری که یک تمرین را ردیابی می‌کند، ممکن است لازم باشد یک برنامه برای مدت طولانی‌تری قابل مشاهده باشد.

در Wear OS 5 و بالاتر، می‌توانید با پیاده‌سازی یک فعالیت مداوم (Ongoing Activity) از این امر جلوگیری کنید. اگر برنامه شما اطلاعاتی در مورد یک کار مداوم کاربر، مانند یک جلسه تمرین، نمایش می‌دهد، می‌توانید از API فعالیت مداوم (Ongoing Activity API) برای قابل مشاهده نگه داشتن برنامه خود تا پایان کار استفاده کنید. اگر کاربر به صورت دستی به صفحه ساعت برگردد، نشانگر فعالیت مداوم، راهی برای بازگشت به برنامه شما با یک ضربه فراهم می‌کند.

از طرف دیگر، در Wear OS 7 و بالاتر، می‌توانید به جای Ongoing Activity از Live Update استفاده کنید. برای سازگاری با نسخه‌های قبلی، به پشتیبانی از Ongoing Activity در دستگاه‌هایی که Wear OS 6 یا پایین‌تر را اجرا می‌کنند، ادامه دهید.

برای پیاده‌سازی این، هدف لمسی اعلان مداوم باید به فعالیت همیشه روشن شما اشاره کند، همانطور که در قطعه کد زیر نشان داده شده است:

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)

val notification = notificationBuilder.build()

روشن نگه داشتن صفحه نمایش و جلوگیری از فعال شدن حالت محیطی (Ambient)

در موارد نادر، ممکن است لازم باشد که به طور کامل از ورود دستگاه به حالت Ambient جلوگیری کنید. یعنی برای جلوگیری از Timeout #1. برای انجام این کار، می‌توانید از اصلاح‌کننده keepScreenOn استفاده کنید. این به عنوان قفل بیدارباش عمل می‌کند و دستگاه را در حالت Interactive نگه می‌دارد. از این مورد با احتیاط شدید استفاده کنید زیرا به شدت بر عمر باتری تأثیر می‌گذارد.

توصیه‌هایی برای حالت محیطی

برای ارائه بهترین تجربه کاربری و صرفه‌جویی در مصرف انرژی در حالت Ambient ، این دستورالعمل‌های طراحی را دنبال کنید. این توصیه‌ها با جلوگیری از اطلاعات گمراه‌کننده و کاهش آشفتگی بصری، ضمن بهینه‌سازی همزمان مصرف انرژی نمایشگر، یک تجربه کاربری واضح را در اولویت قرار می‌دهند.

  • کاهش شلوغی بصری و مصرف انرژی نمایشگر. یک رابط کاربری ساده و مینیمالیستی به کاربر نشان می‌دهد که برنامه در حالت کم‌مصرف است و با محدود کردن پیکسل‌های روشن، باتری قابل توجهی را ذخیره می‌کند.
    • حداقل ۸۵٪ صفحه نمایش را سیاه نگه دارید.
    • فقط مهم‌ترین اطلاعات را نمایش دهید و جزئیات ثانویه را به صفحه نمایش تعاملی منتقل کنید.
    • برای آیکون‌ها یا دکمه‌های بزرگ، به جای پر کردن‌های توپر، از خطوط بیرونی استفاده کنید.
    • از بلوک‌های بزرگ با رنگ‌های ثابت و نام‌های تجاری یا تصاویر پس‌زمینه غیرکاربردی خودداری کنید.
  • مدیریت داده‌های پویای قدیمی
    • تابع فراخوانی AmbientTickEffect فقط به صورت دوره‌ای - معمولاً یک بار در دقیقه - برای صرفه‌جویی در مصرف انرژی فراخوانی می‌شود. به دلیل این محدودیت، هر داده‌ای که مرتباً تغییر می‌کند - مانند کرونومتر، ضربان قلب یا مسافت تمرین - بین به‌روزرسانی‌ها بی‌استفاده می‌شود. برای جلوگیری از نمایش اطلاعات گمراه‌کننده و نادرست، این مقادیر زنده را با محتوای ثابت جایگزین کنید، مانند -- .
  • طرح‌بندی منسجمی را حفظ کنید
    • عناصر را در حالت‌های تعاملی و محیطی در موقعیت یکسانی نگه دارید تا یک انتقال روان ایجاد شود.
    • همیشه زمان را نشان دهید.
  • از زمینه آگاه باشید
    • اگر کاربر هنگام ورود دستگاه به حالت محیطی در صفحه تنظیمات یا پیکربندی بوده است، به جای نمای تنظیمات، صفحه مرتبط‌تری از برنامه خود را نمایش دهید.
  • رسیدگی به الزامات خاص دستگاه
    • در شیء AmbientMode که از currentAmbientMode برگردانده شده است:
      • اگر isLowBitAmbientSupported true است، در صورت امکان، anti-aliasing را غیرفعال کنید.
      • اگر isBurnInProtectionRequired روی 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

مثال: اپلیکیشن تمرین ورزشی

یک اپلیکیشن ورزشی را در نظر بگیرید که باید در تمام مدت زمان جلسه تمرینی، معیارهایی را به کاربر نمایش دهد. این اپلیکیشن باید در طول تغییر وضعیت Ambient قابل مشاهده باشد و با صفحه ساعت جایگزین نشود.

برای رسیدن به این هدف، توسعه‌دهنده باید موارد زیر را انجام دهد:

  1. از LocalAmbientModeManager برای مدیریت تغییرات رابط کاربری بین حالت‌های Interactive و Ambient ، مانند کم کردن نور صفحه نمایش و حذف داده‌های غیرضروری، استفاده کنید.
  2. یک طرح‌بندی کم‌مصرف جدید برای حالت Ambient ایجاد کنید که از بهترین شیوه‌ها پیروی کند.
  3. برای جلوگیری از بازگشت سیستم به صفحه ساعت، در طول تمرین از رابط برنامه‌نویسی کاربردی فعالیت مداوم (یا به‌روزرسانی‌های زنده در Wear OS 7 و بالاتر) استفاده کنید.

برای پیاده‌سازی کامل، به نمونه تمرین مبتنی بر compose در GitHub مراجعه کنید. این نمونه همچنین استفاده از LocalAmbientModeManager composable را برای ساده‌سازی مدیریت حالت محیطی در Compose نشان می‌دهد.