Google Health Services bietet über die ExerciseClient
erstklassigen Support für Trainings-Apps.
Mit ExerciseClient
kann Ihre App steuern, wann ein Training läuft, Trainingsziele hinzufügen und Updates zum Trainingsstatus, zu Trainingsereignissen oder zu anderen gewünschten Messwerten erhalten. Weitere Informationen finden Sie in der vollständigen Liste der Übungstypen, die von den Gesundheitsdiensten unterstützt werden.
Sehen Sie sich das Beispiel für die Übung auf GitHub an.
Abhängigkeiten hinzufügen
Wenn Sie eine Abhängigkeit von Health Services hinzufügen möchten, müssen Sie Ihrem Projekt das Google Maven-Repository hinzufügen. Weitere Informationen finden Sie im Maven-Repository von Google.
Fügen Sie dann in der Datei build.gradle
auf Modulebene die folgende Abhängigkeit hinzu:
Groovy
dependencies { implementation "androidx.health:health-services-client:1.1.0-alpha05" }
Kotlin
dependencies { implementation("androidx.health:health-services-client:1.1.0-alpha05") }
App-Struktur
Verwenden Sie die folgende App-Struktur, wenn Sie eine Trainings-App mit Gesundheitsdiensten erstellen:
- Beschränken Sie Bildschirme und Navigation auf eine Hauptaktivität.
- Verwalten Sie den Trainingsstatus, Sensordaten, laufende Aktivitäten und Daten mit einem Dienst im Vordergrund.
- Speichern Sie Daten mit Room und laden Sie sie mit WorkManager hoch.
Bei der Vorbereitung auf ein Training und während des Trainings kann Ihre Aktivität aus verschiedenen Gründen beendet werden. Der Nutzer kann zu einer anderen App wechseln oder zum Zifferblatt zurückkehren. Möglicherweise wird etwas über Ihrer Aktivität angezeigt oder das Display schaltet sich nach einer bestimmten Zeit ohne Aktivität aus.
Verwenden Sie eine kontinuierlich laufende ForegroundService
in Verbindung mit ExerciseClient
, um den ordnungsgemäßen Betrieb während des gesamten Trainings sicherzustellen.
Wenn Sie ein ForegroundService
verwenden, können Sie mit der Ongoing Activity API eine Anzeige auf Ihren Smartwatch-Oberflächen anzeigen lassen, damit Nutzer schnell zum Training zurückkehren können.
Es ist wichtig, dass Sie Standortdaten in Ihrem Dienst im Vordergrund ordnungsgemäß anfordern. Geben Sie in Ihrer Manifestdatei die erforderlichen Typen von Diensten im Vordergrund und Berechtigungen an:
<manifest ...> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application ...> <!-- If your app is designed only for devices that run Wear OS 4 or lower, use android:foregroundServiceType="location" instead. --> <service android:name=".MyExerciseSessionRecorder" android:foregroundServiceType="health|location"> </service> </application> </manifest>
Verwende AmbientLifecycleObserver
für die Aktivität vor dem Training, die den prepareExercise()
-Aufruf enthält, und für die Trainingsaktivität. Aktualisieren Sie das Display während des Trainings jedoch nicht, wenn sich das Display im Ruhemodus befindet. Das liegt daran, dass Trainingsdaten von den Gesundheitsdiensten im Batchverfahren verarbeitet werden, wenn sich das Display im Ruhemodus befindet, um Strom zu sparen. Die angezeigten Informationen sind daher möglicherweise nicht aktuell. Während eines Trainings sollten Daten angezeigt werden, die für den Nutzer sinnvoll sind. Zeigen Sie entweder aktuelle Informationen oder einen leeren Bildschirm an.
Funktionen prüfen
Jede ExerciseType
unterstützt bestimmte Datentypen für Messwerte und Trainingsziele. Prüfen Sie diese Funktionen beim Starten, da sie je nach Gerät variieren können. Ein Gerät unterstützt möglicherweise keinen bestimmten Trainingstyp oder keine bestimmte Funktion, z. B. die automatische Pause. Außerdem können sich die Funktionen eines Geräts im Laufe der Zeit ändern, z. B. nach einem Softwareupdate.
Beim Starten der App die Gerätefunktionen abfragen und Folgendes speichern und verarbeiten:
- Die Übungen, die von der Plattform unterstützt werden.
- Die für die einzelnen Übungen unterstützten Funktionen.
- Die für jede Übung unterstützten Datentypen.
- Die für jeden dieser Datentypen erforderlichen Berechtigungen.
Wenn Sie ExerciseCapabilities.getExerciseTypeCapabilities()
mit dem gewünschten Trainingstyp verwenden, sehen Sie, welche Messwerte Sie anfordern, welche Trainingsziele Sie konfigurieren und welche anderen Funktionen für diesen Typ verfügbar sind. Das ist im folgenden Beispiel zu sehen:
val healthClient = HealthServices.getClient(this /*context*/)
val exerciseClient = healthClient.exerciseClient
lifecycleScope.launch {
val capabilities = exerciseClient.getCapabilitiesAsync().await()
if (ExerciseType.RUNNING in capabilities.supportedExerciseTypes) {
runningCapabilities =
capabilities.getExerciseTypeCapabilities(ExerciseType.RUNNING)
}
}
Im zurückgegebenen ExerciseTypeCapabilities
sind unter supportedDataTypes
die Datentypen aufgeführt, für die Sie Daten anfordern können. Das ist von Gerät zu Gerät unterschiedlich. Achten Sie darauf, keine DataType
anzufordern, die nicht unterstützt wird, da Ihre Anfrage sonst fehlschlagen kann.
Anhand der Felder supportedGoals
und supportedMilestones
können Sie feststellen, ob die Übung ein Trainingsziel unterstützen kann, das Sie erstellen möchten.
Wenn Nutzer in Ihrer App die automatische Pausierung verwenden können, müssen Sie prüfen, ob diese Funktion vom Gerät unterstützt wird. Verwenden Sie dazu supportsAutoPauseAndResume
.
ExerciseClient
lehnt Anfragen ab, die auf dem Gerät nicht unterstützt werden.
Im folgenden Beispiel wird die Unterstützung für den Datentyp HEART_RATE_BPM
, die Zielvorhabenfunktion STEPS_TOTAL
und die Funktion zur automatischen Pausierung geprüft:
// Whether we can request heart rate metrics.
supportsHeartRate = DataType.HEART_RATE_BPM in runningCapabilities.supportedDataTypes
// Whether we can make a one-time goal for aggregate steps.
val stepGoals = runningCapabilities.supportedGoals[DataType.STEPS_TOTAL]
supportsStepGoals =
(stepGoals != null && ComparisonType.GREATER_THAN_OR_EQUAL in stepGoals)
// Whether auto-pause is supported.
val supportsAutoPause = runningCapabilities.supportsAutoPauseAndResume
Für Updates zum Trainingsstatus registrieren
Trainingsupdates werden an einen Listener gesendet. Ihre App kann jeweils nur einen einzelnen Listener registrieren. Richten Sie den Listener vor Beginn des Trainings ein, wie im folgenden Beispiel gezeigt. Der Empfänger erhält nur Updates zu Übungen, die Ihrer App gehören.
val callback = object : ExerciseUpdateCallback {
override fun onExerciseUpdateReceived(update: ExerciseUpdate) {
val exerciseStateInfo = update.exerciseStateInfo
val activeDuration = update.activeDurationCheckpoint
val latestMetrics = update.latestMetrics
val latestGoals = update.latestAchievedGoals
}
override fun onLapSummaryReceived(lapSummary: ExerciseLapSummary) {
// For ExerciseTypes that support laps, this is called when a lap is marked.
}
override fun onAvailabilityChanged(
dataType: DataType<*, *>,
availability: Availability
) {
// Called when the availability of a particular DataType changes.
when {
availability is LocationAvailability -> // Relates to Location/GPS.
availability is DataTypeAvailability -> // Relates to another DataType.
}
}
}
exerciseClient.setUpdateCallback(callback)
Lebensdauer der Übung verwalten
Die Gesundheitsdienste unterstützen maximal eine Übung gleichzeitig in allen Apps auf dem Gerät. Wenn eine Aktivität erfasst wird und eine andere App mit dem Erfassen einer neuen Aktivität beginnt, wird die erste Aktivität beendet.
Führen Sie vor Beginn der Übung die folgenden Schritte aus:
- Prüfen, ob eine Übung bereits erfasst wird, und entsprechend reagieren Bitten Sie den Nutzer beispielsweise um Bestätigung, bevor Sie ein vorheriges Training überschreiben und mit dem Erfassen eines neuen beginnen.
Das folgende Beispiel zeigt, wie Sie mit getCurrentExerciseInfoAsync
nach einer vorhandenen Übung suchen:
lifecycleScope.launch {
val exerciseInfo = exerciseClient.getCurrentExerciseInfoAsync().await()
when (exerciseInfo.exerciseTrackedStatus) {
OTHER_APP_IN_PROGRESS -> // Warn user before continuing, will stop the existing workout.
OWNED_EXERCISE_IN_PROGRESS -> // This app has an existing workout.
NO_EXERCISE_IN_PROGRESS -> // Start a fresh workout.
}
}
Berechtigungen
Achten Sie bei der Verwendung von ExerciseClient
darauf, dass Ihre App die erforderlichen Berechtigungen anfordert und beibehält.
Wenn Ihre App LOCATION
-Daten verwendet, muss sie auch die entsprechenden Berechtigungen anfordern und verwalten.
Führe für alle Datentypen vor dem Aufrufen von prepareExercise()
oder startExercise()
die folgenden Schritte aus:
- Geben Sie in Ihrer
AndroidManifest.xml
-Datei die entsprechenden Berechtigungen für die angeforderten Datentypen an. - Prüfen Sie, ob der Nutzer die erforderlichen Berechtigungen erteilt hat. Weitere Informationen finden Sie unter App-Berechtigungen anfordern. Health Services lehnt die Anfrage ab, wenn die erforderlichen Berechtigungen nicht bereits gewährt wurden.
Führen Sie für Standortdaten die folgenden zusätzlichen Schritte aus:
- Prüfen Sie, ob GPS auf dem Gerät aktiviert ist.
isProviderEnabled(LocationManager.GPS_PROVIDER)
Bitten Sie den Nutzer gegebenenfalls, die Standorteinstellungen zu öffnen. - Achten Sie darauf, dass während des Trainings ein
ForegroundService
mit der entsprechendenforegroundServiceType
beibehalten wird.
Training vorbereiten
Einige Sensoren wie GPS oder Herzfrequenz benötigen möglicherweise etwas Zeit zum Aufwärmen. Möglicherweise möchte der Nutzer auch seine Daten sehen, bevor er mit dem Training beginnt. Mit der optionalen Methode prepareExerciseAsync()
können diese Sensoren aufgewärmt und Daten empfangen werden, ohne dass der Timer für das Training gestartet wird. Die activeDuration
ist von dieser Vorbereitungszeit nicht betroffen.
Prüfen Sie vor dem Anruf bei prepareExerciseAsync()
Folgendes:
Prüfen Sie die plattformweite Standorteinstellung. Diese Einstellung wird vom Nutzer im Hauptmenü „Einstellungen“ gesteuert. Sie unterscheidet sich von der Berechtigungsprüfung auf App-Ebene.
Wenn die Einstellung deaktiviert ist, informieren Sie den Nutzer darüber, dass er den Zugriff auf die Standortermittlung verweigert hat, und bitten Sie ihn, sie zu aktivieren, wenn Ihre App die Standortermittlung benötigt.
Prüfen Sie, ob Ihre App Laufzeitberechtigungen für Körpersensoren (API-Level 35 oder niedriger) oder Puls (API-Level 36 oder höher), Aktivitätserkennung und Standortermittlung hat. Wenn Berechtigungen fehlen, bitten Sie den Nutzer, Laufzeitberechtigungen zu gewähren, und geben Sie einen angemessenen Kontext an. Wenn der Nutzer eine bestimmte Berechtigung nicht erteilt, entfernen Sie die mit dieser Berechtigung verknüpften Datentypen aus dem Aufruf von
prepareExerciseAsync()
. Wenn weder Körpersensoren (Herzfrequenz auf API-Ebene 36 und höher) noch Standortberechtigungen gewährt werden, rufeprepareExerciseAsync()
nicht auf. Der Vorbereitungsaufruf dient speziell dazu, vor Beginn eines Trainings eine stabile Herzfrequenz oder GPS-Fix zu erhalten. Die App kann weiterhin schrittbasierte Entfernung, Schritttempo, Geschwindigkeit und andere Messwerte abrufen, für die diese Berechtigungen nicht erforderlich sind.
So sorgen Sie dafür, dass Ihr Aufruf von prepareExerciseAsync()
erfolgreich ist:
- Verwende
AmbientLifecycleObserver
für die Aktivität vor dem Training, die den prepare-Aufruf enthält. - Rufen Sie
prepareExerciseAsync()
über Ihren Dienst im Vordergrund auf. Wenn sich der Sensor nicht in einem Dienst befindet und mit dem Aktivitätszyklus verknüpft ist, wird die Sensorvorbereitung möglicherweise unnötig beendet. - Rufen Sie
endExercise()
auf, um die Sensoren auszuschalten und den Energieverbrauch zu senken, wenn der Nutzer die Aktivität vor dem Training verlässt.
Das folgende Beispiel zeigt, wie prepareExerciseAsync()
aufgerufen wird:
val warmUpConfig = WarmUpConfig(
ExerciseType.RUNNING,
setOf(
DataType.HEART_RATE_BPM,
DataType.LOCATION
)
)
// Only necessary to call prepareExerciseAsync if body sensor (API level 35
// or lower), heart rate (API level 36+), or location permissions are given.
exerciseClient.prepareExerciseAsync(warmUpConfig).await()
// Data and availability updates are delivered to the registered listener.
Sobald sich die App im Status PREPARING
befindet, werden Updates zur Sensorverfügbarkeit in den Status ExerciseUpdateCallback
bis onAvailabilityChanged()
gesendet.
Diese Informationen können dann dem Nutzer angezeigt werden, damit er entscheiden kann, ob er mit dem Training beginnen möchte.
Training starten
Wenn Sie eine Übung starten möchten, erstellen Sie eine ExerciseConfig
, um den Übungstyp, die Datentypen, für die Sie Messwerte erhalten möchten, und alle Übungsziele oder -meilensteine zu konfigurieren.
Trainingsziele bestehen aus einem DataType
und einer Bedingung. Trainingsziele sind einmalige Ziele, die ausgelöst werden, wenn eine Bedingung erfüllt ist, z. B. wenn der Nutzer eine bestimmte Strecke zurücklegt. Es kann auch ein Meilenstein für das Training festgelegt werden. Trainingsmeilensteine können mehrmals ausgelöst werden, z. B. jedes Mal, wenn der Nutzer eine bestimmte Strecke zurückgelegt hat.
Im folgenden Beispiel wird gezeigt, wie Sie ein Ziel für jeden Typ erstellen:
const val CALORIES_THRESHOLD = 250.0
const val DISTANCE_THRESHOLD = 1_000.0 // meters
suspend fun startExercise() {
// Types for which we want to receive metrics.
val dataTypes = setOf(
DataType.HEART_RATE_BPM,
DataType.CALORIES_TOTAL,
DataType.DISTANCE
)
// Create a one-time goal.
val calorieGoal = ExerciseGoal.createOneTimeGoal(
DataTypeCondition(
dataType = DataType.CALORIES_TOTAL,
threshold = CALORIES_THRESHOLD,
comparisonType = ComparisonType.GREATER_THAN_OR_EQUAL
)
)
// Create a milestone goal. To make a milestone for every kilometer, set the initial
// threshold to 1km and the period to 1km.
val distanceGoal = ExerciseGoal.createMilestone(
condition = DataTypeCondition(
dataType = DataType.DISTANCE_TOTAL,
threshold = DISTANCE_THRESHOLD,
comparisonType = ComparisonType.GREATER_THAN_OR_EQUAL
),
period = DISTANCE_THRESHOLD
)
val config = ExerciseConfig(
exerciseType = ExerciseType.RUNNING,
dataTypes = dataTypes,
isAutoPauseAndResumeEnabled = false,
isGpsEnabled = true,
exerciseGoals = mutableListOf<ExerciseGoal<Double>>(calorieGoal, distanceGoal)
)
exerciseClient.startExerciseAsync(config).await()
}
Sie können auch für alle Übungen Runden markieren. Gesundheitsdienste stellen eine ExerciseLapSummary
mit Messwerten bereit, die über den gesamten Erfassungszeitraum aggregiert wurden.
Im vorherigen Beispiel wird die Verwendung von isGpsEnabled
gezeigt, die beim Anfordern von Standortdaten wahr sein muss. Die Verwendung von GPS kann jedoch auch bei anderen Messwerten hilfreich sein.
Wenn in ExerciseConfig
die Entfernung als DataType
angegeben ist, wird standardmäßig die Entfernung in Schritten geschätzt. Wenn Sie optional GPS aktivieren, können Standortinformationen anstelle der Schrittzahl verwendet werden, um die Entfernung zu schätzen.
Training pausieren, fortsetzen und beenden
Sie können Trainings mit der entsprechenden Methode pausieren, fortsetzen und beenden, z. B. mit pauseExerciseAsync()
oder endExerciseAsync()
.
Verwenden Sie den Status von ExerciseUpdate
als „Source of Truth“. Das Training gilt nicht als pausiert, wenn der Aufruf von pauseExerciseAsync()
zurückgegeben wird, sondern wenn dieser Status in der ExerciseUpdate
-Nachricht widergespiegelt wird. Dies ist besonders wichtig, wenn es um UI-Status geht. Wenn der Nutzer auf „Pausieren“ drückt, deaktivieren Sie die Schaltfläche „Pausieren“ und rufen Sie pauseExerciseAsync()
für den Gesundheitsdienst an. Warten Sie mit ExerciseUpdate.exerciseStateInfo.state
, bis die Gesundheitsdienste den Status „Pausiert“ erreichen, und stellen Sie dann die Schaltfläche auf „Fortsetzen“ um. Das liegt daran, dass es länger dauern kann, bis Statusaktualisierungen für die Gesundheitsdienste zugestellt werden, als bis die Schaltfläche gedrückt wird. Wenn Sie also alle Änderungen an der Benutzeroberfläche an Schaltflächendrücke binden, kann die Benutzeroberfläche nicht mehr mit dem Status der Gesundheitsdienste synchronisiert werden.
Beachten Sie dies in den folgenden Fällen:
- Die automatische Pausenfunktion ist aktiviert:Das Training kann ohne Nutzerinteraktion pausiert oder gestartet werden.
- Eine andere App startet ein Training:Ihr Training wird möglicherweise ohne Nutzerinteraktion beendet.
Wenn das Training Ihrer App von einer anderen App beendet wird, muss Ihre App die Beendigung ordnungsgemäß verarbeiten:
- Speichern Sie den Status des teilweisen Trainings, damit der Fortschritt eines Nutzers nicht gelöscht wird.
- Entfernen Sie das Symbol für laufende Aktivitäten und senden Sie dem Nutzer eine Benachrichtigung, dass sein Training von einer anderen App beendet wurde.
Berücksichtigen Sie auch den Fall, dass Berechtigungen während einer laufenden Übung widerrufen werden. Dieser wird mit dem Status isEnded
und einer ExerciseEndReason
von AUTO_END_PERMISSION_LOST
gesendet. Gehe mit diesem Fall ähnlich wie bei der Kontoschließung vor: Speichere den teilweisen Status, entferne das Symbol für laufende Aktivitäten und sende eine Benachrichtigung über das, was mit dem Nutzer passiert ist.
Im folgenden Beispiel wird gezeigt, wie die Beendigung korrekt geprüft wird:
val callback = object : ExerciseUpdateCallback {
override fun onExerciseUpdateReceived(update: ExerciseUpdate) {
if (update.exerciseStateInfo.state.isEnded) {
// Workout has either been ended by the user, or otherwise terminated
}
...
}
...
}
Dauer der Aktivität verwalten
Während einer Übung kann eine App die aktive Dauer des Trainings anzeigen. Die App, die Gesundheitsdienste und die Microcontroller-Einheit (MCU) des Geräts – der energieeffiziente Prozessor, der für das Erfassen von Aktivitäten verantwortlich ist – müssen synchronisiert sein und dieselbe aktuelle aktive Dauer haben. Zur besseren Verwaltung sendet der Dienst „Gesundheit“ eine ActiveDurationCheckpoint
, die einen Ankerpunkt liefert, von dem aus die App ihren Timer starten kann.
Da die aktive Dauer von der MCU gesendet wird und es etwas dauern kann, bis sie in der App ankommt, enthält ActiveDurationCheckpoint
zwei Properties:
activeDuration
: wie lange die Übung aktiv isttime
: Zeitpunkt, zu dem die aktive Dauer berechnet wurde
Daher kann die aktive Dauer einer Übung in der App anhand von ActiveDurationCheckpoint
mithilfe der folgenden Gleichung berechnet werden:
(now() - checkpoint.time) + checkpoint.activeDuration
So wird das kleine Delta zwischen der aktiven Dauer, die auf der MCU berechnet wird, und der Zeit, zu der sie in der App ankommt, berücksichtigt. So kann ein Chronometer in der App gestartet werden und der Timer der App ist genau auf die Zeit in den Gesundheitsdiensten und der MCU abgestimmt.
Wenn die Übung pausiert ist, wartet die App, bis die berechnete Zeit die auf der Benutzeroberfläche angezeigte Zeit überschritten hat, bevor sie den Timer auf der Benutzeroberfläche neu startet.
Das liegt daran, dass das Pausierungssignal die Health Services und die MCU mit einer leichten Verzögerung erreicht. Wenn die App beispielsweise bei t=10 Sekunden pausiert wird, liefert Health Services das PAUSED
-Update möglicherweise erst bei t=10, 2 Sekunden an die App.
Mit Daten von ExerciseClient arbeiten
Messwerte für die Datentypen, für die Ihre App registriert ist, werden in ExerciseUpdate
-Nachrichten gesendet.
Der Prozessor sendet Nachrichten nur, wenn er aktiv ist oder ein maximaler Meldezeitraum erreicht wird, z. B. alle 150 Sekunden. Verwende die ExerciseUpdate
-Frequenz nicht, um einen Chronometer mit der activeDuration
weiterzuschalten. Im Beispiel für das Training auf GitHub finden Sie ein Beispiel für die Implementierung eines unabhängigen Chronometers.
Wenn ein Nutzer ein Training startet, können ExerciseUpdate
-Nachrichten häufig gesendet werden, z. B. jede Sekunde. Wenn der Nutzer das Training startet, wird der Bildschirm möglicherweise ausgeschaltet. Gesundheitsdienste können dann weniger häufig Daten senden, werden aber weiterhin mit derselben Häufigkeit abgetastet, um das Aufwecken des Hauptprozessors zu vermeiden. Wenn der Nutzer auf den Bildschirm schaut, werden alle Daten, die gerade in Batches verarbeitet werden, sofort an Ihre App gesendet.
Batch-Frequenz steuern
In einigen Fällen möchten Sie möglicherweise festlegen, wie oft Ihre App bestimmte Datentypen empfängt, während das Display ausgeschaltet ist. Mit einem BatchingMode
-Objekt kann Ihre App das standardmäßige Batch-Verhalten überschreiben, um Daten häufiger zu erhalten.
So konfigurieren Sie die Batch-Rate:
Prüfen Sie, ob die jeweilige
BatchingMode
-Definition vom Gerät unterstützt wird:// Confirm BatchingMode support to control heart rate stream to phone. suspend fun supportsHrWorkoutCompanionMode(): Boolean { val capabilities = exerciseClient.getCapabilities() return BatchingMode.HEART_RATE_5_SECONDS in capabilities.supportedBatchingModeOverrides }
Geben Sie an, dass das
ExerciseConfig
-Objekt eine bestimmteBatchingMode
verwenden soll, wie im folgenden Code-Snippet gezeigt.val config = ExerciseConfig( exerciseType = ExerciseType.WORKOUT, dataTypes = setOf( DataType.HEART_RATE_BPM, DataType.TOTAL_CALORIES ), // ... batchingModeOverrides = setOf(BatchingMode.HEART_RATE_5_SECONDS) )
Optional kannst du
BatchingMode
während des Trainings dynamisch konfigurieren, anstatt ein bestimmtes Batching-Verhalten während der gesamten Dauer des Trainings beizubehalten:val desiredModes = setOf(BatchingMode.HEART_RATE_5_SECONDS) exerciseClient.overrideBatchingModesForActiveExercise(desiredModes)
Wenn Sie die benutzerdefinierte
BatchingMode
löschen und zum Standardverhalten zurückkehren möchten, übergeben Sie einen leeren Satz anexerciseClient.overrideBatchingModesForActiveExercise()
.
Zeitstempel
Der Zeitpunkt jedes Datenpunkts entspricht der Dauer seit dem Start des Geräts. So wandeln Sie diese in einen Zeitstempel um:
val bootInstant =
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
Dieser Wert kann dann für jeden Datenpunkt mit getStartInstant()
oder getEndInstant()
verwendet werden.
Richtigkeit der Daten
Bei einigen Datentypen können jedem Datenpunkt Genauigkeitsinformationen zugeordnet sein.
Das wird durch das Attribut accuracy
dargestellt.
Die Klassen HrAccuracy
und LocationAccuracy
können jeweils für die Datentypen HEART_RATE_BPM
und LOCATION
ausgefüllt werden. Verwenden Sie gegebenenfalls das Attribut accuracy
, um festzustellen, ob die einzelnen Datenpunkte für Ihre Anwendung ausreichend genau sind.
Daten speichern und hochladen
Verwenden Sie Room, um von Health Services übermittelte Daten zu speichern. Der Datenupload erfolgt am Ende der Übung mit einem Mechanismus wie dem Work Manager. So werden Netzwerkanrufe zum Hochladen von Daten bis zum Ende der Übung verschoben, wodurch der Energieverbrauch während der Übung minimiert und die Arbeit vereinfacht wird.
Liste zur Überprüfung der Einbindung
Bevor Sie Ihre App veröffentlichen, die die ExerciseClient
von Gesundheitsdiensten verwendet, sehen Sie sich die folgende Checkliste an, um häufige Probleme zu vermeiden.
Sind die folgenden Voraussetzungen erfüllt?
- Ihre App prüft die Funktionen des Trainingstyps und des Geräts jedes Mal, wenn sie ausgeführt wird. So können Sie erkennen, wenn ein bestimmtes Gerät oder eine bestimmte Übung keinen der Datentypen unterstützt, die für Ihre App erforderlich sind.
- Sie fordern die erforderlichen Berechtigungen an, verwalten sie und geben sie in Ihrer Manifestdatei an. Bevor
prepareExerciseAsync()
aufgerufen wird, bestätigt Ihre App, dass die Laufzeitberechtigungen erteilt wurden. - In Ihrer App wird
getCurrentExerciseInfoAsync()
verwendet, um in folgenden Fällen zu reagieren:- Es wird bereits ein Training aufgezeichnet und Ihre App überschreibt das vorherige Training.
- Eine andere App hat Ihr Training beendet. Wenn der Nutzer die App wieder öffnet, wird ihm möglicherweise eine Meldung angezeigt, dass die Übung beendet wurde, weil eine andere App übernommen hat.
- Wenn Sie
LOCATION
-Daten verwenden:- Ihre App verwaltet während der gesamten Dauer des Trainings (einschließlich des Aufrufs zum Vorbereiten) einen
ForegroundService
mit der entsprechendenforegroundServiceType
. - Prüfen Sie mit
isProviderEnabled(LocationManager.GPS_PROVIDER)
, ob GPS auf dem Gerät aktiviert ist, und fordern Sie den Nutzer gegebenenfalls auf, die Standorteinstellungen zu öffnen. - Bei anspruchsvollen Anwendungsfällen, bei denen es wichtig ist, Standortdaten mit geringer Latenz zu erhalten, sollten Sie den Fused Location Provider (FLP) einbinden und seine Daten als erste Standortbestimmung verwenden. Wenn von den Gesundheitsdiensten stabilere Standortinformationen verfügbar sind, verwenden Sie diese anstelle von FLP.
- Ihre App verwaltet während der gesamten Dauer des Trainings (einschließlich des Aufrufs zum Vorbereiten) einen
- Wenn für Ihre App ein Datenupload erforderlich ist, werden alle Netzwerkaufrufe zum Hochladen von Daten bis zum Ende der Übung verschoben. Ansonsten führt Ihre App während der gesamten Übung nur sparsam notwendige Netzwerkaufrufe aus.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Passive Datenaktualisierungen
- Gesundheitsdienste unter Wear OS
- Einführung in Ansichten