Membaca data mentah

Contoh berikut menunjukkan cara membaca data mentah sebagai bagian dari alur kerja umum.

Membaca data

Health Connect memungkinkan aplikasi membaca data dari datastore saat aplikasi berada di latar depan dan latar belakang:

  • Pembacaan latar depan: Anda biasanya dapat membaca data dari Health Connect saat aplikasi Anda berada di latar depan. Dalam kasus ini, Anda dapat mempertimbangkan untuk menggunakan layanan latar depan untuk menjalankan operasi ini jika pengguna atau sistem menempatkan aplikasi Anda di latar belakang selama operasi baca.

  • Fungsi baca di latar belakang: Dengan meminta izin tambahan dari pengguna, Anda dapat membaca data setelah pengguna atau sistem menempatkan aplikasi Anda di latar belakang. Lihat contoh pembacaan latar belakang yang lengkap.

Jenis data Langkah di Health Connect mendeteksi jumlah langkah pengguna di sela-sela pembacaan. Jumlah langkah mewakili pengukuran umum di seluruh platform kesehatan, kebugaran, dan kesegaran. Health Connect memungkinkan Anda membaca dan menulis data jumlah langkah.

Untuk membaca data, buat ReadRecordsRequest dan berikan saat Anda memanggil readRecords.

Contoh berikut menunjukkan cara membaca data jumlah langkah untuk pengguna dalam waktu tertentu. Untuk contoh yang lebih panjang dengan SensorManager, lihat panduan data jumlah langkah.

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.readRecords(
            ReadRecordsRequest(
                StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        for (record in response.records) {
            // Process each record
        }
    } catch (e: Exception) {
        // Run error handling here
    }
}

Anda juga dapat membaca data secara agregat menggunakan aggregate.

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Membaca langkah seluler

Dengan Android 14 (level API 34) dan Ekstensi SDK versi 20 atau yang lebih tinggi, Health Connect menyediakan penghitungan langkah di perangkat. Jika aplikasi telah diberi izin READ_STEPS, Health Connect akan mulai merekam langkah dari perangkat berteknologi Android, dan pengguna akan melihat data langkah yang otomatis ditambahkan ke entri Langkah Health Connect.

Untuk memeriksa apakah penghitungan langkah di perangkat tersedia, Anda harus memverifikasi bahwa perangkat menjalankan Android 14 (level API 34) dan memiliki setidaknya ekstensi SDK versi 20. Anda dapat menggunakan kode berikut:

val isStepTrackingAvailable =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
        SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20

Langkah seluler yang direkam oleh Health Connect memiliki DataOrigin yang ditetapkan ke nama paket android. Jika aplikasi Anda hanya membaca jumlah langkah yang digabungkan menggunakan aggregate dan tidak memfilter menurut DataOrigin, langkah di perangkat akan otomatis disertakan dalam total.

Jika aplikasi Anda perlu membaca langkah-langkah di perangkat, atau jika aplikasi menampilkan data langkah yang dikelompokkan menurut aplikasi atau perangkat sumber, Anda dapat membuat kueri untuk data saat DataOrigin adalah android. Jika aplikasi Anda menampilkan atribusi untuk data langkah, Anda harus mengatribusikan data dari paket android ke perangkat saat ini. Anda dapat melakukannya dengan menggunakan label seperti "Ponsel Anda", mengambil nama perangkat dengan Settings.Global.getString(resolver, Settings.Global.DEVICE_NAME), atau memeriksa kolom Device dalam metadata rekaman.

Contoh berikut menunjukkan cara membaca data jumlah langkah seluler gabungan dengan memfilter asal data android:

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                dataOriginFilter = setOf(DataOrigin("android"))
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Penghitungan Langkah di Perangkat

Mempelajari lebih dalam fitur penghitungan langkah di perangkat:

  • Penggunaan Sensor: Health Connect menggunakan sensor TYPE_STEP_COUNTER dari SensorManager. Sensor ini dioptimalkan untuk konsumsi daya rendah, sehingga ideal untuk pelacakan langkah di latar belakang secara berkelanjutan.
  • Perincian Data: Untuk menghemat masa pakai baterai, data langkah biasanya dikelompokkan dan ditulis ke database Health Connect tidak lebih sering dari sekali per menit.
  • Atribusi: Seperti yang disebutkan sebelumnya, semua langkah yang direkam oleh fitur di perangkat ini diatribusikan ke nama paket android dalam DataOrigin.
  • Aktivasi: Mekanisme penghitungan langkah di perangkat hanya aktif jika setidaknya satu aplikasi di perangkat telah diberi izin READ_STEPS dalam Health Connect.

Contoh pembacaan latar belakang

Untuk membaca data di latar belakang, deklarasikan izin berikut dalam file manifes Anda:

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

Contoh berikut menunjukkan cara membaca data jumlah langkah di latar belakang untuk pengguna dalam waktu tertentu menggunakan WorkManager:

class ScheduleWorker(private val appContext: Context, workerParams: WorkerParameters):
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        // Read data and process it.
        ...

        // Return success indicating successful data retrieval
        return Result.success()
    }
}

if (healthConnectClient
    .features
    .getFeatureStatus(
    HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
    ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {

    // Check if necessary permission is granted
    val grantedPermissions = healthConnectClient.permissionController.getGrantedPermissions()

    if (PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND !in grantedPermissions) {
        // Perform read in foreground
        ...
    } else {
        // Schedule the periodic work request in background
        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
} else {
  // Background reading is not available, perform read in foreground
  ...
}

Parameter ReadRecordsRequest memiliki nilai pageSize default 1.000. Jika jumlah data dalam satu readResponse melebihi pageSize permintaan, Anda harus melakukan iterasi di semua halaman respons untuk mengambil semua data menggunakan pageToken. Namun, berhati-hatilah untuk menghindari masalah pembatasan kecepatan.

Contoh pembacaan pageToken

Sebaiknya gunakan pageToken untuk membaca rekaman guna mengambil semua data yang tersedia dari jangka waktu yang diminta.

Contoh berikut menunjukkan cara membaca semua data hingga semua token halaman telah habis:

val type = HeartRateRecord::class
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(7))

try {
    var pageToken: String? = null
    do {
        val readResponse =
            healthConnectClient.readRecords(
                ReadRecordsRequest(
                    recordType = type,
                    timeRangeFilter = TimeRangeFilter.between(
                        startTime,
                        endTime
                    ),
                    pageToken = pageToken
                )
            )
        val records = readResponse.records
        // Do something with records
        pageToken = readResponse.pageToken
    } while (pageToken != null)
} catch (quotaError: IllegalStateException) {
    // Backoff
}

Untuk mengetahui informasi tentang praktik terbaik saat membaca set data besar, lihat Rencanakan untuk menghindari pembatasan kecepatan.

Membaca data yang ditulis sebelumnya

Jika aplikasi telah menulis catatan ke Health Connect sebelumnya, aplikasi tersebut dapat membaca data historis. Hal ini berlaku untuk skenario saat aplikasi perlu disinkronkan ulang dengan Health Connect setelah pengguna menginstal ulang aplikasi.

Beberapa batasan baca berlaku:

  • Untuk Android 14 dan yang lebih baru

    • Tidak ada batasan historis pada aplikasi yang membaca datanya sendiri.
    • Batas 30 hari untuk aplikasi yang membaca data lain.
  • Untuk Android 13 dan yang lebih lama

    • Batas 30 hari untuk aplikasi membaca data apa pun.

Pembatasan dapat dihapus dengan meminta izin Baca.

Untuk membaca data historis, Anda perlu menunjukkan nama paket sebagai objek DataOrigin dalam parameter dataOriginFilter dari ReadRecordsRequest.

Contoh berikut menunjukkan cara menunjukkan nama paket saat membaca data detak jantung:

try {
    val response =  healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = HeartRateRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
            dataOriginFilter = setOf(DataOrigin("com.my.package.name"))
        )
    )
    for (record in response.records) {
        // Process each record
    }
} catch (e: Exception) {
    // Run error handling here
}

Membaca data yang lebih lama dari 30 hari

Secara default, semua aplikasi dapat membaca data dari Health Connect hingga 30 hari sebelum izin apa pun pertama kali diberikan.

Jika Anda perlu memperluas izin baca di luar batasan default, minta PERMISSION_READ_HEALTH_DATA_HISTORY. Jika tidak, tanpa izin ini, upaya untuk membaca data yang lebih lama dari 30 hari akan menghasilkan error.

Histori izin untuk aplikasi yang dihapus

Jika pengguna menghapus aplikasi Anda, semua izin, termasuk izin histori, akan dicabut. Jika pengguna menginstal ulang aplikasi Anda dan memberikan izin lagi, batasan default yang sama akan berlaku, dan aplikasi Anda dapat membaca data dari Health Connect hingga 30 hari sebelum tanggal baru tersebut.

Misalnya, pengguna menghapus aplikasi Anda pada 10 Mei 2023, lalu menginstal ulang aplikasi pada 15 Mei 2023, dan memberikan izin baca. Tanggal awal data yang dapat dibaca aplikasi Anda sekarang secara default adalah 15 April 2023.

Menangani pengecualian

Health Connect menerapkan pengecualian standar untuk operasi CRUD saat terjadi masalah. Aplikasi Anda harus menangkap dan menangani setiap pengecualian ini sebagaimana mestinya.

Setiap metode di HealthConnectClient mencantumkan pengecualian yang dapat diterapkan. Secara umum, aplikasi Anda harus menangani pengecualian berikut:

Tabel 1: Pengecualian Health Connect dan praktik terbaik yang direkomendasikan
Pengecualian Deskripsi Praktik terbaik yang direkomendasikan
IllegalStateException Salah satu skenario berikut terjadi:

  • Layanan Health Connect tidak tersedia.
  • Permintaan ini bukan konstruksi yang valid. Misalnya, permintaan gabungan dalam bucket berkala tempat objek Instant digunakan untuk timeRangeFilter.

Tangani kemungkinan masalah dengan input terlebih dahulu sebelum melakukan permintaan. Sebaiknya, tetapkan nilai ke variabel atau gunakan sebagai parameter dalam fungsi kustom, bukan menggunakannya langsung dalam permintaan, sehingga Anda dapat menerapkan strategi penanganan error.
IOException Terjadi masalah saat membaca dan menulis data dari disk. Untuk menghindari masalah ini, berikut beberapa saran:

  • Cadangkan input pengguna.
  • Dapat menangani masalah apa pun yang terjadi selama operasi tulis massal. Misalnya, pastikan proses melalui masalah, lalu lakukan operasi lainnya.
  • Terapkan percobaan ulang dan strategi backoff untuk menangani masalah permintaan.

RemoteException Error terjadi dalam, atau saat berkomunikasi dengan, layanan dasar yang terhubung dengan SDK.

Misalnya, aplikasi Anda mencoba menghapus data dengan uid yang ditentukan. Namun, pengecualian diterapkan setelah aplikasi mengetahui saat memeriksa layanan dasar bahwa data tersebut tidak ada.
Untuk menghindari masalah ini, berikut beberapa saran:

  • Lakukan sinkronisasi reguler antara datastore aplikasi dan Health Connect aplikasi Anda.
  • Terapkan percobaan ulang dan strategi backoff untuk menangani masalah permintaan.

SecurityException Ada masalah yang muncul saat permintaan memerlukan izin yang tidak diberikan. Untuk menghindari hal ini, pastikan Anda telah mendeklarasikan penggunaan jenis data Health Connect untuk aplikasi yang dipublikasikan. Selain itu, Anda harus mendeklarasikan izin Health Connect dalam file manifes dan dalam aktivitas Anda.