Phát triển trải nghiệm tập luyện bằng Health Connect

Nếu muốn tạo trải nghiệm tập thể dục trong ứng dụng, bạn có thể dùng Health Connect để thực hiện những việc như:

  • Ghi phiên hoạt động tập thể dục
  • Ghi tuyến đường tập thể dục
  • Ghi các chỉ số tập luyện như tần số tim, tốc độ và quãng đường
  • Đọc dữ liệu tập thể dục từ các ứng dụng khác

Hướng dẫn này mô tả cách tạo các tính năng tập thể dục này, bao gồm các loại dữ liệu, việc thực thi ở chế độ nền, quyền, quy trình đề xuất và các phương pháp hay nhất.

Tổng quan: Tạo trình theo dõi bài tập thể dục toàn diện

Bạn có thể tạo trải nghiệm theo dõi bài tập thể dục toàn diện bằng Health Connect bằng cách làm theo các bước cốt lõi sau:

  • Triển khai chính xác các quyền dựa trên Quyền truy cập vào dữ liệu sức khoẻ.
  • Ghi lại các phiên bằng ExerciseSessionRecord.
  • Ghi dữ liệu tập thể dục một cách nhất quán trong phiên.
  • Quản lý đúng cách việc thực thi ở chế độ nền để xác minh quá trình thu thập dữ liệu liên tục.
  • Đọc dữ liệu phiên để phân tích và tóm tắt sau khi tập thể dục.

Quy trình này cho phép khả năng tương tác với các ứng dụng Health Connect khác và xác minh quyền truy cập dữ liệu do người dùng kiểm soát.

Trước khi bắt đầu

Trước khi triển khai các tính năng tập thể dục:

Khái niệm chính

Health Connect biểu thị dữ liệu tập thể dục bằng một số thành phần cốt lõi. ExerciseSessionRecord hoạt động như bản ghi trung tâm cho một bài tập thể dục, chứa các thông tin chi tiết như thời gian bắt đầu hoặc kết thúc và loại bài tập. Trong một phiên, nhiều loại dữ liệu như HeartRateRecord hoặc SpeedRecord có thể được ghi lại. Đối với các hoạt động ngoài trời, ExerciseRoute lưu trữ dữ liệu GPS được liên kết với phiên tương ứng.

Phiên hoạt động tập thể dục

ExerciseSessionRecord là bản ghi trung tâm cho dữ liệu tập thể dục, biểu thị một phiên tập thể dục. Mỗi bản ghi lưu trữ:

  • startTime
  • endTime
  • exerciseType
  • Siêu dữ liệu phiên không bắt buộc (tiêu đề, ghi chú)

ExerciseSessionRecord cũng có thể chứa các tuyến đường tập thể dục, số vòng và phân đoạn như một phần của dữ liệu. Ngoài ra, các loại dữ liệu khác như HeartRateRecord hoặc SpeedRecord có thể được ghi lại trong một phiên và liên kết với phiên đó.

Các loại dữ liệu được liên kết

Dữ liệu liên kết với các phiên tập thể dục được biểu thị bằng các loại bản ghi riêng lẻ. Các loại phổ biến bao gồm:

  • HeartRateRecord: Biểu thị một chuỗi các phép đo tần số tim.
  • SpeedRecord: Biểu thị một chuỗi các phép đo tốc độ.
  • DistanceRecord: Biểu thị quãng đường đã đi giữa các lần đọc.
  • TotalCaloriesBurnedRecord: Biểu thị tổng lượng calo đã đốt cháy giữa các lần đọc.
  • ElevationGainedRecord: Biểu thị độ cao đạt được giữa các lần đọc.
  • StepsCadenceRecord: Biểu thị nhịp độ bước chân giữa các lần đọc.
  • PowerRecord: Biểu thị công suất đầu ra giữa các lần đọc, thường thấy trong các hoạt động như đạp xe.

Để xem danh sách đầy đủ các loại dữ liệu, hãy xem Các loại dữ liệu của Health Connect.

Tuyến đường tập thể dục

Bạn có thể liên kết một tuyến đường với các bài tập thể dục ngoài trời bằng cách sử dụng ExerciseRoute. Các tuyến đường bao gồm các đối tượng ExerciseRoute.Location tuần tự, mỗi đối tượng chứa:

  • Vĩ độ và kinh độ
  • Độ cao không bắt buộc
  • Hướng không bắt buộc
  • Thông tin về độ chính xác
  • Dấu thời gian

Liên kết các tuyến đường trong phiên

ExerciseRoute chứa dữ liệu vị trí tuần tự cho một phiên tập thể dục. Dữ liệu này không được coi là một bản ghi độc lập trong Health Connect. Thay vào đó, bạn cung cấp dữ liệu ExerciseRoute khi chèn hoặc cập nhật ExerciseSessionRecord.

Điều cần cân nhắc khi phát triển ứng dụng

Các ứng dụng theo dõi bài tập thể dục thường cần chạy trong thời gian dài, thường là ở chế độ nền khi màn hình tắt. Khi tạo các tính năng tập thể dục, bạn cần cân nhắc cách quản lý việc thực thi ở chế độ nền và yêu cầu các quyền cần thiết đối với dữ liệu tập thể dục.

Chạy ở chế độ nền

Các ứng dụng tập thể dục thường chạy khi màn hình tắt. Khi ở trạng thái này, bạn nên sử dụng:

  • Dịch vụ trên nền trước để lấy mẫu vị trí và cảm biến
  • WorkManager để ghi hoặc đồng bộ hoá bị trì hoãn
  • Các chiến lược theo lô để ghi bản ghi thường xuyên

Duy trì tính liên tục bằng cách giữ cho mã phiên nhất quán trên tất cả các lần ghi.

Quyền

Ứng dụng của bạn phải yêu cầu các quyền liên quan đến Health Connect trước khi đọc hoặc ghi dữ liệu tập thể dục. Các quyền phổ biến đối với bài tập bao gồm phiên tập thể dục, tuyến đường tập thể dục và các chỉ số như tần số tim hoặc tốc độ. Điều này bao gồm những nội dung sau:

  • Phiên tập thể dục: Quyền đọc và ghi cho ExerciseSessionRecord.
  • Tuyến đường tập thể dục: Quyền đọc và ghi cho ExerciseRoute.
  • Nhịp tim: Quyền đọc và ghi cho HeartRateRecord.
  • Tốc độ: Quyền đọc và ghi cho SpeedRecord.
  • Quãng đường: Quyền đọc và ghi cho DistanceRecord.
  • Lượng calo: Quyền đọc và ghi cho TotalCaloriesBurnedRecord.
  • Độ cao đạt được: Quyền đọc và ghi cho ElevationGainedRecord.
  • Nhịp độ bước chân: Quyền đọc và ghi cho StepsCadenceRecord.
  • Công suất: Quyền đọc và ghi cho PowerRecord.
  • Số bước: Quyền đọc và ghi cho StepsRecord.

Sau đây là ví dụ về cách yêu cầu nhiều quyền cho một phiên tập thể dục bao gồm dữ liệu về tuyến đường, tần số tim, quãng đường, lượng calo, tốc độ và số bước:

Sau khi tạo một thực thể ứng dụng, ứng dụng của bạn cần yêu cầu người dùng cấp quyền. Người dùng phải được phép cấp hoặc từ chối cấp quyền bất cứ lúc nào. Để thực hiện việc này, hãy tạo một tập hợp quyền cho các kiểu dữ liệu bắt buộc. Trước tiên, bạn cần khai báo các quyền trong tập hợp này ở tệp kê khai Android.

val permissions =
    setOf(
        HealthPermission.getReadPermission(ExerciseSessionRecord::class),
        HealthPermission.getWritePermission(ExerciseSessionRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class),
        HealthPermission.getReadPermission(SpeedRecord::class),
        HealthPermission.getWritePermission(SpeedRecord::class),
        HealthPermission.getReadPermission(DistanceRecord::class),
        HealthPermission.getWritePermission(DistanceRecord::class),
        HealthPermission.getReadPermission(TotalCaloriesBurnedRecord::class),
        HealthPermission.getWritePermission(TotalCaloriesBurnedRecord::class),
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class)
    )
Hãy sử dụng getGrantedPermissions để xem ứng dụng của bạn đã được cấp các quyền cần thiết chưa. Nếu chưa, hãy sử dụng createRequestPermissionResultContract để yêu cầu các quyền đó. Thao tác này sẽ hiện màn hình các quyền của Health Connect.
val permissions = setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class)
    )

val requestPermissionsLauncher = rememberLauncherForActivityResult(
    contract = PermissionController.createRequestPermissionResultContract()
) { grantedPermissions ->
    if (grantedPermissions.containsAll(permissions)) {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") }
    } else {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") }
    }
}
Vì người dùng có thể cấp hoặc thu hồi quyền bất cứ lúc nào, nên ứng dụng của bạn cần kiểm tra quyền mỗi khi sử dụng và xử lý các trường hợp mất quyền.

Để yêu cầu quyền, hãy gọi hàm checkPermissionsAndRun:

if (!granted.containsAll(permissions)) {
    // Check if required permissions are not granted, and return
    return emptySet()
}
// Permissions already granted; proceed with inserting or reading data

Nếu bạn chỉ cần yêu cầu quyền cho một loại dữ liệu, chẳng hạn như nhịp tim, hãy chỉ đưa loại dữ liệu đó vào tập hợp quyền:

Quyền truy cập vào tần số tim được bảo vệ bằng các quyền sau:

  • android.permission.health.READ_HEART_RATE
  • android.permission.health.WRITE_HEART_RATE

Để thêm chức năng nhịp tim vào ứng dụng của bạn, hãy bắt đầu bằng cách yêu cầu quyền cho loại dữ liệu HeartRateRecord.

Dưới đây là quyền bạn cần khai báo để có thể ghi tần số tim:

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

Để đọc nhịp tim, bạn cần yêu cầu các quyền sau:

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

Triển khai một phiên tập thể dục

Phần này mô tả quy trình đề xuất để ghi dữ liệu tập thể dục.

Bắt đầu phiên

Cách tạo một bài tập thể dục mới:

  1. Tạo một mã phiên duy nhất: Xác minh rằng mã này ổn định. Nếu quá trình ứng dụng của bạn bị huỷ và khởi động lại, bạn phải có thể tiếp tục sử dụng cùng một mã để ngăn các phiên bị phân mảnh.
  2. Đặt metadata.clientRecordId để ngăn các bản sao trong quá trình thử lại đồng bộ hoá.
  3. Ghi ExerciseSessionRecord: Thêm thời gian bắt đầu.
  4. Bắt đầu thu thập dữ liệu về Loại dữ liệu và GPS: Chỉ bắt đầu các dữ liệu này sau khi bản ghi phiên được khởi chạy thành công.

Ví dụ:

val sessionClientId = UUID.randomUUID().toString()
val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)

val session =   ExerciseSessionRecord(
    startTime = startTime,
    startZoneOffset = zoneOffset,
    endTime = startTime.plusSeconds(3600),
    endZoneOffset = zoneOffset,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
    metadata = Metadata(clientRecordId = sessionClientId),
)

healthConnectClient.insertRecords(listOf(session))

Ghi tuyến đường tập thể dục

Để tìm hiểu thêm về hướng dẫn đọc, hãy xem bài viết Đọc dữ liệu thô.

Khi ghi tuyến đường tập thể dục, bạn nên xử lý dữ liệu theo lô. Điều này có nghĩa là thay vì lưu từng điểm GPS khi xảy ra, bạn sẽ thu thập một nhóm điểm và lưu tất cả cùng một lúc trong một lệnh gọi.

Điều này rất quan trọng vì mỗi khi ứng dụng của bạn đọc hoặc ghi vào Health Connect, ứng dụng sẽ sử dụng một chút pin và sức mạnh xử lý.

Đoạn mã sau đây cho biết cách ghi theo lô:

// 1. Create a list to hold your route locations
val routeLocations = mutableListOf<ExerciseRoute.Location>()

// 2. Add points to your list as the exercise happens
routeLocations.add(
    ExerciseRoute.Location(
        time = Instant.now(),
        latitude = 37.7749,
        longitude = -122.4194
    )
)

// ... keep adding points over a period of time ...

// 3. Save the whole list at once (Batching)
val session = ExerciseSessionRecord(
    startTime = startTime,
    endTime = endTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
    // We pass the whole list here
    exerciseRoute = ExerciseRoute(routeLocations)
)

healthConnectClient.insertRecords(listOf(session))

Kết thúc phiên

Sau khi dừng thu thập dữ liệu:

  • Cập nhật bản ghi: Ứng dụng của bạn cập nhật ExerciseSessionRecord bằng endTime.
  • Hoàn thiện dữ liệu: Bạn có thể tính toán các giá trị tóm tắt (như tổng quãng đường hoặc tốc độ trung bình) và ghi các giá trị đó dưới dạng bản ghi bổ sung.
val finishedSession = session.copy(endTime = Instant.now())
healthConnectClient.updateRecords(listOf(finishedSession))

Đọc dữ liệu tập thể dục

Các ứng dụng có thể đọc các phiên tập thể dục và dữ liệu liên kết của chúng để tóm tắt hoạt động, cung cấp thông tin chi tiết về sức khoẻ hoặc đồng bộ hoá dữ liệu với một máy chủ bên ngoài. Ví dụ: bạn có thể đọc ExerciseSessionRecord rồi truy vấn HeartRateRecord hoặc DistanceRecord xảy ra trong cùng khoảng thời gian đó.

Nếu bạn cần đồng bộ hoá dữ liệu tập thể dục với máy chủ phụ trợ hoặc cập nhật kho dữ liệu của ứng dụng bằng Health Connect, hãy sử dụng ChangeLogs. Điều này cho phép bạn truy xuất danh sách các bản ghi được chèn, cập nhật hoặc xoá kể từ một thời điểm cụ thể, hiệu quả hơn so với việc theo dõi các thay đổi theo cách thủ công hoặc đọc tất cả dữ liệu nhiều lần. Để biết thêm thông tin, hãy xem bài viết Đồng bộ hoá dữ liệu với Health Connect.

Đọc phiên

Để đọc các phiên tập thể dục, hãy sử dụng ReadRecordsRequest với ExerciseSessionRecord làm loại. Bạn thường lọc dữ liệu này theo một phạm vi thời gian cụ thể.

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

    for (exerciseRecord in response.records) {
        // Process each session
        val exerciseType = exerciseRecord.exerciseType
        val notes = exerciseRecord.notes
    }
}

Đọc tuyến đường

Mặc dù dữ liệu ExerciseRoute được ghi như một phần của phiên tập thể dục, nhưng bạn phải đọc riêng dữ liệu này. Sử dụng phương thức getExerciseRoute() với mã phiên để đọc dữ liệu tuyến đường:

suspend fun readExerciseRoute(
    healthConnectClient: HealthConnectClient,
    exerciseSessionRecord: ExerciseSessionRecord
) {
    // Check if the session has a route
    val route = healthConnectClient.getExerciseRoute(
        exerciseSessionRecordId = exerciseSessionRecord.metadata.id
    )

    when (route) {
        is ExerciseRouteResponse.Success -> {
            val locations = route.exerciseRoute.locations
            for (location in locations) {
                // Use latitude, longitude, and altitude
            }
        }
        is ExerciseRouteResponse.NoData -> {
            // Handle case where no route exists
        }
        is ExerciseRouteResponse.ConsentRequired -> {
            // Handle case where permissions are missing
        }
    }
}

Đọc các loại dữ liệu

Để đọc dữ liệu chi tiết cụ thể (như nhịp tim) xảy ra trong một phiên, hãy sử dụng startTimeendTime của phiên đó để lọc yêu cầu cho loại dữ liệu đó.

suspend fun readHeartRateData(
    healthConnectClient: HealthConnectClient,
    exerciseSession: ExerciseSessionRecord
) {
    val response = healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = HeartRateRecord::class,
            timeRangeFilter = TimeRangeFilter.between(
                exerciseSession.startTime,
                exerciseSession.endTime
            )
        )
    )

    for (heartRateRecord in response.records) {
        for (sample in heartRateRecord.samples) {
            val bpm = sample.beatsPerMinute
        }
    }
}

Các phương pháp hay nhất

Hãy làm theo các nguyên tắc sau để cải thiện độ tin cậy của dữ liệu và trải nghiệm người dùng:

  • Ghi thường xuyên trong quá trình theo dõi đang hoạt động: Đối với quá trình theo dõi đang hoạt động, hãy ghi dữ liệu khi có hoặc ở khoảng thời gian tối đa là 15 phút.
  • Sử dụng WorkManager cho quá trình đồng bộ hoá ở chế độ nền: Sử dụng WorkManager cho các lần ghi bị trì hoãn. Đặt mục tiêu khoảng thời gian là 15 phút để cân bằng giữa dữ liệu theo thời gian thực và hiệu suất pin.
  • Yêu cầu ghi theo lô: Đừng ghi từng sự kiện cảm biến riêng lẻ. Phân đoạn các yêu cầu của bạn. Health Connect xử lý tối đa 1.000 bản ghi cho mỗi yêu cầu ghi.
  • Giữ cho mã phiên ổn định và duy nhất: Sử dụng các giá trị nhận dạng nhất quán cho các phiên của bạn. Nếu một phiên được chỉnh sửa hoặc cập nhật, việc sử dụng cùng một mã sẽ ngăn phiên đó bị coi là một phiên mới, riêng biệt.
  • Sử dụng tính năng xử lý theo lô cho cả loại dữ liệu và điểm tuyến đường: Để giảm chi phí đầu vào/đầu ra và tiết kiệm pin, hãy nhóm các điểm dữ liệu của bạn thành một lệnh gọi insertRecords thay vì ghi từng điểm riêng lẻ.
  • Tránh ghi dữ liệu trùng lặp: Sử dụng mã ứng dụng: Khi tạo bản ghi, hãy đặt metadata.clientRecordId. Health Connect sử dụng mã này để xác định các bản ghi duy nhất. Nếu bạn cố gắng ghi một bản ghi có clientRecordId đã tồn tại, Health Connect sẽ bỏ qua bản sao hoặc cập nhật bản ghi hiện có thay vì tạo một bản ghi mới. Việc đặt metadata.clientRecordId là cách hiệu quả nhất để ngăn các bản sao trong quá trình thử lại đồng bộ hoá hoặc cài đặt lại ứng dụng.
    val record = StepsRecord(
        count = 100,
        startTime = startTime,
        endTime = endTime,
        startZoneOffset = ZoneOffset.UTC,
        endZoneOffset = ZoneOffset.UTC,
        metadata = Metadata(
            // Use a unique ID from your own database
            clientRecordId = "daily_steps_2023_10_27_user_123"
        )
    )
  • Kiểm tra dữ liệu hiện có: Trước khi đồng bộ hoá, hãy truy vấn phạm vi thời gian để xem các bản ghi từ ứng dụng của bạn đã tồn tại hay chưa.
  • Xác thực độ chính xác của GPS: Lọc các mẫu GPS có độ chính xác thấp (Ví dụ: các điểm có bán kính độ chính xác theo phương ngang cao) trước khi ghi vào ExerciseRoute để xác minh rằng bản đồ trông rõ ràng và chuyên nghiệp.
  • Đảm bảo dấu thời gian không trùng lặp: Xác minh rằng một phiên mới không bắt đầu trước khi phiên trước kết thúc. Các phiên trùng lặp có thể gây ra xung đột trong bảng điều khiển thể dục và tính toán tóm tắt.
  • Nêu rõ lý do cho quyền: Sử dụng luồng Permission.createIntent để giải thích lý do ứng dụng của bạn cần quyền truy cập vào dữ liệu sức khoẻ, ví dụ: "Để theo dõi xu hướng huyết áp và cung cấp thông tin chi tiết".
  • Hỗ trợ tạm dừng và tiếp tục: Xác minh rằng ứng dụng của bạn xử lý các lần tạm dừng một cách chính xác. Khi người dùng tạm dừng, hãy dừng thu thập các điểm tuyến đường và loại dữ liệu để tốc độ và thời lượng trung bình vẫn chính xác.
  • Kiểm thử các phiên chạy dài: Theo dõi mức tiêu thụ pin trong các phiên kéo dài vài giờ để xác minh rằng khoảng thời gian xử lý theo lô và mức sử dụng cảm biến không làm tiêu hao pin thiết bị.
  • Căn chỉnh dấu thời gian với tốc độ cảm biến: Khớp dấu thời gian bản ghi với tần suất thực tế của cảm biến để duy trì độ trung thực cao của dữ liệu.

Thử nghiệm

Để xác minh tính chính xác của dữ liệu và trải nghiệm người dùng chất lượng cao, hãy làm theo các chiến lược kiểm thử này và tham khảo tài liệu chính thức về Kiểm thử các trường hợp sử dụng hàng đầu documentation.

Công cụ xác minh

  • Hộp công cụ Health Connect: Sử dụng ứng dụng bổ trợ này để kiểm tra bản ghi theo cách thủ công, xoá dữ liệu kiểm thử và mô phỏng các thay đổi đối với cơ sở dữ liệu. Đây là cách tốt nhất để xác minh rằng các bản ghi của bạn đang được lưu trữ chính xác.
  • Kiểm thử đơn vị bằng FakeHealthConnectClient: Sử dụng thư viện kiểm thử để xác minh cách ứng dụng của bạn xử lý các trường hợp đặc biệt, chẳng hạn như thu hồi quyền hoặc ngoại lệ API mà không cần thiết bị thực.

Danh sách kiểm tra chất lượng

Kiến trúc điển hình

Việc triển khai bài tập thể dục thường bao gồm:

Thành phần Quản lý
Bộ điều khiển phiên Trạng thái phiên
Bộ hẹn giờ
Logic xử lý theo lô
Bộ điều khiển loại dữ liệu
Lấy mẫu vị trí
Lớp kho lưu trữ (gói các thao tác Health Connect:) Chèn phiên
Chèn các loại dữ liệu
Chèn các điểm tuyến đường
Đọc thông tin tóm tắt phiên
Lớp giao diện người dùng (Hiển thị): Thời lượng
Các loại dữ liệu trực tiếp
Xem trước bản đồ
Tính toán phân tách
Dấu vết GPS trực tiếp

Khắc phục sự cố

Dấu hiệu Nguyên nhân có thể gây ra lỗi Độ phân giải
Tuyến đường không liên kết với phiên Mã phiên hoặc phạm vi thời gian không khớp. Xác minh rằng ExerciseRoute được ghi với phạm vi thời gian nằm hoàn toàn trong thời lượng ExerciseSessionRecord. Xác minh rằng bạn đang sử dụng các mã nhất quán nếu tham chiếu đến phiên sau. Xem bài viết Ghi tuyến đường tập thể dục.
Thiếu các loại dữ liệu (ví dụ: Nhịp tim) Thiếu quyền ghi hoặc bộ lọc thời gian không chính xác. Kiểm tra để đảm bảo bạn đã yêu cầu và người dùng đã cấp quyền cho loại dữ liệu cụ thể. Xác minh rằng ReadRecordsRequest của bạn sử dụng TimeRangeFilter khớp với phiên. Xem phần Quyền.
Không ghi được phiên Dấu thời gian trùng lặp. Health Connect có thể từ chối các bản ghi trùng lặp với dữ liệu hiện có từ cùng một ứng dụng. Xác thực rằng startTime của một phiên mới là sau endTime của phiên trước.
Không ghi được dữ liệu GPS Dịch vụ trên nền trước bị huỷ hoặc không hoạt động. Để thu thập dữ liệu khi màn hình tắt, bạn phải sử dụng Dịch vụ trên nền trước có thuộc tính foregroundServiceType="health" hoặc vị trí.
Bản ghi trùng lặp xuất hiện Thiếu clientRecordId. Chỉ định một clientRecordId duy nhất trong Metadata của mỗi bản ghi. Điều này cho phép Health Connect thực hiện việc loại bỏ trùng lặp nếu cùng một dữ liệu được ghi hai lần trong quá trình thử lại đồng bộ hoá. Xem phần Các phương pháp hay nhất.

Các bước gỡ lỗi phổ biến

Kiểm tra trạng thái quyền. Luôn gọi getPermissionStatus() trước khi thử thực hiện thao tác đọc hoặc ghi. Người dùng có thể thu hồi quyền trong phần cài đặt hệ thống bất cứ lúc nào.
Xác minh chế độ thực thi. Nếu ứng dụng của bạn không thu thập dữ liệu ở chế độ nền, hãy xác minh rằng bạn đã khai báo các quyền chính xác trong tệp AndroidManifest.xml và người dùng chưa đặt ứng dụng ở chế độ "Hạn chế pin".