Wenn Sie in Ihrer App eine Funktion zum Schlaftracking entwickeln möchten, können Sie mit Health Connect unter anderem Folgendes tun:
- Schlafdauer schreiben
- Schlafphasendaten schreiben
- Schlafdaten wie Herzfrequenz, Sauerstoffsättigung und Atemfrequenz schreiben
- Schlafdaten aus anderen Apps lesen
In diesem Leitfaden wird beschrieben, wie du diese Schlaffunktionen entwickelst. Dabei werden Datentypen, die Ausführung im Hintergrund, Berechtigungen, empfohlene Abläufe und Best Practices behandelt.
Übersicht: Umfassenden Schlaftracker erstellen
So können Sie mit Health Connect eine umfassende Funktion zur Schlafanalyse entwickeln:
- Berechtigungen basierend auf Health Permissions korrekt implementieren.
- Sitzungen mit
SleepSessionRecordaufzeichnen. - Datentypen wie Schlafphasen, Herzfrequenz und Sauerstoffsättigung werden während der Sitzung konsistent geschrieben.
- Hintergrundausführung richtig verwalten, um die kontinuierliche Datenerfassung über Nacht zu gewährleisten.
- Lesen von Daten zu Schlafeinheiten für Zusammenfassungen und Analysen nach dem Schlafen.
Dieser Workflow ermöglicht die Interoperabilität mit anderen Health Connect-Apps und überprüft den nutzergesteuerten Datenzugriff.
Hinweis
Bevor du Schlaffunktionen implementierst:
- Health Connect mit der entsprechenden Abhängigkeit einbinden
- Erstellen Sie eine
HealthConnectClient-Instanz. - Prüfe, ob in deiner App Berechtigungsabläufe zur Laufzeit basierend auf Health Permissions implementiert sind.
Wichtige Konzepte
Schlafdaten werden in Health Connect mit einigen Kernkomponenten dargestellt. Das SleepSessionRecord ist der zentrale Datensatz für Schlaf und enthält Details wie Start- und Endzeiten sowie Schlafphasen. Während einer Sitzung können verschiedene Datentypen wie HeartRateRecord oder OxygenSaturationRecord aufgezeichnet werden.
Schlafeinheiten
Schlafdaten werden durch SleepSessionRecord dargestellt. In jedem Datensatz werden folgende Informationen gespeichert:
startTimeendTimestages: Eine Liste vonSleepSessionRecord.Stage, einschließlich Tief-, Leicht-, REM- und Wachschlaf.- Optionale Sitzungsmetadaten (Titel, Notizen)
Apps können mehrere Datentypen schreiben, die mit einer Sitzung verknüpft sind.
Datentypen
Zu den gängigen Datentypen, die während einer Schlafeinheit aufgezeichnet werden, gehören:
SleepSessionRecord: Erfasst die Schlafdauer und die Schlafphasen, einschließlich Tief-, Leicht-, REM- und Wachschlaf.HeartRateRecord: Zeichnet die Herzfrequenz während des Schlafs auf.OxygenSaturationRecord: Zeichnet die Sauerstoffsättigung (SpO2) während des Schlafs auf.RespiratoryRateRecord: Erfasst die Atemfrequenz im Schlaf.
Jeder Datentyp wird als einzelner Datensatz gespeichert.
Überlegungen zur Entwicklung
Apps zur Schlafanalyse müssen oft über längere Zeiträume hinweg ausgeführt werden, häufig im Hintergrund, wenn der Bildschirm ausgeschaltet ist. Wenn Sie Ihre Schlaffunktionen entwickeln, ist es wichtig, dass Sie sich überlegen, wie Sie die Hintergrundausführung verwalten und die erforderlichen Berechtigungen für Schlafdaten anfordern.
Ausführung im Hintergrund
Apps zur Schlafanalyse werden in der Regel über Nacht ausgeführt, während das Display ausgeschaltet ist. In diesem Fall sollten Sie Folgendes verwenden:
- Dienste im Vordergrund für die Datenerhebung
WorkManagerfür verzögertes Schreiben oder Synchronisieren- Batching-Strategien für reguläre Datensatzschreibvorgänge von detaillierten Daten wie der Herzfrequenz
Sorgen Sie für Kontinuität, indem Sie die Sitzungs-ID bei allen Schreibvorgängen beibehalten.
Berechtigungen
Ihre App muss die entsprechenden Health Connect-Berechtigungen anfordern, bevor sie Schlafdaten lesen oder schreiben kann. Eine vollständige Liste der Datentypen finden Sie unter Health Connect-Datentypen. Häufige Berechtigungen für Schlaf sind Schlafsitzungen und Messwerte wie Herzfrequenz oder Sauerstoffsättigung.
Der Zugriff auf Schlaf wird durch die folgenden Berechtigungen geschützt:
android.permission.health.READ_SLEEPandroid.permission.health.WRITE_SLEEP
Wenn du deiner App Schlaffunktionen hinzufügen möchtest, musst du zuerst Berechtigungen für den Datentyp SleepSession anfordern.
Hier ist die Berechtigung, die Sie deklarieren müssen, um „Schlaf“ schreiben zu können:
<application>
<uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>
Zum Lesen von Schlafdaten müssen Sie die folgenden Berechtigungen anfordern:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
Das Folgende ist ein Beispiel dafür, wie Berechtigungen für eine Schlafsitzung angefordert werden, die Daten zu Herzfrequenz, Sauerstoffsättigung und Atemfrequenz enthält:
Nachdem Sie eine Client-Instanz erstellt haben, muss Ihre App Berechtigungen vom Nutzer anfordern. Nutzer müssen jederzeit die Möglichkeit haben, Berechtigungen zu erteilen oder zu verweigern. Erstellen Sie dazu eine Reihe von Berechtigungen für die erforderlichen Datentypen. Die Berechtigungen im Set müssen zuerst in Ihrem Android-Manifest deklariert werden.
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) )
getGrantedPermissions, um zu prüfen, ob Ihrer App bereits die erforderlichen Berechtigungen erteilt wurden. Falls nicht, verwenden Sie createRequestPermissionResultContract, um diese Berechtigungen anzufordern. Dadurch wird der Health Connect-Berechtigungsbildschirm angezeigt.
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.") } } }
Schlafeinheit implementieren
In diesem Abschnitt wird der empfohlene Workflow zum Aufzeichnen von Schlafdaten beschrieben.
Wenn du Datentypen wie HeartRateRecord oder OxygenSaturationRecord mit einer Schlafperiode abstimmen möchtest, zeichne sie mit Zeitstempeln auf, die zwischen dem startTime und dem endTime der Periode liegen. Health Connect verwendet keine Sitzungs-ID, um Schlafeinheiten mit detaillierten Daten zu verknüpfen. Stattdessen erfolgt die Zuordnung implizit über sich überschneidende Zeiträume. Beim Lesen von Schlafdaten können Sie den Zeitraum einer Sitzung verwenden, um zugehörige Datentypen abzufragen, wie unter Schlafdaten lesen beschrieben.
Sitzung schreiben
Granulare Daten wie die Herzfrequenz können während einer Schlafsitzung aufgezeichnet werden. Das SleepSessionRecord selbst darf jedoch erst in Health Connect geschrieben werden, wenn die Sitzung beendet ist, z. B. wenn der Nutzer aufwacht. Der Datensatz muss die Sitzungs-startTime, endTime und eine Liste der während der Sitzung aufgezeichneten SleepSessionRecord.Stage-Objekte enthalten, da für SleepSessionRecord gilt, dass endTime nach startTime liegen muss.
So schreibst du eine Schlafeinheit:
- Generieren Sie eine eindeutige Client-Datensatz-ID.
- Wenn der Nutzer aufwacht oder die Schlafanalyse beendet wird, werden alle Schlafphasen erfasst und ein
SleepSessionRecorderstellt. - Fügen Sie den Datensatz mit
insertRecordsein.
Beispiel:
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))
Schlafdaten lesen
Apps können Schlafsitzungen und die zugehörigen Daten lesen, um Aktivitäten zusammenzufassen, Gesundheitsinformationen bereitzustellen oder Daten mit einem externen Server zu synchronisieren. Sie können beispielsweise einen SleepSessionRecord lesen und dann die HeartRateRecord abfragen, die im selben Zeitraum aufgetreten sind.
Lesesitzung mit zugehörigen Daten
Du kannst Schlafeinheiten mit einem ReadRecordsRequest mit SleepSessionRecord als Datensatztyp lesen, gefiltert nach einem Zeitraum. Wenn Sie die zugehörigen Daten für eine bestimmte Schlafeinheit lesen möchten, stellen Sie eine zweite Anfrage für den ausgewählten Datentyp, z. B. HeartRateRecord, und filtern Sie nach startTime und endTime der Schlafeinheit.
Das folgende Beispiel zeigt, wie du Schlafsitzungen mit zugehörigen Herzfrequenzdaten für einen bestimmten Zeitraum lesen kannst:
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
}
}
}
}
Best Practices
Befolgen Sie diese Richtlinien, um die Zuverlässigkeit der Daten und die Nutzerfreundlichkeit zu verbessern:
- Häufig schreiben, wenn das aktive Tracking läuft: Schreiben Sie Daten während des aktiven Trackings, sobald sie verfügbar sind, oder in einem maximalen Intervall von 15 Minuten.
- WorkManager für die Hintergrundsynchronisierung verwenden: Verwenden Sie
WorkManagerfür verzögerte Schreibvorgänge. Wir empfehlen ein 15-Minuten-Intervall, um ein Gleichgewicht zwischen Echtzeitdaten und Akkueffizienz zu erreichen. - Batchschreibanfragen: Schreiben Sie nicht jedes einzelne Sensorereignis einzeln. Teilen Sie Ihre Anfragen auf. Health Connect verarbeitet bis zu 1.000 Datensätze pro Schreibanfrage.
- Sitzungs-IDs stabil und eindeutig halten: Verwenden Sie einheitliche Kennzeichnungen für Ihre Sitzungen. Wenn eine Sitzung bearbeitet oder aktualisiert wird, wird sie durch die Verwendung derselben ID nicht als neue, separate Sitzung behandelt.
- Batching für Datentypen verwenden: Um den Input-/Output-Aufwand zu reduzieren und die Akkulaufzeit zu verlängern, sollten Sie Ihre Datenpunkte in einem einzigen
insertRecords-Aufruf gruppieren, anstatt jeden Punkt einzeln zu schreiben. - Doppelte Daten vermeiden: Client-IDs verwenden: Legen Sie beim Erstellen von Datensätzen eine
metadata.clientRecordIdfest. Health Connect verwendet diese Informationen, um eindeutige Datensätze zu identifizieren. Wenn Sie versuchen, einen Datensatz mit einemclientRecordIdzu schreiben, der bereits vorhanden ist, ignoriert Health Connect das Duplikat oder aktualisiert den vorhandenen Datensatz, anstatt einen neuen zu erstellen. Wenn Sie einemetadata.clientRecordIdfestlegen, können Sie Duplikate bei Synchronisierungsversuchen oder Neuinstallationen von Apps am effektivsten verhindern.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" ) )
- Vorhandene Daten prüfen: Fragen Sie vor der Synchronisierung den Zeitraum ab, um zu sehen, ob bereits Datensätze aus Ihrer App vorhanden sind.
- Zeitstempel dürfen sich nicht überschneiden: Achten Sie darauf, dass eine neue Sitzung nicht beginnt, bevor die vorherige endet. Überschneidende Sitzungen können zu Konflikten in Fitness-Dashboards und Zusammenfassungsberechnungen führen.
- Klare Begründungen für Berechtigungen angeben: Verwenden Sie den
Permission.createIntent-Ablauf, um zu erklären, warum Ihre App Zugriff auf Gesundheitsdaten benötigt, z. B. „Um Ihre Blutdrucktrends zu überwachen und Statistiken zu erstellen.“ - Sitzungen mit langer Laufzeit testen: Überwachen Sie den Akkuverbrauch während mehrstündiger Sitzungen, um zu prüfen, ob das Batching-Intervall und die Sensornutzung den Akku des Geräts nicht zu stark belasten.
- Zeitstempel an Sensorraten anpassen: Passen Sie die Zeitstempel Ihrer Aufzeichnungen an die tatsächliche Häufigkeit Ihrer Sensoren an, um die Datenqualität zu erhalten.
Test
Um die Richtigkeit der Daten und eine hohe Nutzerfreundlichkeit zu gewährleisten, sollten Sie die folgenden Teststrategien anwenden und die offizielle Dokumentation Top-Anwendungsfälle testen lesen.
Tools zur Bestätigung
- Health Connect Toolbox:Mit dieser Begleit-App können Sie Datensätze manuell prüfen, Testdaten löschen und Änderungen an der Datenbank simulieren. So können Sie am besten überprüfen, ob Ihre Datensätze richtig gespeichert werden.
- Unit-Tests mit
FakeHealthConnectClient:Mit der Testbibliothek können Sie prüfen, wie Ihre App Grenzfälle wie den Widerruf von Berechtigungen oder API-Ausnahmen ohne physisches Gerät behandelt.
Checkliste für Qualität
Typische Architektur
Eine Implementierung des Schlaftrackings umfasst in der Regel:
| Komponente | Verwaltet |
|---|---|
| Sitzungscontroller | Sitzungsstatus Timer Batching-Logik Controller für Datentypen Datenerhebung |
| Repository-Ebene (umfasst Health Connect-Vorgänge): | Sitzung einfügen Datentypen einfügen Schlafphasen einfügen Sitzungszusammenfassungen lesen |
| UI-Ebene (Displays): | Dauer Live-Datentypen Visualisierung der Schlafphasen |
Fehlerbehebung
| Symptom | Mögliche Ursache | Auflösung |
|---|---|---|
| Fehlende Datentypen (z. B. Herzfrequenz) | Fehlende Schreibberechtigungen oder falsche Zeitfilter. | Prüfen Sie, ob Sie die Berechtigung für den jeweiligen Datentyp angefordert haben und ob der Nutzer sie erteilt hat. Prüfen Sie, ob für ReadRecordsRequest ein TimeRangeFilter verwendet wird, das der Sitzung entspricht. Weitere Informationen finden Sie unter Berechtigungen. |
| Sitzung kann nicht geschrieben werden | Überlappende Zeitstempel. | Health Connect lehnt möglicherweise Datensätze ab, die sich mit vorhandenen Daten aus derselben App überschneiden. Prüfe, ob die startTime einer neuen Sitzung nach der endTime der vorherigen Sitzung liegt. |
| Während des Schlafs wurden keine Sensordaten aufgezeichnet | Der Dienst im Vordergrund wurde beendet oder ist inaktiv. | Wenn Sie Sensordaten über Nacht erheben möchten, während der Bildschirm ausgeschaltet ist, können Sie einen Vordergrunddienst mit foregroundServiceType="health" verwenden. |
| Doppelte Einträge werden angezeigt | clientRecordId fehlt. |
Weisen Sie jedem Datensatz im Metadata eine eindeutige clientRecordId zu. So kann Health Connect doppelte Daten entfernen, wenn dieselben Daten bei einem Synchronisierungsversuch zweimal geschrieben werden. Best Practices |
Häufige Schritte zur Fehlerbehebung
| Berechtigungsstatus prüfen | Rufen Sie getPermissionStatus() immer auf, bevor Sie einen Lese- oder Schreibvorgang ausführen. Nutzer können Berechtigungen jederzeit in den Systemeinstellungen widerrufen. |
| Prüfen Sie den Ausführungsmodus. | Wenn Ihre App keine Daten im Hintergrund erhebt, prüfen Sie, ob Sie die richtigen Berechtigungen in Ihrer AndroidManifest.xml-Datei deklariert haben und ob der Nutzer die App nicht in den Modus „Akkuverbrauch eingeschränkt“ versetzt hat. |