Usługi zdrowotne zapewniają najwyższej jakości wsparcie dla aplikacji treningowych za pomocą ExerciseClient
.
Dzięki ExerciseClient
Twoja aplikacja może kontrolować, kiedy trwa ćwiczenie, dodawać cele ćwiczeń oraz otrzymywać informacje o stanie ćwiczeń, zdarzeniach ćwiczeń i innych danych. Więcej informacji znajdziesz na pełnej liście typów ćwiczeń obsługiwanych przez Health Services.
Zapoznaj się z przykładowym ćwiczeniem na GitHubie.
Dodawanie zależności
Aby dodać zależność od Health Services, musisz dodać do projektu repozytorium Google Maven. Więcej informacji znajdziesz w repozytorium Maven Google.
Następnie w pliku build.gradle
na poziomie modułu dodaj tę zależność:
Groovy
dependencies { implementation "androidx.health:health-services-client:1.1.0-alpha05" }
Kotlin
dependencies { implementation("androidx.health:health-services-client:1.1.0-alpha05") }
Struktura aplikacji
Podczas tworzenia aplikacji do ćwiczeń za pomocą Health Services należy używać tej struktury aplikacji:
- Zachowaj ekrany i nawigację w ramach głównej aktywności.
- Zarządzaj stanem treningu, danymi z czujników, trwającą aktywnością i danymi z usługi na pierwszym planie.
- Przechowuj dane w usłudze Room i przesyłaj je za pomocą WorkManager.
Podczas przygotowania się do treningu i w trakcie treningu Twoja aktywność może zostać przerwana z różnych powodów. Użytkownik może przełączyć się na inną aplikację lub wrócić do tarczy zegarka. System może wyświetlać coś na ekranie podczas Twojej aktywności lub wyłączyć ekran po okresie bezczynności.
Używaj stale działającego ForegroundService
w połączeniu z ExerciseClient
, aby zapewnić prawidłowe działanie przez cały czas trwania treningu.
Dzięki ForegroundService
możesz używać interfejsu API trwającej aktywności, aby wyświetlać na tarczach zegarka wskaźnik, który pozwala użytkownikowi szybko wrócić do treningu.
Ważne jest, aby w usłudze na pierwszym planie prawidłowo prosić o dane o lokalizacji. W pliku manifestu określ niezbędne typy usług na pierwszym planie i uprawnienia:
<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>
Użyj AmbientLifecycleObserver
do aktywności przed treningiem, która zawiera wywołanie prepareExercise()
, oraz do aktywności treningowej. Nie aktualizuj jednak wyświetlacza podczas treningu w trybie otoczenia: usługi zdrowotne grupowo zapisują dane treningowe, gdy ekran urządzenia jest w trybie otoczenia, aby oszczędzać energię. Wyświetlane informacje mogą być więc nieaktualne. Podczas treningów wyświetlaj dane, które mają sens dla użytkownika, pokazując aktualne informacje lub pusty ekran.
Sprawdzanie możliwości
Każda aplikacja ExerciseType
obsługuje określone typy danych dla danych i celów ćwiczeń. Sprawdź te funkcje podczas uruchamiania, ponieważ mogą się one różnić w zależności od urządzenia. Urządzenie może nie obsługiwać określonego typu ćwiczeń lub określonej funkcji, np. automatycznej pauzy. Dodatkowo możliwości urządzenia mogą się zmieniać z czasem, np. po aktualizacji oprogramowania.
Podczas uruchamiania aplikacji zapytaj o możliwości urządzenia oraz przechowuj i przetwarzaj te dane:
- Ćwiczenia, które obsługuje platforma.
- Funkcje obsługiwane w przypadku każdego ćwiczenia.
- Typy danych obsługiwane w przypadku poszczególnych ćwiczeń.
- Uprawnienia wymagane w przypadku każdego z tych typów danych.
Użyj ExerciseCapabilities.getExerciseTypeCapabilities()
z wybranym typem ćwiczeń, aby sprawdzić, jakie dane możesz pobrać, jakie cele ćwiczeń możesz skonfigurować i jakie inne funkcje są dostępne dla tego typu. Przykład:
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)
}
}
W zwracanym elemencie ExerciseTypeCapabilities
supportedDataTypes
znajdują się typy danych, których dotyczy żądanie. Ta opcja różni się w zależności od urządzenia. Upewnij się, że nie prosisz o urządzenie DataType
, które nie jest obsługiwane, ponieważ może to spowodować niepowodzenie prośby.
Użyj pól supportedGoals
i supportedMilestones
, aby sprawdzić, czy ćwiczenie może obsługiwać cel ćwiczenia, który chcesz utworzyć.
Jeśli Twoja aplikacja umożliwia użytkownikowi korzystanie z automatycznego wstrzymywania, musisz sprawdzić, czy ta funkcja jest obsługiwana przez urządzenie z supportsAutoPauseAndResume
.
ExerciseClient
odrzuca żądania, które nie są obsługiwane na urządzeniu.
W tym przykładzie sprawdzamy obsługę typu danych HEART_RATE_BPM
, możliwości celu STEPS_TOTAL
i funkcji automatycznego wstrzymywania:
// 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
Rejestracja w celu otrzymywania powiadomień o stanie ćwiczeń
Słuchacz otrzymuje powiadomienia o ćwiczeniach. Aplikacja może zarejestrować tylko jednego słuchacza naraz. Przed rozpoczęciem treningu skonfiguruj słuchacza, jak w poniższym przykładzie. Słuchacz otrzymuje tylko informacje o ćwiczeniach należących do aplikacji.
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)
Zarządzanie czasem trwania ćwiczenia
Usługi dotyczące zdrowia obsługują maksymalnie 1 ćwiczenie naraz we wszystkich aplikacjach na urządzeniu. Jeśli podczas śledzenia ćwiczenia inna aplikacja zacznie śledzić nowe ćwiczenie, pierwsze ćwiczenie zostanie zakończone.
Przed rozpoczęciem ćwiczenia:
- Sprawdź, czy dane dotyczące ćwiczenia są już rejestrowane, i odpowiednio się zachowaj. Możesz na przykład poprosić użytkownika o potwierdzenie, zanim zastąpisz poprzednie ćwiczenie i zaczniesz rejestrować nowe.
Z tego przykładu dowiesz się, jak sprawdzić, czy istnieje już ćwiczenie o nazwie getCurrentExerciseInfoAsync
:
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.
}
}
Uprawnienia
Podczas korzystania z funkcji ExerciseClient
upewnij się, że aplikacja prosi o wymagane uprawnienia i utrzymuje je.
Jeśli Twoja aplikacja korzysta z danych LOCATION
, upewnij się, że prosi o odpowiednie uprawnienia i je zachowuje.
W przypadku wszystkich typów danych przed wywołaniem funkcji prepareExercise()
lub startExercise()
wykonaj te czynności:
- W pliku
AndroidManifest.xml
określ odpowiednie uprawnienia dla żądanych typów danych. - Sprawdź, czy użytkownik ma niezbędne uprawnienia. Więcej informacji znajdziesz w artykule Prośba o uprawnienia aplikacji. Usługi zdrowotne odrzucają żądanie, jeśli wymagane uprawnienia nie zostały jeszcze przyznane.
W przypadku danych o lokalizacji wykonaj te dodatkowe czynności:
- Sprawdź, czy na urządzeniu włączony jest GPS
isProviderEnabled(LocationManager.GPS_PROVIDER)
. W razie potrzeby poproś użytkownika o otwarcie ustawień lokalizacji. - Podczas treningu należy utrzymać
ForegroundService
z odpowiednimforegroundServiceType
.
Przygotowanie do treningu
Niektóre czujniki, takie jak GPS czy tętno, mogą potrzebować chwili na rozgrzanie się. Użytkownik może też chcieć zobaczyć swoje dane przed rozpoczęciem treningu. Opcjonalna metoda prepareExerciseAsync()
pozwala tym czujnikom się rozgrzać, a dane są otrzymywane bez uruchamiania minutnika treningu. Czas przygotowania nie ma wpływu na activeDuration
.
Zanim zadzwonisz do prepareExerciseAsync()
, sprawdź te kwestie:
Sprawdź ustawienia lokalizacji na całej platformie. Użytkownik może kontrolować to ustawienie w głównym menu ustawień. Jest ono inne niż sprawdzanie uprawnień na poziomie aplikacji.
Jeśli to ustawienie jest wyłączone, poinformuj użytkownika, że odmówił on dostępu do lokalizacji, i poproś o włączenie tej opcji, jeśli Twoja aplikacja wymaga dostępu do lokalizacji.
Sprawdź, czy Twoja aplikacja ma uprawnienia do odczytu danych z czujników na ciele (poziom API 35 lub niższy) lub tętna (poziom API 36 lub wyższy), a także czy umożliwia rozpoznawanie aktywności i dostęp do lokalizacji z dokładnością do metra. W przypadku braku uprawnień poproś użytkownika o przyznanie uprawnień w czasie działania, podając odpowiedni kontekst. Jeśli użytkownik nie udzieli określonego uprawnienia, usuń typy danych powiązane z tym uprawnieniem z wywołania do
prepareExerciseAsync()
. Jeśli nie masz uprawnień do czujnika ciała (częstotliwości pracy serca na poziomie interfejsu API 36 lub nowszego) ani uprawnień do lokalizacji, nie wywołuj metodyprepareExerciseAsync()
, ponieważ metoda prepare jest przeznaczona do uzyskiwania stabilnej częstotliwości pracy serca lub pozycji GPS przed rozpoczęciem ćwiczenia. Aplikacja może nadal uzyskiwać dane dotyczące odległości, tempa, prędkości i innych danych, które nie wymagają tych uprawnień.
Aby wywołanie funkcji prepareExerciseAsync()
zakończyło się powodzeniem:
- Użyj wartości
AmbientLifecycleObserver
do aktywności przed treningiem, która zawiera wywołanie prepare. - Zadzwoń do
prepareExerciseAsync()
z poziomu usługi na pierwszym planie. Jeśli nie jest ona w usłudze i jest powiązana z cyklem aktywności, przygotowanie czujnika może zostać niepotrzebnie przerwane. - Wywołaj funkcję
endExercise()
, aby wyłączyć czujniki i ograniczyć zużycie energii, jeśli użytkownik przejdzie do innej aktywności niż przedtreningowej.
Ten przykład pokazuje, jak wywołać funkcję prepareExerciseAsync()
:
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.
Gdy aplikacja jest w stanie PREPARING
, aktualizacje dotyczące dostępności czujnika są dostarczane w ramach ExerciseUpdateCallback
przez onAvailabilityChanged()
.
Te informacje mogą zostać wyświetlone użytkownikowi, aby mógł zdecydować, czy chce rozpocząć trening.
Rozpocznij trening
Aby rozpocząć ćwiczenie, utwórz ExerciseConfig
, aby skonfigurować typ ćwiczenia, typy danych, dla których chcesz otrzymywać dane, oraz cele lub kamienie milowe ćwiczenia.
Cele ćwiczeń składają się z DataType
i warunku. Cele ćwiczeń to cele jednorazowe, które są uruchamiane po spełnieniu określonego warunku, np. gdy użytkownik przebiegnie pewną odległość. Możesz też ustawić cel związany z ćwiczeniami. Osiągnięcia dotyczące ćwiczeń mogą być uruchamiane wielokrotnie, na przykład za każdym razem, gdy użytkownik przebiegnie pewną odległość w ramach określonego dystansu.
W tym przykładzie pokazujemy, jak utworzyć po jednym celu z każdego typu:
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()
}
Możesz też oznaczać okrążenia w przypadku wszystkich ćwiczeń. Usługi zdrowotne udostępniają ExerciseLapSummary
z danymi zagregowanymi w okresie okrążenia.
Poprzedni przykład pokazuje użycie wartości isGpsEnabled
, która musi być zwrócona jako true, gdy żądasz danych o lokalizacji. Jednak korzystanie z GPS może też ułatwiać uzyskiwanie innych danych.
Jeśli ExerciseConfig
określa odległość jako DataType
, domyślnie do oszacowania odległości używane są kroki. Opcjonalnie można włączyć GPS, aby informacje o lokalizacji były używane do szacowania odległości.
Wstrzymywanie, wznawianie i kończenie treningu
Ćwiczenia możesz wstrzymywać, wznawiać i kończyć, używając odpowiedniej metody, np. pauseExerciseAsync()
lub endExerciseAsync()
.
Użyj stanu z ExerciseUpdate
jako źródła informacji. Trening nie jest uważany za wstrzymany, gdy wywołanie funkcji pauseExerciseAsync()
zwraca wartość, ale gdy stan jest odzwierciedlony w wiadomości ExerciseUpdate
. Jest to szczególnie ważne w przypadku stanów interfejsu użytkownika. Jeśli użytkownik naciśnie przycisk pauzy, wyłącz przycisk pauzy i wywołaj funkcję pauseExerciseAsync()
w Health Services. Zaczekaj, aż usługi zdrowotne przejdą do stanu wstrzymania za pomocą przycisku ExerciseUpdate.exerciseStateInfo.state
, a następnie przełącz go, aby wznowić działanie. Dzieje się tak, ponieważ aktualizacje stanu usług zdrowotnych mogą być przesyłane dłużej niż naciśnięcie przycisku. Jeśli więc wszystkie zmiany w interfejsie będą powiązane z naciśnięciami przycisków, interfejs może stracić synchronizację ze stanem usług zdrowotnych.
Pamiętaj o tym w następujących sytuacjach:
- Automatyczne wstrzymywanie jest włączone: trening może się wstrzymywać lub rozpoczynać bez udziału użytkownika.
- Inna aplikacja uruchamia trening: trening może zostać zakończony bez interakcji użytkownika.
Jeśli trening w aplikacji zostanie przerwany przez inną aplikację, aplikacja musi prawidłowo obsłużyć przerwanie:
- Zapisywanie częściowego stanu treningu, aby nie tracić postępów użytkownika.
- Usuń ikonę bieżącej aktywności i wyślij użytkownikowi powiadomienie z informacją, że jego trening został zakończony przez inną aplikację.
Zadbaj też o to, aby aplikacja mogła działać, gdy uprawnienia zostaną cofnięte w trakcie ćwiczenia. Jest on wysyłany w stanie isEnded
z wartością ExerciseEndReason
AUTO_END_PERMISSION_LOST
. W takim przypadku postępuj podobnie jak w przypadku rozwiązania umowy: zapisz stan częściowy, usuń ikonę bieżącej aktywności i wyślij powiadomienie o tym, co się stało użytkownikowi.
Ten przykład pokazuje, jak prawidłowo sprawdzić, czy subskrypcja została zakończona:
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
}
...
}
...
}
Zarządzanie czasem trwania aktywności
Podczas ćwiczeń aplikacja może wyświetlać aktywny czas trwania treningu. Aplikacja, usługi zdrowotne i mikrokontroler (MCU) urządzenia (niskoprądowy procesor odpowiedzialny za śledzenie ćwiczeń) muszą być zsynchronizowane i mieć ten sam bieżący czas aktywności. Aby ułatwić zarządzanie tymi funkcjami, usługi zdrowotne wysyłają zdarzenie ActiveDurationCheckpoint
, które stanowi punkt odniesienia, od którego aplikacja może uruchomić swój minutnik.
Czas trwania aktywnego połączenia jest wysyłany z MCU i może trochę potrwać, zanim dotrze do aplikacji. Dlatego ActiveDurationCheckpoint
zawiera 2 właściwości:
activeDuration
: czas trwania ćwiczenia,time
: czas trwania aktywnego okresu, w którym obliczono dane
Dlatego w aplikacji aktywny czas trwania ćwiczenia można obliczyć z poziomu ActiveDurationCheckpoint
za pomocą tego równania:
(now() - checkpoint.time) + checkpoint.activeDuration
Jest to spowodowane niewielką różnicą między czasem aktywnego działania obliczanym na MCU a czasem dotarcia do aplikacji. Można go wykorzystać do ustawienia zegara w aplikacji i upewnienia się, że zegar w aplikacji jest idealnie zsynchronizowany z czasem w Health Services i MCU.
Jeśli ćwiczenie jest wstrzymane, aplikacja czeka na ponowne uruchomienie minutnika w interfejsie, aż obliczony czas przekroczy czas wyświetlany obecnie w interfejsie.
Dzieje się tak, ponieważ sygnał pauzy dociera do usług zdrowotnych i MCU z niewielkim opóźnieniem. Jeśli na przykład aplikacja jest wstrzymana w t=10 sekund, usługi Health mogą nie przesłać aktualizacji PAUSED
do aplikacji, dopóki nie osiągnie ona wartości t=10,2 sekundy.
Praca z danymi z ExerciseClient
Dane dotyczące typów danych, które zostały zarejestrowane przez aplikację, są dostarczane w wiadomościach ExerciseUpdate
.
Przetwarzacz wysyła wiadomości tylko wtedy, gdy jest aktywny lub gdy osiągnie maksymalny okres raportowania, np. co 150 sekund. Nie polegaj na częstotliwości ExerciseUpdate
, aby przesuwać zegar activeDuration
. Przykład implementacji niezależnego chronometru znajdziesz w przykładowym ćwiczeniu na GitHubie.
Gdy użytkownik rozpoczyna trening, ExerciseUpdate
wiadomości mogą być wysyłane często, np. co sekundę. Gdy użytkownik rozpocznie trening, ekran może się wyłączyć. Usługi zdrowotne mogą wtedy przesyłać dane rzadziej, ale nadal z tą samą częstotliwością, aby uniknąć budzenia procesora głównego. Gdy użytkownik spojrzy na ekran, wszystkie dane, które są w trakcie grupowania, zostaną natychmiast dostarczone do aplikacji.
Kontrolowanie szybkości grupowania
W niektórych przypadkach możesz chcieć kontrolować częstotliwość, z jaką aplikacja otrzymuje określone typy danych, gdy ekran jest wyłączony. Obiekt BatchingMode
pozwala aplikacji zastąpić domyślne zachowanie grupowania, aby częściej otrzymywać dane.
Aby skonfigurować szybkość przetwarzania w partiach:
Sprawdź, czy urządzenie obsługuje określoną definicję
BatchingMode
:// 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 }
Określ, że obiekt
ExerciseConfig
powinien używać określonego obiektuBatchingMode
, jak w tym fragmencie kodu.val config = ExerciseConfig( exerciseType = ExerciseType.WORKOUT, dataTypes = setOf( DataType.HEART_RATE_BPM, DataType.TOTAL_CALORIES ), // ... batchingModeOverrides = setOf(BatchingMode.HEART_RATE_5_SECONDS) )
Opcjonalnie możesz dynamicznie konfigurować
BatchingMode
podczas treningu, zamiast utrzymywać określonego zachowania grupowania przez cały czas trwania treningu:val desiredModes = setOf(BatchingMode.HEART_RATE_5_SECONDS) exerciseClient.overrideBatchingModesForActiveExercise(desiredModes)
Aby wyczyścić niestandardową wartość
BatchingMode
i przywrócić działanie domyślne, prześlij pusty zbiór do funkcjiexerciseClient.overrideBatchingModesForActiveExercise()
.
Sygnatury czasowe
Punkt w czasie każdego punktu danych odpowiada czasowi od momentu uruchomienia urządzenia. Aby przekonwertować go na sygnaturę czasową:
val bootInstant =
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
Następnie można użyć tej wartości z getStartInstant()
lub getEndInstant()
dla każdego punktu danych.
Dokładność danych
Niektóre typy danych mogą zawierać informacje o dokładności powiązane z poszczególnymi punktami danych.
Jest ona reprezentowana przez właściwość accuracy
.
Klasy HrAccuracy
i LocationAccuracy
można wypełniać odpowiednio dla typów danych HEART_RATE_BPM
i LOCATION
. Jeśli jest dostępna, użyj właściwości accuracy
, aby określić, czy każdy punkt danych ma wystarczającą dokładność dla Twojej aplikacji.
Przechowywanie i przesyłanie danych
Użyj Room, aby zachować dane dostarczane przez Health Services. Przesyłanie danych odbywa się na koniec ćwiczenia za pomocą mechanizmu takiego jak Menedżer zadań. Dzięki temu wywołania sieci służące do przesyłania danych są opóźniane do zakończenia ćwiczenia, co minimalizuje zużycie energii podczas ćwiczenia i upraszcza pracę.
Lista kontrolna integracji
Zanim opublikujesz aplikację, która korzysta z usług ExerciseClient
związanych ze zdrowiem, zapoznaj się z poniższą listą kontrolną, aby uniknąć typowych problemów.
Sprawdź, czy:
- Aplikacja sprawdza możliwości typu ćwiczenia i możliwości urządzenia za każdym razem, gdy jest uruchamiana. Dzięki temu możesz wykryć, kiedy dane urządzenie lub ćwiczenie nie obsługuje jednego z typów danych, których potrzebuje Twoja aplikacja.
- Musisz poprosić o wymagane uprawnienia, zachować je i wymienić je w pliku manifestu. Przed wywołaniem funkcji
prepareExerciseAsync()
aplikacja potwierdza, że uprawnienia w czasie działania zostały przyznane. - Aplikacja używa uprawnień
getCurrentExerciseInfoAsync()
, aby obsługiwać przypadki, w których:- Ćwiczenie jest już śledzone, a aplikacja zastąpi poprzednie ćwiczenie.
- Inna aplikacja zakończyła ćwiczenie. Może się tak zdarzyć, gdy użytkownik ponownie otworzy aplikację i zobaczy komunikat informujący, że ćwiczenie zostało przerwane, ponieważ przejęła je inna aplikacja.
- Jeśli używasz danych
LOCATION
:- Aplikacja utrzymuje
ForegroundService
z odpowiednimforegroundServiceType
przez cały czas wykonywania ćwiczenia (w tym podczas przygotowywania wywołania). - Sprawdzanie, czy GPS jest włączony na urządzeniu za pomocą
isProviderEnabled(LocationManager.GPS_PROVIDER)
, i w razie potrzeby wyświetlanie użytkownikowi prośby o otwarcie ustawień lokalizacji. - W wymagających zastosowaniach, w których bardzo ważne jest otrzymywanie danych o lokalizacji z niskim opóźnieniem, rozważ zintegrowanie połączonego dostawcy lokalizacji (FLP) i używanie jego danych jako początkowego wyznaczenia lokalizacji. Jeśli z usługi Health Services są dostępne bardziej stabilne informacje o lokalizacji, użyj ich zamiast FLP.
- Aplikacja utrzymuje
- Jeśli aplikacja wymaga przesyłania danych, wszystkie wywołania sieci do przesyłania danych są odkładane do czasu zakończenia ćwiczenia. W pozostałym czasie aplikacja oszczędnie korzysta z wywołań sieciowych.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Aktualizacje danych pasywnych
- Usługi związane ze zdrowiem w Wear OS
- Pierwsze kroki z kafelkami