แอปที่เปิดตลอดเวลาและโหมดแอมเบียนท์ของระบบ

คำแนะนำนี้จะอธิบายวิธีทำให้แอปทำงานอยู่เสมอ วิธีตอบสนองต่อการเปลี่ยนสถานะพลังงาน และวิธีจัดการลักษณะการทํางานของแอปเพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีขณะที่ประหยัดแบตเตอรี่

การแสดงแอปให้เห็นอยู่ตลอดเวลาจะส่งผลต่ออายุการใช้งานแบตเตอรี่อย่างมาก ดังนั้นโปรดพิจารณาถึงผลกระทบด้านพลังงานเมื่อเพิ่มฟีเจอร์นี้

หัวข้อสำคัญ

เมื่อแอป Wear OS แสดงในโหมดเต็มหน้าจอ แอปจะอยู่ในสถานะพลังงานอย่างใดอย่างหนึ่งต่อไปนี้

  • อินเทอร์แอกทีฟ: สถานะพลังงานสูงที่หน้าจอมีความสว่างสูงสุด ซึ่งช่วยให้ผู้ใช้โต้ตอบได้อย่างเต็มที่
  • โหมดแอมเบียนท์: สถานะพลังงานต่ำที่จอแสดงผลจะหรี่แสงเพื่อประหยัดพลังงาน ในสถานะนี้ UI ของแอปจะยังคงแสดงเต็มหน้าจอ แต่ระบบอาจเปลี่ยนลักษณะที่ปรากฏโดยการเบลอหรือวางซ้อนเนื้อหา เช่น เวลา หรือที่เรียกว่าโหมดแอมเบียนท์

ระบบปฏิบัติการจะควบคุมการเปลี่ยนระหว่างสถานะเหล่านี้

แอปที่เปิดอยู่เสมอคือแอปพลิเคชันที่แสดงเนื้อหาทั้งในสถานะอินเทอร์แอกทีฟและแอมเบียนท์

เมื่อแอปที่ทำงานอยู่เสมอแสดง UI ของตัวเองต่อไปขณะที่อุปกรณ์อยู่ในสถานะแอมเบียนท์พลังงานต่ำ ระบบจะระบุว่าแอปอยู่ในโหมดแอมเบียนท์แอ็กทีฟ

การเปลี่ยนระบบและลักษณะการทำงานเริ่มต้น

เมื่อแอปทำงานอยู่เบื้องหน้า ระบบจะจัดการการเปลี่ยนสถานะพลังงานโดยอิงตามการหมดเวลา 2 รายการที่เรียกให้แสดงโดยไม่มีการใช้งานของผู้ใช้

  • ระยะหมดเวลา #1: สถานะอินเทอร์แอกทีฟเป็นสถานะแอมเบียนท์: หลังจากไม่มีการใช้งานของผู้ใช้เป็นระยะเวลาหนึ่ง อุปกรณ์จะเข้าสู่สถานะแอมเบียนท์
  • ระยะหมดเวลา #2: กลับไปที่หน้าปัด: หลังจากไม่มีการใช้งานเป็นระยะเวลาหนึ่ง ระบบอาจซ่อนแอปปัจจุบันและแสดงหน้าปัด

ทันทีที่ระบบผ่านการเปลี่ยนสถานะแรกเป็นสถานะแอมเบียนท์ ลักษณะการทำงานเริ่มต้นจะขึ้นอยู่กับเวอร์ชัน Wear OS และการกําหนดค่าของแอป ดังนี้

  • ใน Wear OS 5 และต่ำกว่า ระบบจะแสดงภาพหน้าจอเบลอของแอปพลิเคชันที่หยุดชั่วคราว โดยมีเวลาวางซ้อนอยู่ด้านบน
  • ใน Wear OS 6 ขึ้นไป หากแอปกำหนดเป้าหมายเป็น SDK 36 ขึ้นไป ระบบจะถือว่าแอปเป็นแบบเปิดตลอดเวลา จอแสดงผลจะหรี่ลง แต่แอปพลิเคชันจะยังคงทำงานและแสดงอยู่ (การอัปเดตอาจเกิดขึ้นเพียง 1 ครั้งต่อนาที)

ปรับแต่งลักษณะการทำงานสำหรับสถานะแอมเบียนท์

ไม่ว่าระบบจะทำงานอย่างไรโดยค่าเริ่มต้น คุณก็ปรับแต่งลักษณะที่ปรากฏหรือลักษณะการทํางานของแอปขณะอยู่ในสถานะแอมเบียนท์ได้ใน Wear OS ทุกเวอร์ชัน โดยใช้ AmbientLifecycleObserver เพื่อฟังการเรียกกลับเมื่อสถานะเปลี่ยนแปลง

ใช้ AmbientLifecycleObserver

หากต้องการตอบสนองต่อเหตุการณ์ในโหมดแอมเบียนท์ ให้ใช้คลาส AmbientLifecycleObserver ดังนี้

  1. ใช้อินเทอร์เฟซ AmbientLifecycleObserver.AmbientLifecycleCallback ใช้เมธอด onEnterAmbient() เพื่อปรับ UI สำหรับสถานะพลังงานต่ำ และ onExitAmbient() เพื่อคืนค่า UI ให้เป็นจอแสดงผลแบบอินเทอร์แอกทีฟเต็มรูปแบบ

    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 Composable ซึ่งช่วยให้ใช้งานรูปแบบนี้ได้ง่ายๆ

TimeText ที่รับรู้สภาพแวดล้อม

TimeText วิดเจ็ตใน Wear OS 6 เป็นแบบรับรู้สภาพแวดล้อมโดยอัตโนมัติ ซึ่งเป็นข้อยกเว้นที่ไม่จำเป็นต้องใช้เครื่องมือตรวจสอบที่กําหนดเอง โดยจะอัปเดตโดยอัตโนมัติ 1 ครั้งต่อนาทีเมื่ออุปกรณ์อยู่ในสถานะแอมเบียนท์โดยไม่ต้องใช้โค้ดเพิ่มเติม

ควบคุมระยะเวลาที่หน้าจอเปิดอยู่

ส่วนต่อไปนี้อธิบายวิธีจัดการระยะเวลาที่แอปแสดงบนหน้าจอ

ป้องกันไม่ให้กลับไปที่หน้าปัดด้วยกิจกรรมต่อเนื่อง

หลังจากผ่านไประยะหนึ่งในสถานะแอมเบียนท์ (การหมดเวลา #2) ระบบมักจะกลับไปที่หน้าปัด ผู้ใช้สามารถกำหนดค่าระยะเวลาหมดเวลาได้ในการตั้งค่าระบบ สำหรับ Use Case บางกรณี เช่น ผู้ใช้ติดตามการออกกำลังกาย แอปอาจต้องแสดงต่อไปอีกนาน

ใน Wear OS 5 ขึ้นไป คุณสามารถป้องกันปัญหานี้ได้โดยใช้กิจกรรมต่อเนื่อง หากแอปแสดงข้อมูลเกี่ยวกับงานของผู้ใช้ที่ดำเนินอยู่ เช่น เซสชันการออกกําลังกาย คุณสามารถใช้ Ongoing Activity API เพื่อแสดงแอปต่อไปจนกว่างานจะสิ้นสุด หากผู้ใช้กลับไปที่หน้าปัดด้วยตนเอง สัญญาณบอกสถานะกิจกรรมต่อเนื่องจะช่วยให้ผู้ใช้กลับไปที่แอปได้ด้วยการแตะเพียงครั้งเดียว

หากต้องการใช้ฟีเจอร์นี้ Intent การแตะของการแจ้งเตือนที่ทำงานอยู่ต้องชี้ไปยังกิจกรรมที่ทำงานอยู่เสมอ ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

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 หน้าต่าง FLAG_KEEP_SCREEN_ON ซึ่งจะทำหน้าที่เป็นล็อกการปลุก ทำให้อุปกรณ์อยู่ในสถานะโต้ตอบ ใช้ฟีเจอร์นี้อย่างระมัดระวังเนื่องจากส่งผลต่ออายุการใช้งานแบตเตอรี่อย่างมาก

คําแนะนําสําหรับโหมดแอมเบียนท์

โปรดปฏิบัติตามหลักเกณฑ์การออกแบบเหล่านี้เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีที่สุดและประหยัดพลังงานในโหมดแอมเบียนท์

  • ใช้จอแสดงผลแบบมินิมอลที่ใช้พลังงานต่ำ
    • หน้าจอต้องเป็นสีดําอย่างน้อย 85%
    • ใช้เส้นขอบสำหรับไอคอนหรือปุ่มขนาดใหญ่แทนการเติมสี
    • แสดงเฉพาะข้อมูลที่สำคัญที่สุด โดยย้ายรายละเอียดรองไปยังจอแสดงผลแบบอินเทอร์แอกทีฟ
    • หลีกเลี่ยงการใช้พื้นที่สีเดียวกันขนาดใหญ่และการใช้แบรนด์หรือภาพพื้นหลังที่ไม่เป็นประโยชน์
  • ตรวจสอบว่าเนื้อหาได้รับการอัปเดตอย่างเหมาะสม
    • สำหรับข้อมูลที่เปลี่ยนแปลงบ่อย เช่น นาฬิกาจับเวลา ระยะทางของการออกกำลังกาย หรือเวลา ให้แสดงเนื้อหาตัวยึดตําแหน่ง เช่น -- เพื่อไม่ให้ผู้ชมรู้สึกว่าเนื้อหาเป็นข้อมูลล่าสุด
    • นำตัวบ่งชี้ความคืบหน้าที่อัปเดตอย่างต่อเนื่องออก เช่น สำหรับเสียงนับถอยหลังและเซสชันสื่อ
    • ควรใช้การเรียกกลับ onUpdateAmbient() สำหรับการอัปเดตที่สำคัญเท่านั้น โดยปกติแล้วจะใช้ 1 ครั้งต่อนาที
  • คงเลย์เอาต์ให้สอดคล้องกัน
    • วางองค์ประกอบในตำแหน่งเดียวกันในโหมดอินเทอร์แอกทีฟและแอมเบียนท์เพื่อสร้างการเปลี่ยนภาพที่ราบรื่น
    • แสดงเวลาเสมอ
  • คำนึงถึงบริบท
    • หากผู้ใช้อยู่ในหน้าจอการตั้งค่าหรือการกำหนดค่าเมื่ออุปกรณ์เข้าสู่โหมดแอมเบียนท์ ให้พิจารณาแสดงหน้าจอที่เกี่ยวข้องมากขึ้นจากแอปแทนมุมมองการตั้งค่า
  • จัดการข้อกำหนดเฉพาะอุปกรณ์
    • ในออบเจ็กต์ AmbientDetails ที่ส่งไปยัง onEnterAmbient() ให้ทำดังนี้
      • หาก deviceHasLowBitAmbient เป็น true ให้ปิดใช้การลดรอยหยักหากเป็นไปได้
      • หาก burnInProtectionRequired เป็น true ให้เลื่อนองค์ประกอบ UI เล็กน้อยเป็นระยะๆ และหลีกเลี่ยงพื้นที่สีขาวล้วนเพื่อป้องกันจอเบิร์น

การแก้ไขข้อบกพร่องและการทดสอบ

คำสั่ง 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 เพื่อจัดการการเปลี่ยนแปลง UI ระหว่างสถานะอินเทอร์แอกทีฟและแอมเบียนท์ เช่น การลดแสงหน้าจอและการนำข้อมูลที่ไม่จำเป็นออก
  2. สร้างเลย์เอาต์ใหม่ที่ใช้พลังงานต่ำสำหรับสถานะแอมเบียนท์ที่เป็นไปตามแนวทางปฏิบัติแนะนำ
  3. ใช้ Ongoing Activity API ตลอดระยะเวลาการออกกำลังกายเพื่อป้องกันไม่ให้ระบบกลับไปที่หน้าปัด

ดูการใช้งานแบบสมบูรณ์ได้ที่ตัวอย่างแบบฝึกหัดที่ใช้ Compose ใน GitHub ตัวอย่างนี้ยังแสดงการใช้คอมโพสิชัน AmbientAware จากไลบรารี Horologist เพื่อลดความซับซ้อนในการจัดการโหมดแอมเบียนท์ใน Compose