Nếu muốn tạo trải nghiệm theo dõi giấc ngủ trong ứng dụng, bạn có thể sử dụng Health Connect để thực hiện những việc như:
- Ghi phiên giấc ngủ
- Ghi dữ liệu về giai đoạn giấc ngủ
- Ghi dữ liệu giấc ngủ, chẳng hạn như tần số tim, độ bão hòa oxy và nhịp thở
- Đọc dữ liệu giấc ngủ 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 về giấc ngủ 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 giấc ngủ toàn diện
Bạn có thể tạo trải nghiệm theo dõi giấc ngủ 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 phiên bằng
SleepSessionRecord. - Ghi các loại dữ liệu như các giai đoạn ngủ, tần số tim và độ bão hòa oxy 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 việc thu thập dữ liệu liên tục qua đêm.
- Đọc dữ liệu phiên để phân tích và tóm tắt sau khi ngủ.
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 về giấc ngủ:
- Tích hợp Health Connect bằng cách sử dụng phần phụ thuộc thích hợp.
- Tạo một thực thể
HealthConnectClient. - Xác minh rằng ứng dụng của bạn triển khai các quy trình cấp quyền khi bắt đầu chạy dựa trên Quyền truy cập vào dữ liệu sức khoẻ.
Khái niệm chính
Health Connect biểu thị dữ liệu giấc ngủ bằng một vài thành phần cốt lõi. SleepSessionRecord hoạt động như bản ghi trung tâm cho giấc ngủ, chứa các thông tin chi tiết như thời gian bắt đầu hoặc thời gian kết thúc và các giai đoạn ngủ. Trong một phiên, nhiều loại dữ liệu như HeartRateRecord hoặc OxygenSaturationRecord có thể được ghi lại.
Phiên giấc ngủ
Dữ liệu giấc ngủ được biểu thị bằng SleepSessionRecord. Mỗi bản ghi lưu trữ:
startTimeendTimestages: Danh sáchSleepSessionRecord.Stagebao gồm ngủ sâu, ngủ nông, ngủ mắt chuyển động nhanh (REM) và thức.- Siêu dữ liệu phiên không bắt buộc (tiêu đề, ghi chú)
Các ứng dụng có thể ghi nhiều loại dữ liệu được liên kết với một phiên.
Loại dữ liệu
Các loại dữ liệu phổ biến được ghi lại trong một phiên giấc ngủ bao gồm:
SleepSessionRecord: Ghi lại thời lượng ngủ và các giai đoạn ngủ, bao gồm ngủ sâu, ngủ nông, ngủ mắt chuyển động nhanh (REM) và thức.HeartRateRecord: Ghi lại tần số tim trong khi ngủ.OxygenSaturationRecord: Ghi lại độ bão hoà oxy (SpO2) trong khi ngủ.RespiratoryRateRecord: Ghi lại nhịp thở trong khi ngủ.
Mỗi loại dữ liệu được lưu trữ dưới dạng một bản ghi riêng lẻ.
Điều cần cân nhắc khi phát triển ứng dụng
Các ứng dụng theo dõi giấc ngủ 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 về giấc ngủ, 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 giấc ngủ.
Chạy ở chế độ nền
Các ứng dụng theo dõi giấc ngủ thường chạy qua đêm 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 để thu thập dữ liệu
WorkManagerđể ghi hoặc đồng bộ hoá bị trì hoãn- Chiến lược phân lô để ghi bản ghi thường xuyên về dữ liệu chi tiết như tần số tim
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 của Health Connect trước khi đọc hoặc ghi dữ liệu giấc ngủ. Để 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. Các quyền phổ biến đối với giấc ngủ bao gồm phiên giấc ngủ và các chỉ số như tần số tim hoặc độ bão hòa oxy.
Quyền truy cập vào dữ liệu về giấc ngủ được bảo vệ bằng các quyền sau:
android.permission.health.READ_SLEEPandroid.permission.health.WRITE_SLEEP
Để thêm chức năng về giấc ngủ vào ứng dụng, hãy bắt đầu bằng cách yêu cầu quyền đối với loại dữ liệu SleepSession.
Dưới đây là quyền bạn cần khai báo để có thể ghi dữ liệu về giấc ngủ:
<application>
<uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>
Để đọc dữ liệu về giấc ngủ, bạn cần yêu cầu các quyền sau:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
Sau đây là ví dụ về cách yêu cầu quyền đối với một phiên giấc ngủ bao gồm dữ liệu về tần số tim, độ bão hòa oxy và nhịp thở:
Sau khi tạo một phiên bản ứ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.
// 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)
)
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.
// 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)
}
}
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.
Triển khai phiên giấc ngủ
Phần này mô tả quy trình đề xuất để ghi dữ liệu giấc ngủ.
Để sắp xếp các loại dữ liệu như HeartRateRecord hoặc OxygenSaturationRecord với một phiên giấc ngủ, hãy ghi lại các loại dữ liệu đó bằng dấu thời gian nằm trong khoảng thời gian startTime và endTime của phiên. Health Connect không sử dụng giá trị nhận dạng phiên để liên kết các phiên giấc ngủ với dữ liệu chi tiết. Thay vào đó, mối liên kết là ngầm thông qua các khoảng thời gian chồng chéo. Khi đọc dữ liệu giấc ngủ, bạn có thể sử dụng phạm vi thời gian của phiên để truy vấn các loại dữ liệu được liên kết, như minh hoạ trong phần Đọc dữ liệu về giấc ngủ.
Ghi phiên
Mặc dù dữ liệu thật chi tiết như tần số tim có thể được ghi lại trong suốt phiên giấc ngủ, nhưng bản thân SleepSessionRecord chỉ được ghi vào Health Connect sau khi phiên kết thúc, chẳng hạn như khi người dùng thức dậy. Bản
ghi phải bao gồm
phiên startTime, endTime, và danh sách các đối tượng SleepSessionRecord.Stage
được ghi lại trong phiên, vì SleepSessionRecord yêu cầu endTime
phải sau startTime.
Cách ghi phiên giấc ngủ:
- Tạo mã nhận dạng bản ghi ứng dụng duy nhất.
- Khi người dùng thức dậy hoặc ngừng theo dõi giấc ngủ, hãy thu thập tất cả các giai đoạn giấc ngủ và tạo
SleepSessionRecord. - Chèn bản ghi bằng
insertRecords.
Ví dụ:
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))
Đọc dữ liệu giấc ngủ
Các ứng dụng có thể đọc phiên giấc ngủ và dữ liệu được liên kết để 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 SleepSessionRecord, sau đó truy vấn HeartRateRecord xảy ra trong cùng khoảng thời gian đó.
Đọc phiên có dữ liệu được liên kết
Bạn có thể đọc các phiên giấc ngủ bằng cách sử dụng ReadRecordsRequest với SleepSessionRecord làm loại bản ghi, được lọc theo một phạm vi thời gian. Để đọc dữ liệu được liên kết cho một phiên nhất định, hãy đưa ra yêu cầu thứ hai cho loại dữ liệu đã chọn, chẳng hạn như HeartRateRecord – lọc theo startTime và endTime của phiên giấc ngủ.
Ví dụ sau đây cho thấy cách đọc các phiên giấc ngủ có dữ liệu về tần số tim được liên kết cho một phạm vi thời gian nhất định:
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
}
}
}
}
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 tính năng theo dõi đang hoạt động, hãy ghi dữ liệu khi dữ liệu đó có sẵn hoặc ở khoảng thời gian tối đa là 15 phút.
- Sử dụng WorkManager để đồng bộ hoá ở chế độ nền: Sử dụng
WorkManagerđể ghi bị trì hoãn. Đặt mục tiêu là khoảng thời gian 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ô: Không ghi riêng từng sự kiện cảm biến. Phân đoạn các yêu cầu. 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 giá trị nhận dạng nhất quán cho các phiê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 phân lô cho các loại dữ liệu: Để giảm chi phí đầu vào/đầu ra và duy trì thời lượng pin, hãy nhóm các điểm dữ liệu thành một lệnh gọi
insertRecordsduy nhất thay vì ghi riêng từng điểm. - 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 bản ghi mới. Việc đặtmetadata.clientRecordIdlà cách hiệu quả nhất để ngăn chặ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 khoảng thời gian để xem bản ghi từ ứng dụng của bạn đã tồn tại hay chưa.
- Đảm bảo dấu thời gian không chồng chéo: 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 chồng chéo có thể gây ra xung đột trong bảng điều khiển thể dục và tính toán bản tóm tắt.
- Nêu rõ lý do cấp quyền: Sử dụng quy trình
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". - Thử nghiệm 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 phân lô và mức sử dụng cảm biến không làm hao pin thiết bị.
- Sắp xếp dấu thời gian với tốc độ cảm biến: So 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 thử nghiệm này và tham khảo tài liệu chính thức về Thử nghiệm các trường hợp sử dụng hàng đầu documentation.
Công cụ xác minh
- Health Connect Toolbox:Sử dụng ứng dụng đồng hành này để kiểm tra bản ghi theo cách thủ công, xoá dữ liệu thử nghiệm 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 bản ghi của bạn đang được lưu trữ đúng cách.
- Kiểm thử đơn vị bằng
FakeHealthConnectClient: Sử dụng thư viện thử nghiệm để 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 tính năng theo dõi giấc ngủ 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 phân lô Bộ điều khiển loại dữ liệu Thu thập dữ liệu |
| Lớp kho lưu trữ (gói các thao tác của Health Connect:) | Chèn phiên Chèn loại dữ liệu Chèn các giai đoạn ngủ Đọc bản tóm tắt phiên |
| Lớp giao diện người dùng (Hiển thị): | Thời lượng Loại dữ liệu trực tiếp Hình ảnh trực quan về giai đoạn giấc ngủ |
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 |
|---|---|---|
| Thiếu 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 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 chồng chéo. | Health Connect có thể từ chối các bản ghi chồng chéo 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 cảm biến trong khi ngủ | Dịch vụ trên nền trước đã bị huỷ hoặc không hoạt động. | Để thu thập dữ liệu cảm biến qua đêm khi màn hình tắt, bạn có thể sử dụng dịch vụ trên nền trước với foregroundServiceType="health". |
| 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ử 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". |