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 di 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.

val response = healthConnectClient.readRecords(
    ReadRecordsRequest(
        HeartRateRecord::class,
        timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
    )
)
response.records.forEach { record ->
    /* Process records */
}

Anda juga dapat membaca data secara agregat menggunakan aggregate.

suspend fun readStepsAggregate(startTime: Instant, endTime: Instant): Long {
    val response = healthConnectClient.aggregate(
        AggregateRequest(
            metrics = setOf(StepsRecord.COUNT_TOTAL),
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )
    return response[StepsRecord.COUNT_TOTAL] ?: 0L
}

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, verifikasi bahwa perangkat menjalankan Android 14 (level API 34) dan memiliki setidaknya ekstensi SDK versi 20:

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

Jika aplikasi Anda membaca jumlah langkah yang digabungkan menggunakan aggregate dan tidak memfilter menurut DataOrigin, langkah di perangkat akan otomatis disertakan dalam total, dan tidak ada perubahan yang diperlukan untuk update Juni 2026.

Perubahan atribusi untuk langkah-langkah di perangkat

Mulai update Juni 2026, langkah yang dilacak secara native oleh Health Connect diatribusikan ke Nama Paket Sintetis (SPN), seperti com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e.

Sebelumnya, langkah-langkah bawaan dikaitkan dengan nama paket android. Data langkah historis yang direkam sebelum Juni 2026 mempertahankan nama paket android.

SPN khusus untuk perangkat dan dicakup berdasarkan per aplikasi untuk melindungi privasi pengguna:

  • Stabil: SPN untuk perangkat saat ini stabil untuk aplikasi Anda.
  • Cakupan Aplikasi: Aplikasi yang berbeda di perangkat yang sama akan melihat SPN yang berbeda untuk data langkah di perangkat.

Kueri untuk langkah-langkah di perangkat

Karena SPN dicakup dan khusus perangkat, Anda tidak boleh meng-hardcode nilai SPN. Sebagai gantinya, gunakan getCurrentDeviceDataSource() API untuk mengambil SPN untuk perangkat saat ini.

Meskipun penghitungan langkah di perangkat memerlukan ekstensi SDK versi 20 atau yang lebih tinggi, API getCurrentDeviceDataSource() tersedia di Android 14 (level API 34) dengan ekstensi SDK versi 11 atau yang lebih tinggi.

getCurrentDeviceDataSource() API belum tersedia di library Jetpack Health Connect. Contoh berikut menggunakan Android framework API sebagai gantinya:

import android.content.Context
import android.health.connect.HealthConnectManager

val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
val deviceDataSource = healthConnectManager?.getCurrentDeviceDataSource()
val currentDeviceSpn = deviceDataSource?.deviceDataOrigin?.packageName

Jika aplikasi Anda perlu membaca langkah-langkah di perangkat, atau jika aplikasi menampilkan data langkah yang dikelompokkan menurut aplikasi atau perangkat sumber, Anda harus membuat kueri untuk data yang DataOrigin-nya adalah android atau cocok dengan SPN perangkat. Jika aplikasi Anda menampilkan atribusi untuk data langkah, gunakan metadata.device untuk mengidentifikasi perangkat sumber untuk setiap catatan. Untuk langkah-langkah di perangkat yang diidentifikasi oleh SPN dalam data gabungan, Anda dapat menggunakan metadata perangkat seperti model atau manufacturer dari DeviceDataSource untuk atribusi, atau menggunakan label umum seperti "Ponsel Anda" untuk langkah-langkah di perangkat.

Contoh berikut menunjukkan cara membaca data jumlah langkah di perangkat yang digabungkan dengan memfilter android dan SPN perangkat saat ini:

import android.content.Context
import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.ext.SdkExtensions
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant

suspend fun readDeviceStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    context: Context,
    startTime: Instant,
    endTime: Instant
) {
    // 1. Check if SDK Extension 11+ is available for getCurrentDeviceDataSource()
    val isDataSourceApiAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.U &&
            SdkExtensions.getExtensionVersion(Build.VERSION_CODES.U) >= 11

    try {
        val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)

        // 2. Safely fetch the package name only if API is available and data exists
        val currentDeviceSpn = if (isDataSourceApiAvailable) {
            healthConnectManager?.getCurrentDeviceDataSource()?.deviceDataOrigin?.packageName
        } else {
            null
        }

        val dataOriginFilters = mutableSetOf(DataOrigin("android"))

        // 3. Explicit null-safety check using .let
        currentDeviceSpn?.let {
            dataOriginFilters.add(DataOrigin(it))
        }

        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                dataOriginFilter = dataOriginFilters
            )
        )

        val stepCount = response[StepsRecord.COUNT_TOTAL]

    } catch (e: Exception) {
        // Now this catch block only handles actual runtime exceptions, 
        // rather than Errors from missing methods.
    }
}

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: Langkah-langkah yang direkam oleh fitur ini sebelum Juni 2026 diatribusikan ke nama paket android di DataOrigin. Setelah tanggal ini, mereka diatribusikan ke SPN khusus perangkat. Lihat Perubahan atribusi untuk langkah-langkah di perangkat.
  • Aktivasi: Mekanisme penghitungan langkah di perangkat hanya aktif jika setidaknya satu aplikasi di perangkat telah diberi izin READ_STEPS dalam Health Connect.

Contoh bacaan 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(appContext: Context, workerParams: WorkerParameters) :
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        val healthConnectClient = HealthConnectClient.getOrCreate(applicationContext)
        // Perform background read logic here
        return Result.success()
    }
}
@OptIn(ExperimentalFeatureAvailabilityApi::class)
fun enqueueBackgroundReadWorker(context: Context, healthConnectClient: HealthConnectClient) {
    if (healthConnectClient
            .features
            .getFeatureStatus(
                HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
            ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE
    ) {

        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
}

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 Merencanakan 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 paling 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.