ตรวจสอบข้อมูลในเบื้องหลัง

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

ดูตัวอย่างการใช้ข้อมูลแบบพาสซีฟได้ในตัวอย่างข้อมูลแบบพาสซีฟ และ เป้าหมายแบบพาสซีฟ ใน GitHub

เพิ่มทรัพยากร Dependency

หากต้องการเพิ่มการอ้างอิงในบริการด้านสุขภาพ คุณต้องเพิ่มที่เก็บ Maven ของ Google ลงในโปรเจ็กต์ ดูข้อมูลเพิ่มเติมได้ที่ ที่เก็บ Maven ของ Google

เพิ่มทรัพยากร Dependency ต่อไปนี้ในไฟล์ build.gradle ระดับโมดูล

ดึงดูด

dependencies {
    implementation "androidx.health:health-services-client:1.1.0-alpha05"
}

Kotlin

dependencies {
    implementation("androidx.health:health-services-client:1.1.0-alpha05")
}

ตรวจสอบความสามารถ

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

val healthClient = HealthServices.getClient(this /*context*/)
val passiveMonitoringClient = healthClient.passiveMonitoringClient
lifecycleScope.launchWhenCreated {
    val capabilities = passiveMonitoringClient.capabilities.await()
    // Supported types for passive data collection
    supportsHeartRate =
        DataType.HEART_RATE_BPM in capabilities.supportedDataTypesPassiveMonitoring
    // Supported types for PassiveGoals
    supportsStepsGoal =
        DataType.STEPS_DAILY in capabilities.supportedDataTypesPassiveGoals
}

ลงทะเบียนเพื่อรับข้อมูลแบบพาสซีฟ

คุณรับข้อมูลแบบพาสซีฟได้ผ่านบริการ, การเรียกกลับ หรือทั้ง 2 อย่าง บริการช่วยให้แอปรับข้อมูลในเบื้องหลังได้เมื่อไม่มีส่วนใดของ แอปแสดงในเบื้องหน้า เมื่อคุณได้รับข้อมูลในเบื้องหลัง ระบบจะ ส่งข้อมูลเป็นชุด การเรียกกลับจะได้รับข้อมูลในอัตราที่เร็วกว่าเล็กน้อย แต่ เฉพาะในขณะที่แอปทำงานอยู่และมีการแจ้งเตือนการเรียกกลับสำเร็จเท่านั้น

ไม่ว่าคุณจะใช้วิธีใดก็ตาม ให้สร้างPassiveListenerConfig ก่อนเพื่อกำหนดประเภทข้อมูลที่จะรับ ดังตัวอย่างต่อไปนี้

val passiveListenerConfig = PassiveListenerConfig.builder()
    .setDataTypes(setOf(DataType.HEART_RATE_BPM))
    .build()

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

val passiveListenerCallback: PassiveListenerCallback = object : PassiveListenerCallback {
    override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
        // TODO: Do something with dataPoints
    }
}

passiveMonitoringClient.setPassiveListenerCallback(
    passiveListenerConfig,
    passiveListenerCallback
)

// To remove the listener
passiveMonitoringClient.clearPassiveListenerCallbackAsync()

การใช้บริการจะคล้ายกัน แต่ให้สร้างคลาสที่ได้มาจาก PassiveListenerService แทนที่จะสร้างจาก PassiveListenerCallback ดังที่แสดงใน ตัวอย่างต่อไปนี้

class PassiveDataService : PassiveListenerService() {
    override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
        // TODO: Do something with dataPoints
    }
}

passiveMonitoringClient.setPassiveListenerServiceAsync(
    PassiveDataService::class.java,
    passiveListenerConfig
)

จากนั้นประกาศบริการในไฟล์ AndroidManifest.xml ต้องมีสิทธิ์ Health Services ซึ่งจะยืนยันว่ามีเพียง Health Services เท่านั้นที่เชื่อมโยงกับบริการได้

<service android:name=".PassiveDataService"
    android:permission="com.google.android.wearable.healthservices.permission.PASSIVE_DATA_BINDING"
    android:exported="true" />

ล่ามเวลา

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

รับการประทับเวลาสำหรับแต่ละ DataPoint โดยคำนวณการประทับเวลาการเริ่มต้นก่อน ดังที่แสดงในตัวอย่างต่อไปนี้

val bootInstant =
    Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())

จากนั้นจะส่งค่านี้ไปยัง getStartInstant() หรือ getEndInstant()

กู้คืนการลงทะเบียนหลังการบูต

การลงทะเบียนข้อมูลแบบพาสซีฟจะไม่คงอยู่เมื่อรีบูต หากต้องการรับข้อมูลหลังจากรีสตาร์ทอุปกรณ์ ให้สร้างการลงทะเบียนใหม่โดยใช้ BroadcastReceiver ที่รอฟังการออกอากาศของระบบ ACTION_BOOT_COMPLETED

ในเครื่องรับ อย่าพยายามกู้คืนการลงทะเบียนโดยตรง แต่ให้มอบหมายฟังก์ชันนี้ให้กับผู้ปฏิบัติงาน WorkManager แทน เมื่ออุปกรณ์เริ่มต้นทำงาน บริการด้านสุขภาพอาจใช้เวลา 10 วินาทีขึ้นไปในการ รับทราบคำขอลงทะเบียนข้อมูลแบบพาสซีฟ และอาจเกิน เวลาดำเนินการที่อนุญาตของ BroadcastReceiver ในทางตรงกันข้าม WorkManager Worker มีขีดจำกัดการดำเนินการ 10 นาที

ข้อมูลโค้ดต่อไปนี้แสดงลักษณะของ BroadcastReceiver

class StartupReceiver : BroadcastReceiver() {

   override fun onReceive(context: Context, intent: Intent) {
       if (intent.action != Intent.ACTION_BOOT_COMPLETED) return


       // TODO: Check permissions first
       WorkManager.getInstance(context).enqueue(
           OneTimeWorkRequestBuilder<RegisterForPassiveDataWorker>().build()
       )
   }
}

class RegisterForPassiveDataWorker(
   private val appContext: Context,
   workerParams: WorkerParameters
) : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       runBlocking {
           HealthServices.getClient(appContext)
                .passiveMonitoringClient
                .setPassiveListenerCallback(...)
       }
       return Result.success()
   }
}

หากต้องการให้ระบบเรียกใช้โค้ดนี้เมื่ออุปกรณ์เริ่มระบบ ให้ทำการเปลี่ยนแปลง 2 อย่างในไฟล์ AndroidManifest.xml

ก่อนอื่น ให้เพิ่มสิทธิ์ต่อไปนี้เป็นสิทธิ์ย่อยของ <manifest>

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

จากนั้นเพิ่มตัวกรอง Intent ของตัวรับต่อไปนี้เป็นองค์ประกอบย่อยของ <application>

<receiver
    android:name=".StartupReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

สถานะกิจกรรม

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

  1. ขอสิทธิ์ ACTIVITY_RECOGNITION
  2. เรียกใช้ setShouldUserActivityInfoBeRequested(true) ในเครื่องมือสร้าง PassiveListenerConfig

ลบล้างเมธอด onUserActivityInfoReceived() ในการเรียกกลับหรือบริการ และใช้ UserActivityInfo ที่ส่งคืน ดังที่แสดงในตัวอย่างต่อไปนี้

override fun onUserActivityInfoReceived(info: UserActivityInfo) {
    val stateChangeTime: Instant = info.stateChangeTime // may be in the past!
    val userActivityState: UserActivityState = info.userActivityState
    if (userActivityState == UserActivityState.USER_ACTIVITY_ASLEEP) {
        // ...
    }
}

เป้าหมายแบบพาสซีฟ

คุณสามารถกำหนดค่าไคลเอ็นต์แบบพาสซีฟให้แจ้งเตือนแอปเมื่อบรรลุเป้าหมายแบบพาสซีฟ เช่น ผู้ใช้เดินครบ 10,000 ก้าวใน 1 วัน

โดยให้สร้างเป้าหมายตามตัวอย่างต่อไปนี้

val dailyStepsGoal by lazy {
    val condition = DataTypeCondition(
        dataType = DataType.STEPS_DAILY,
        threshold = 10_000, // Trigger every 10000 steps
        comparisonType = ComparisonType.GREATER_THAN_OR_EQUAL
    )
    PassiveGoal(condition)
}

เพิ่มเป้าหมายนี้ลงใน PassiveListenerConfig ตามที่แสดงในตัวอย่างต่อไปนี้

val passiveListenerConfig = PassiveListenerConfig.builder()
    .setDailyGoals(setOf(dailyStepsGoal))
    .build()

ลบล้างเมธอด onGoalCompleted() ในการเรียกกลับหรือบริการ และใช้ PassiveGoal ที่ส่งคืน ดังที่แสดงในตัวอย่างต่อไปนี้

override fun onGoalCompleted(goal: PassiveGoal) {
    when (goal.dataTypeCondition.dataType) {
        DataType.STEPS_DAILY -> {
            // ...
        }
    }
}