Diese Anleitung ist mit Health Connect-Version 1.1.0 oder höher kompatibel.
Wenn du in deiner App eine Schlafanalysefunktion erstellen möchtest, kannst du Health Connect für Folgendes verwenden:
- Schlafeinheiten schreiben
- Daten zu Schlafphasen schreiben
- Schlafdaten wie Herzfrequenz, Sauerstoffsättigung und Atemfrequenz schreiben
- Schlafdaten aus anderen Apps lesen
In diesem Leitfaden wird beschrieben, wie du diese Schlaffunktionen erstellst. Dabei werden Datentypen, die Ausführung im Hintergrund, Berechtigungen, empfohlene Workflows und Best Practices behandelt.
Übersicht: Umfassenden Schlaf-Tracker erstellen
Mit Health Connect kannst du eine umfassende Schlafanalyse erstellen. Folge dazu diesen Schritten:
- Berechtigungen basierend auf Gesundheitsberechtigungen korrekt implementieren.
- Sitzungen mit
SleepSessionRecordaufzeichnen. - Datentypen wie Schlafphasen, Herzfrequenz und Sauerstoffsättigung werden während der Trainingseinheit konsistent geschrieben.
- Die Hintergrundausführung ordnungsgemäß verwalten, um die kontinuierliche Datenerfassung über Nacht zu überprüfen.
- Lesen von Sitzungsdaten 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 Sie Schlaffunktionen implementieren:
- Integrieren Sie Health Connect mit der entsprechenden Abhängigkeit.
- Erstellen Sie eine
HealthConnectClient-Instanz. - Prüfe, ob deine App die Abläufe für Laufzeitberechtigungen basierend auf Health-Berechtigungen implementiert.
Wichtige Konzepte
Health Connect stellt Schlafdaten mithilfe einiger Kernkomponenten dar. Ein SleepSessionRecord dient als zentraler Datensatz für den Schlaf und enthält Details wie Start- oder Endzeiten und Schlafphasen. Während einer Sitzung können verschiedene Datentypen wie HeartRateRecord oder OxygenSaturationRecord aufgezeichnet werden.
Schlafeinheiten
Schlafdaten werden durch SleepSessionRecord dargestellt. In jedem Eintrag wird Folgendes 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 Trainingseinheit verknüpft sind.
Datentypen
Zu den gängigen Datentypen, die während einer Schlafeinheit aufgezeichnet werden, gehören:
SleepSessionRecord: Zeichnet die Schlafdauer und die Schlafphasen auf, einschließlich Tiefschlaf, Leichtschlaf, REM-Schlaf und Wachphasen.HeartRateRecord: Zeichnet die Herzfrequenz während des Schlafs auf.OxygenSaturationRecord: Zeichnet die Sauerstoffsättigung (SpO2) während des Schlafs auf.RespiratoryRateRecord: Zeichnet die Atemfrequenz während des Schlafs auf.
Jeder Datentyp wird als einzelner Datensatz gespeichert.
Überlegungen zur Entwicklung
Apps zur Schlafanalyse müssen oft über längere Zeiträume ausgeführt werden, häufig im Hintergrund, wenn das Display ausgeschaltet ist. Bei der Entwicklung von Schlaffunktionen ist es wichtig, die Ausführung im Hintergrund zu verwalten und die erforderlichen Berechtigungen für Schlafdaten anzufordern.
Ausführung im Hintergrund
Apps zur Schlafanalyse werden in der Regel über Nacht mit ausgeschaltetem Display ausgeführt. In diesem Zustand solltest du Folgendes verwenden:
- Dienste im Vordergrund für die Datenerhebung
WorkManagerfür verzögertes Schreiben oder Synchronisieren- Batching-Strategien für regelmäßige Datensatzschreibvorgänge von detaillierten Daten wie der Herzfrequenz
Sorgen Sie für Kontinuität, indem Sie die Sitzungs-ID bei allen Schreibvorgängen einheitlich halten.
Berechtigungen
Deine App muss die entsprechenden Health Connect-Berechtigungen anfordern, bevor sie Schlafdaten lesen oder schreiben kann. Eine vollständige Liste der Datentypen findest du unter Health Connect-Datentypen. Zu den gängigen Berechtigungen für den Schlaf gehören Schlafeinheiten 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>
Wenn Sie Schlafdaten lesen möchten, müssen Sie die folgenden Berechtigungen anfordern:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
Im folgenden Beispiel wird gezeigt, wie Berechtigungen für eine Schlafeinheit angefordert werden, die Daten zur Herzfrequenz, Sauerstoffsättigung und Atemfrequenz enthält:
Nachdem Sie eine Clientinstanz erstellt haben, muss Ihre App Berechtigungen vom Nutzer anfordern. Nutzer müssen Berechtigungen jederzeit erteilen oder verweigern können. Erstellen Sie dazu eine Reihe von Berechtigungen für die erforderlichen Datentypen. Achte darauf, dass die Berechtigungen in der Gruppe zuerst in deinem 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 kannst du prüfen, ob deiner App bereits die erforderlichen Berechtigungen gewährt wurden. Falls nicht, verwenden Sie createRequestPermissionResultContract, um diese Berechtigungen anzufordern. Der Bildschirm mit den Health Connect-Berechtigungen wird 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 Schlafeinheit abgleichen möchtest, zeichne sie mit Zeitstempeln auf, die zwischen startTime und endTime der Einheit liegen. Health Connect verwendet keine Sitzungskennung, um Schlafeinheiten mit detaillierten Daten zu verknüpfen. Stattdessen erfolgt die Verknüpfung implizit über sich überschneidende Zeitintervalle. Beim Lesen von Schlafdaten kannst du den Zeitraum einer Sitzung verwenden, um nach zugehörigen Datentypen zu suchen, wie unter Schlafdaten lesen beschrieben.
Trainingseinheit schreiben
Detaillierte Daten wie die Herzfrequenz können während einer Schlafeinheit aufgezeichnet werden, die SleepSessionRecord selbst darf jedoch erst nach Beendigung der Schlafeinheit in Health Connect geschrieben werden, z. B. wenn der Nutzer aufwacht. Der Datensatz muss die startTime, endTime und eine Liste von SleepSessionRecord.Stage-Objekten enthalten, die während der Sitzung aufgezeichnet wurden, da SleepSessionRecord erfordert, dass endTime nach startTime liegt.
So zeichnest du eine Schlafeinheit auf:
- Generieren Sie eine eindeutige Client-Datensatz-ID.
- Wenn der Nutzer aufwacht oder die Schlafanalyse beendet wird, werden alle Schlafphasen erfasst und ein
SleepSessionRecord-Objekt erstellt. - Fügen Sie den Eintrag 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 werden gelesen
Apps können Schlafeinheiten und die zugehörigen Daten lesen, um Aktivitäten zusammenzufassen, Informationen zur Gesundheit bereitzustellen oder Daten mit einem externen Server zu synchronisieren. Sie können beispielsweise einen SleepSessionRecord lesen und dann die HeartRateRecord abfragen, die im selben Zeitintervall aufgetreten sind.
Trainingseinheit mit zugehörigen Daten lesen
Du kannst Schlafeinheiten mit einem ReadRecordsRequest mit SleepSessionRecord als Datensatztyp lesen, gefiltert nach einem Zeitraum. Wenn du die zugehörigen Daten für eine bestimmte Trainingseinheit lesen möchtest, stelle eine zweite Anfrage für den ausgewählten Datentyp, z. B. HeartRateRecord, und filtere nach startTime und endTime der Schlafeinheit.
Im folgenden Beispiel wird gezeigt, wie Schlafeinheiten mit zugehörigen Herzfrequenzdaten für einen bestimmten Zeitraum gelesen werden:
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:
- Während der Aktivitätsaufzeichnung häufig schreiben: Bei der Aktivitätsaufzeichnung sollten Daten geschrieben werden, sobald sie verfügbar sind, oder in einem maximalen Intervall von 15 Minuten.
- WorkManager für Hintergrundsynchronisierungen verwenden: Verwende
WorkManagerfür verzögerte Schreibvorgänge. Ein Intervall von 15 Minuten ist ein guter Kompromiss zwischen Echtzeitdaten und Akkueffizienz. - Batch-Schreibanfragen: 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 Kennungen für Ihre Sitzungen. Wenn eine Trainingseinheit bearbeitet oder aktualisiert wird, wird sie durch die Verwendung derselben ID nicht als neue, separate Trainingseinheit behandelt.
- Batching für Datentypen verwenden: Um den Ein-/Ausgabe-Overhead zu reduzieren und die Akkulaufzeit zu verlängern, gruppieren Sie Ihre Datenpunkte in einem einzigen
insertRecords-Aufruf, 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, um eindeutige Einträge zu identifizieren. Wenn Sie versuchen, einen Eintrag mit einer bereits vorhandenenclientRecordIdzu schreiben, ignoriert Health Connect das Duplikat oder aktualisiert den vorhandenen Eintrag, anstatt einen neuen zu erstellen. Das Festlegen einermetadata.clientRecordIdist die effektivste Methode, um Duplikate bei Synchronisierungswiederholungen oder Neuinstallationen von Apps zu vermeiden.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 Einträge aus Ihrer App vorhanden sind.
- Zeitstempel dürfen sich nicht überschneiden: Achten Sie darauf, dass eine neue Sitzung nicht beginnt, bevor die vorherige beendet ist. Sich überschneidende Trainingseinheiten 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 deine Blutdrucktrends zu beobachten und dir Einblicke zu geben.“ - Lang andauernde Sitzungen testen: Überwache den Akkuverbrauch während Sitzungen, die mehrere Stunden dauern, um sicherzustellen, dass das Batchintervall und die Sensornutzung den Akku des Geräts nicht zu schnell entladen.
- Zeitstempel an Sensorraten anpassen: Passen Sie die Zeitstempel Ihrer Datensätze an die tatsächliche Frequenz Ihrer Sensoren an, um die Datenqualität zu erhalten.
Test
Um die Richtigkeit der Daten und eine hohe Qualität der Nutzererfahrung zu gewährleisten, solltest du die folgenden Teststrategien befolgen und die offizielle Dokumentation Wichtige Anwendungsfälle testen lesen.
Tools zur Überprüfung
- Health Connect Toolbox:Mit dieser Companion-App können Sie Einträge manuell prüfen, Testdaten löschen und Änderungen an der Datenbank simulieren. So können Sie am besten prüfen, ob Ihre Datensätze korrekt gespeichert werden.
- Unittests mit
FakeHealthConnectClient: Mit der Testbibliothek können Sie prüfen, wie Ihre App mit Grenzfällen wie dem Widerruf von Berechtigungen oder API-Ausnahmen umgeht, ohne dass ein physisches Gerät erforderlich ist.
Checkliste für Qualität
Typische Architektur
Eine Implementierung der Schlafanalyse umfasst in der Regel Folgendes:
| Komponente | Verwaltet |
|---|---|
| Sitzungscontroller | Sitzungsstatus Timer Batching-Logik Datentyp-Controller 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 gewährt hat. Prüfen Sie, ob für ReadRecordsRequest ein TimeRangeFilter verwendet wird, der mit der Sitzung übereinstimmt. Weitere Informationen finden Sie unter Berechtigungen. |
| Sitzung kann nicht geschrieben werden | Sich überschneidende Zeitstempel. | Health Connect kann Einträge ablehnen, die sich mit vorhandenen Daten aus derselben App überschneiden. Prüfe, ob die startTime einer neuen Trainingseinheit nach der endTime der vorherigen Trainingseinheit liegt. |
| Keine Sensordaten während des Schlafs aufgezeichnet | Der Dienst im Vordergrund wurde beendet oder ist inaktiv. | Wenn du Sensordaten über Nacht erheben möchtest, während das Display ausgeschaltet ist, kannst du einen Dienst im Vordergrund mit foregroundServiceType="health" verwenden. |
| Doppelte Einträge werden angezeigt | clientRecordId fehlt. |
Weise jedem Datensatz im Metadata eine eindeutige clientRecordId zu. So kann Health Connect Duplikate entfernen, wenn dieselben Daten während eines Synchronisierungsversuchs zweimal geschrieben werden. Siehe Best Practices. |
Allgemeine Schritte zur Fehlerbehebung
| Berechtigungsstatus prüfen | Rufen Sie immer getPermissionStatus() auf, bevor Sie einen Lese- oder Schreibvorgang ausführen. Nutzer können Berechtigungen jederzeit in den Systemeinstellungen widerrufen. |
| Ausführungsmodus prüfen | Wenn Ihre App keine Daten im Hintergrund erhebt, prüfen Sie, ob Sie die richtigen Berechtigungen in der Datei AndroidManifest.xml deklariert haben und ob der Nutzer die App nicht in den Modus „Eingeschränkte Akkunutzung“ versetzt hat. |