Mengembangkan Pengalaman Tidur dengan Health Connect

Jika ingin membuat pengalaman pelacakan tidur di aplikasi Anda, Anda dapat menggunakan Health Connect untuk melakukan hal-hal seperti:

  • Menulis sesi tidur
  • Menulis data fase tidur
  • Menulis data tidur seperti detak jantung, saturasi oksigen, dan laju pernapasan
  • Membaca data tidur dari aplikasi lain

Panduan ini menjelaskan cara membuat fitur tidur ini, yang mencakup jenis data, eksekusi di latar belakang, izin, alur kerja yang direkomendasikan, dan praktik terbaik.

Ringkasan: Membangun Pelacak Tidur yang Komprehensif

Anda dapat membangun pengalaman pelacakan tidur yang komprehensif menggunakan Health Connect dengan mengikuti langkah-langkah inti berikut:

  • Menerapkan izin dengan benar berdasarkan Izin Kesehatan.
  • Merekam sesi menggunakan SleepSessionRecord.
  • Menulis jenis data seperti tahap tidur, detak jantung, dan saturasi oksigen secara konsisten selama sesi.
  • Mengelola eksekusi latar belakang dengan benar untuk memverifikasi pengambilan data berkelanjutan semalaman.
  • Membaca data sesi untuk ringkasan dan analisis pasca-tidur.

Alur kerja ini memungkinkan interoperabilitas dengan aplikasi Health Connect lainnya dan memverifikasi akses data yang dikontrol pengguna.

Sebelum memulai

Sebelum menerapkan fitur tidur:

Konsep utama

Health Connect menampilkan data tidur menggunakan beberapa komponen inti. SleepSessionRecord berfungsi sebagai catatan pusat untuk tidur, yang berisi detail seperti waktu mulai atau berakhir dan tahap tidur. Selama sesi, berbagai jenis data seperti HeartRateRecord atau OxygenSaturationRecord dapat direkam.

Sesi tidur

Data tidur direpresentasikan oleh SleepSessionRecord. Setiap data menyimpan:

  • startTime
  • endTime
  • stages: Daftar SleepSessionRecord.Stage termasuk tidur dalam, tidur ringan, REM, dan terjaga.
  • Metadata sesi opsional (judul, catatan)

Aplikasi dapat menulis beberapa jenis data yang terkait dengan sesi.

Jenis data

Jenis data umum yang dicatat selama sesi tidur meliputi:

Setiap jenis data disimpan sebagai data individual.

Pertimbangan pengembangan

Aplikasi pelacak tidur sering kali perlu berjalan dalam jangka waktu yang lama, sering kali di latar belakang saat layar nonaktif. Saat membangun fitur tidur, penting untuk mempertimbangkan cara mengelola eksekusi di latar belakang dan meminta izin yang diperlukan untuk data tidur.

Eksekusi latar belakang

Aplikasi pelacak tidur biasanya berjalan semalaman dengan layar nonaktif. Saat dalam status ini, Anda harus menggunakan:

  • Layanan latar depan untuk pengumpulan data
  • WorkManager untuk penulisan atau sinkronisasi yang ditangguhkan
  • Strategi batch untuk penulisan data terperinci secara rutin seperti detak jantung

Pertahankan kontinuitas dengan menjaga konsistensi ID sesi di semua penulisan.

Izin

Aplikasi Anda harus meminta izin Health Connect yang relevan sebelum membaca atau menulis data tidur. Untuk mengetahui daftar lengkap jenis data, lihat Jenis data Health Connect. Izin umum untuk tidur mencakup sesi tidur dan metrik seperti detak jantung atau saturasi oksigen.

Akses ke mode tidur dilindungi oleh izin berikut:

  • android.permission.health.READ_SLEEP
  • android.permission.health.WRITE_SLEEP

Untuk menambahkan kemampuan tidur ke aplikasi Anda, mulailah dengan meminta izin untuk jenis data SleepSession.

Berikut adalah izin yang harus Anda deklarasikan agar dapat menulis tidur:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>

Untuk membaca data tidur, Anda perlu meminta izin berikut:

<application>
  <uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>

Berikut menunjukkan contoh cara meminta izin untuk sesi tidur yang mencakup data detak jantung, saturasi oksigen, dan laju pernapasan:

Setelah membuat instance klien, aplikasi Anda perlu meminta izin dari pengguna. Pengguna harus diizinkan untuk memberikan atau menolak izin kapan saja.

Untuk melakukannya, buat kumpulan izin untuk jenis data yang diperlukan. Pastikan izin dalam kumpulan dideklarasikan dalam manifes Android Anda terlebih dahulu.

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(SleepSessionRecord::class),
  HealthPermission.getWritePermission(SleepSessionRecord::class),
  HealthPermission.getReadPermission(HeartRateRecord::class),
  HealthPermission.getWritePermission(HeartRateRecord::class),
  HealthPermission.getReadPermission(OxygenSaturationRecord::class),
  HealthPermission.getWritePermission(OxygenSaturationRecord::class),
  HealthPermission.getReadPermission(RespiratoryRateRecord::class),
  HealthPermission.getWritePermission(RespiratoryRateRecord::class)
)

Gunakan getGrantedPermissions untuk mengetahui apakah aplikasi Anda sudah mendapatkan izin yang diperlukan. Jika belum, gunakan createRequestPermissionResultContract untuk meminta izin tersebut. Tindakan ini akan menampilkan layar izin Health Connect.

// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()

val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions successfully granted
  } else {
    // Lack of required permissions
  }
}

suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
  val granted = healthConnectClient.permissionController.getGrantedPermissions()
  if (granted.containsAll(PERMISSIONS)) {
    // Permissions already granted; proceed with inserting or reading data
  } else {
    requestPermissions.launch(PERMISSIONS)
  }
}

Karena pengguna dapat memberikan atau mencabut izin kapan saja, aplikasi Anda perlu memeriksa izin setiap kali sebelum menggunakannya dan menangani skenario saat izin hilang.

Menerapkan sesi tidur

Bagian ini menjelaskan alur kerja yang direkomendasikan untuk merekam data tidur.

Untuk menyelaraskan jenis data seperti HeartRateRecord atau OxygenSaturationRecord dengan sesi tidur, catat dengan stempel waktu yang berada di antara startTime dan endTime sesi. Health Connect tidak menggunakan ID sesi untuk menautkan sesi tidur dengan data terperinci. Sebaliknya, asosiasi bersifat implisit melalui interval waktu yang tumpang-tindih. Saat membaca data tidur, Anda dapat menggunakan rentang waktu sesi untuk membuat kueri jenis data terkait, seperti yang ditunjukkan dalam Membaca data tidur.

Menulis sesi

Meskipun data terperinci seperti detak jantung dapat direkam selama sesi tidur, SleepSessionRecord itu sendiri hanya boleh ditulis ke Health Connect setelah sesi selesai, misalnya saat pengguna bangun. Catatan harus menyertakan startTime sesi, endTime, dan daftar objek SleepSessionRecord.Stage yang direkam selama sesi, karena SleepSessionRecord mengharuskan endTime berada setelah startTime.

Untuk menulis sesi tidur:

  1. Buat ID catatan klien yang unik.
  2. Saat pengguna bangun, atau pelacakan tidur dihentikan, kumpulkan semua tahap tidur dan buat SleepSessionRecord.
  3. Sisipkan rekaman menggunakan insertRecords.

Contoh:

val clientRecordId = UUID.randomUUID().toString()
val sessionStartTime = LocalDateTime.of(2023, 10, 30, 22, 0).toInstant(ZoneOffset.UTC)
val sessionEndTime = LocalDateTime.of(2023, 10, 31, 7, 0).toInstant(ZoneOffset.UTC)

val stages = mutableListOf<SleepSessionRecord.Stage>()
// Add recorded stages, for example:
stages.add(SleepSessionRecord.Stage(
    startTime = sessionStartTime.plusSeconds(3600),
    endTime = sessionStartTime.plusSeconds(7200),
    stage = SleepSessionRecord.STAGE_TYPE_LIGHT)
)
stages.add(SleepSessionRecord.Stage(
    startTime = sessionStartTime.plusSeconds(7200),
    endTime = sessionStartTime.plusSeconds(10800),
    stage = SleepSessionRecord.STAGE_TYPE_DEEP)
)
// ... other stages

val session = SleepSessionRecord(
    startTime = sessionStartTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = sessionEndTime,
    endZoneOffset = ZoneOffset.UTC,
    stages = stages,
    metadata = Metadata(clientRecordId = clientRecordId)
)

healthConnectClient.insertRecords(listOf(session))

Membaca data tidur

Aplikasi dapat membaca sesi tidur dan data terkaitnya untuk meringkas aktivitas, memberikan insight kesehatan, atau menyinkronkan data dengan server eksternal. Misalnya, Anda dapat membaca SleepSessionRecord, lalu mengkueri HeartRateRecord yang terjadi selama interval waktu yang sama.

Sesi baca dengan data terkait

Anda dapat membaca sesi tidur menggunakan ReadRecordsRequest dengan SleepSessionRecord sebagai jenis rekaman, yang difilter menurut rentang waktu. Untuk membaca data terkait untuk sesi tertentu, buat permintaan kedua untuk jenis data yang dipilih, seperti HeartRateRecord—memfilter menurut startTime dan endTime sesi tidur.

Contoh berikut menunjukkan cara membaca sesi tidur dengan data detak jantung terkait untuk rentang waktu tertentu:

suspend fun readSleepSessionsWithAssociatedData(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    val response = healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = SleepSessionRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )

    for (sleepRecord in response.records) {
        // Process each session
        val stages = sleepRecord.stages
        val notes = sleepRecord.notes

        // To read specific granular data (like heart rate) that occurred during
        // this session, use the session's startTime and endTime to filter
        // the request for that data type.
        val hrResponse = healthConnectClient.readRecords(
            ReadRecordsRequest(
                recordType = HeartRateRecord::class,
                timeRangeFilter = TimeRangeFilter.between(
                    sleepRecord.startTime,
                    sleepRecord.endTime
                )
            )
        )
        for (heartRateRecord in hrResponse.records) {
            for (sample in heartRateRecord.samples) {
                val bpm = sample.beatsPerMinute
            }
        }
    }
}

Praktik terbaik

Ikuti panduan berikut untuk meningkatkan keandalan data dan pengalaman pengguna:

  • Frekuensi Penulisan
    • Pelacakan Aktif(Latar Depan): Untuk pelacakan tidur aktif, tulis data saat tersedia atau dengan interval maksimum 15 menit.
    • Sinkronisasi Latar Belakang: Gunakan WorkManager untuk operasi tulis yang ditangguhkan. Tetapkan interval 15 menit untuk menyeimbangkan data real-time dan efisiensi baterai.
    • Batching: Jangan tulis setiap peristiwa sensor satu per satu. Bagi permintaan Anda menjadi beberapa bagian. Health Connect menangani hingga 1.000 data per permintaan penulisan.
  • Menjaga ID sesi tetap stabil dan unik: Gunakan ID yang konsisten untuk sesi Anda. Jika sesi diedit atau diperbarui, penggunaan ID yang sama akan mencegah sesi tersebut diperlakukan sebagai sesi tidur baru yang terpisah.
  • Gunakan batching untuk jenis data: Untuk mengurangi overhead Input/Output dan menghemat daya baterai, kelompokkan titik data Anda ke dalam satu panggilan insertRecords, bukan menulis setiap titik secara terpisah.
  • Menghindari penulisan data duplikat: Gunakan ID Klien Saat membuat catatan, tetapkan metadata.clientRecordId. Health Connect menggunakan ini untuk mengidentifikasi catatan unik. Jika Anda mencoba menulis data dengan clientRecordId yang sudah ada, Health Connect akan mengabaikan duplikat atau memperbarui data yang ada, bukan membuat data baru. Menetapkan metadata.clientRecordId adalah cara paling efektif untuk mencegah duplikat selama percobaan ulang sinkronisasi atau penginstalan ulang aplikasi.

    val record = RespiratoryRateRecord(
        rate = 16.0,
        time = time,
        zoneOffset = ZoneOffset.UTC,
        metadata = Metadata(
            // Use a unique ID from your own database
            clientRecordId = "respiratory_rate_20231030_1"
        )
    )
    
  • Periksa data yang ada: Sebelum menyinkronkan, kueri rentang waktu untuk melihat apakah data dari aplikasi Anda sudah ada.

  • Pastikan stempel waktu tidak tumpang-tindih: Verifikasi bahwa sesi baru tidak dimulai sebelum sesi sebelumnya berakhir. Sesi yang tumpang-tindih dapat menyebabkan konflik di dasbor kebugaran dan penghitungan ringkasan.

  • Berikan alasan yang jelas untuk izin: Gunakan alur Permission.createIntent untuk menjelaskan alasan aplikasi Anda memerlukan akses ke data kesehatan, seperti "Untuk menganalisis pola tidur Anda".

  • Uji sesi yang berjalan lama: Pantau konsumsi baterai selama sesi yang berlangsung beberapa jam untuk memverifikasi bahwa interval batching dan penggunaan sensor Anda tidak menguras baterai perangkat.

  • Menyelaraskan stempel waktu dengan kecepatan sensor: Cocokkan stempel waktu rekaman Anda dengan frekuensi aktual sensor untuk mempertahankan fidelitas tinggi data.

Pengujian

Untuk memverifikasi kebenaran data dan pengalaman pengguna yang berkualitas tinggi, ikuti strategi pengujian berikut dan lihat dokumentasi Uji kasus penggunaan teratas resmi.

Alat verifikasi

  • Toolbox Health Connect: Gunakan aplikasi pendamping ini untuk memeriksa catatan secara manual, menghapus data pengujian, dan menyimulasikan perubahan pada database. Cara ini adalah cara terbaik untuk memverifikasi bahwa catatan Anda disimpan dengan benar.
  • Pengujian unit dengan FakeHealthConnectClient: Gunakan library pengujian untuk memverifikasi cara aplikasi Anda menangani kasus ekstrem, seperti pencabutan izin atau pengecualian API tanpa memerlukan perangkat fisik.

Checklist kualitas

Arsitektur umum

Penerapan pelacakan tidur biasanya mencakup:

Komponen Mengelola
Pengontrol sesi Status sesi
Timer
Logika pengelompokan
Pengontrol jenis data
Pengumpulan data
Lapisan repositori (membungkus operasi Health Connect:) Menyisipkan sesi
Menyisipkan jenis data
Menyisipkan tahap tidur
Membaca ringkasan sesi
Lapisan UI (Tampilan): Durasi
Jenis data live
Visualisasi tahap tidur

Pemecahan masalah

Gejala Kemungkinan penyebab Resolusi
Jenis data tidak ada (misalnya, Detak Jantung) Izin tulis tidak ada atau filter waktu salah. Pastikan Anda telah meminta dan pengguna telah memberikan izin jenis data tertentu. Pastikan ReadRecordsRequest Anda menggunakan TimeRangeFilter yang cocok dengan sesi. Lihat Izin.
Sesi gagal menulis Stempel waktu yang tumpang-tindih. Health Connect dapat menolak data yang tumpang-tindih dengan data yang ada dari aplikasi yang sama. Pastikan startTime sesi baru berada setelah endTime sesi sebelumnya.
Tidak ada data sensor yang direkam selama tidur Layanan latar depan dihentikan atau tidak aktif. Untuk mengumpulkan data sensor semalaman saat layar nonaktif, Anda dapat menggunakan Layanan Latar Depan dengan foregroundServiceType="health".
Record duplikat muncul clientRecordId tidak ada. Tetapkan clientRecordId unik di Metadata setiap data. Hal ini memungkinkan Health Connect melakukan penghapusan duplikat jika data yang sama ditulis dua kali selama percobaan ulang sinkronisasi. Lihat Praktik terbaik.

Langkah-langkah umum proses penelusuran kesalahan

Periksa status izin. Selalu panggil getPermissionStatus() sebelum mencoba operasi baca atau tulis. Pengguna dapat mencabut izin di setelan sistem kapan saja.
Verifikasi mode eksekusi. Jika aplikasi Anda tidak mengumpulkan data di latar belakang, pastikan Anda telah mendeklarasikan izin yang benar dalam file AndroidManifest.xml dan pengguna belum menempatkan aplikasi ke mode "Dibatasi Baterai".