Śledzenie kroków

Health Connect udostępnia typ danych kroki do rejestrowania liczby kroków za pomocą StepsRecord. Kroki to podstawowy pomiar w śledzeniu zdrowia i aktywności fizycznej.

Odczytuj dane o krokach na urządzeniu mobilnym

W przypadku Androida 14 (API na poziomie 34) i rozszerzenia SDK w wersji 20 lub nowszej Health Connect udostępnia zliczanie kroków na urządzeniu. Jeśli jakiejkolwiek aplikacji przyznano uprawnienie READ_STEPS, Health Connect zacznie rejestrować kroki z urządzenia z Androidem, a użytkownicy będą widzieć dane o krokach automatycznie dodawane do wpisów Kroki w Health Connect.

Aby sprawdzić, czy na urządzeniu jest dostępna funkcja zliczania kroków, musisz sprawdzić, czy urządzenie działa na Androidzie 14 (API na poziomie 34) i ma co najmniej wersję rozszerzenia SDK 20. Możesz użyć tego kodu:

val isStepTrackingAvailable =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
        SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20

Kroki zarejestrowane przez Health Connect mają ustawioną wartość DataOrigin na nazwę pakietu android. Jeśli Twoja aplikacja odczytuje tylko zagregowane liczby kroków za pomocą aggregate i nie filtruje ich według DataOrigin, kroki zarejestrowane na urządzeniu są automatycznie uwzględniane w sumie.

Jeśli aplikacja musi odczytywać dane o krokach na urządzeniu lub wyświetlać dane o krokach podzielone według aplikacji lub urządzenia źródłowego, możesz wysyłać zapytania o rekordy, w których pole DataOrigin ma wartość android. Jeśli Twoja aplikacja wyświetla atrybucję danych o krokach, dane z pakietu Android powinny być przypisywane do bieżącego urządzenia. Możesz to zrobić, używając etykiety, np. „Twój telefon”, pobierając nazwę urządzenia za pomocą Settings.Global.getString(resolver, Settings.Global.DEVICE_NAME) lub sprawdzając pole Device w metadanych rekordu.

Ten przykład pokazuje, jak odczytać zagregowane dane o liczbie kroków na urządzeniu mobilnym, filtrując je według android źródła danych:

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                dataOriginFilter = setOf(DataOrigin("android"))
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Liczenie kroków na urządzeniu

Szczegółowe informacje o funkcji liczenia kroków na urządzeniu:

  • Korzystanie z czujników: Health Connect korzysta z czujnika TYPE_STEP_COUNTER firmy SensorManager. Ten czujnik jest zoptymalizowany pod kątem niskiego zużycia energii, dzięki czemu idealnie nadaje się do ciągłego śledzenia kroków w tle.
  • Granularność danych: aby oszczędzać baterię, dane o krokach są zwykle przesyłane w pakietach i zapisywane w bazie danych Health Connect nie częściej niż raz na minutę.
  • Atrybucja: jak wspomnieliśmy wcześniej, wszystkie kroki zarejestrowane przez tę funkcję na urządzeniu są przypisywane do nazwy pakietu androidDataOrigin.
  • Aktywacja: mechanizm zliczania kroków na urządzeniu jest aktywny tylko wtedy, gdy co najmniej 1 aplikacja na urządzeniu ma przyznane uprawnienie READ_STEPS w Health Connect.

Sprawdzanie dostępności Health Connect

Zanim spróbujesz użyć Health Connect, sprawdź, czy ta usługa jest dostępna na urządzeniu użytkownika. Aplikacja Health Connect może nie być wstępnie zainstalowana na wszystkich urządzeniach lub może być wyłączona. Dostępność możesz sprawdzić za pomocą HealthConnectClient.getSdkStatus()metody.

Jak sprawdzić dostępność Health Connect

fun checkHealthConnectAvailability(context: Context) {
    val providerPackageName = "com.google.android.apps.healthdata" // Or get from HealthConnectClient.DEFAULT_PROVIDER_PACKAGE_NAME
    val availabilityStatus = HealthConnectClient.getSdkStatus(context, providerPackageName)

    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE) {
      // Health Connect is not available. Guide the user to install/enable it.
      // For example, show a dialog.
      return // early return as there is no viable integration
    }
    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED) {
      // Health Connect is available but requires an update.
      // Optionally redirect to package installer to find a provider, for example:
      val uriString = "market://details?id=$providerPackageName&url=healthconnect%3A%2F%2Fonboarding"
      context.startActivity(
        Intent(Intent.ACTION_VIEW).apply {
          setPackage("com.android.vending")
          data = Uri.parse(uriString)
          putExtra("overlay", true)
          putExtra("callerId", context.packageName)
        }
      )
      return
    }
    // Health Connect is available, obtain a HealthConnectClient instance
    val healthConnectClient = HealthConnectClient.getOrCreate(context)
    // Issue operations with healthConnectClient
}

W zależności od stanu zwróconego przez getSdkStatus() możesz w razie potrzeby poprosić użytkownika o zainstalowanie lub zaktualizowanie Health Connect ze Sklepu Google Play.

Wymagane uprawnienia

Dostęp do danych o krokach jest chroniony przez te uprawnienia:

  • android.permission.health.READ_STEPS
  • android.permission.health.WRITE_STEPS

Aby dodać do aplikacji możliwość zliczania kroków, zacznij od poproszenia o uprawnienia do zapisu w przypadku typu danych Steps.

Aby móc zapisywać kroki, musisz zadeklarować to uprawnienie:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_STEPS" />
...
</application>

Aby odczytać kroki, musisz poprosić o te uprawnienia:

<application>
  <uses-permission
android:name="android.permission.health.READ_STEPS" />
...
</application>

Prośba użytkownika o uprawnienia

Po utworzeniu instancji klienta aplikacja musi poprosić użytkownika o uprawnienia. Użytkownicy muszą mieć możliwość przyznania lub odmowy przyznania uprawnień w dowolnym momencie.

Aby to zrobić, utwórz zestaw uprawnień dla wymaganych typów danych. Sprawdź, czy uprawnienia w zestawie są najpierw zadeklarowane w pliku manifestu Androida.

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(StepsRecord::class),
  HealthPermission.getWritePermission(StepsRecord::class)
)

Użyj getGrantedPermissions, aby sprawdzić, czy Twoja aplikacja ma już przyznane wymagane uprawnienia. Jeśli nie, użyj createRequestPermissionResultContract, aby poprosić o te uprawnienia. Wyświetli się ekran uprawnień 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)
  }
}

Użytkownicy mogą w dowolnym momencie przyznawać i odbierać uprawnienia, dlatego aplikacja musi okresowo sprawdzać przyznane uprawnienia i obsługiwać sytuacje, w których uprawnienia zostaną utracone.

Informacje zawarte w rekordzie kroków

Każdy element StepsRecord zawiera te informacje:

  • count: liczba kroków wykonanych w danym przedziale czasu w formacie Long.
  • startTime: czas rozpoczęcia przedziału pomiarowego.
  • endTime: czas zakończenia przedziału pomiarowego.
  • startZoneOffset: przesunięcie strefy czasowej dla czasu rozpoczęcia.
  • endZoneOffset: przesunięcie strefy czasowej dla czasu zakończenia.

Obsługiwane agregacje

Dostępne są te wartości zagregowane elementu StepsRecord:

Dostępne są te wartości zagregowane elementu StepsCadenceRecord:

Przykład użycia

W sekcjach poniżej dowiesz się, jak odczytywać i zapisywać dane StepsRecord.

Zapisywanie danych o krokach

Aplikacja może zapisywać dane o liczbie kroków, wstawiając instancje StepsRecord. Poniższy przykład pokazuje, jak zarejestrować 1000 kroków wykonanych przez użytkownika:

suspend fun writeStepsData(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant,
    startZoneOffset: ZoneOffset,
    endZoneOffset: ZoneOffset
) {
    try {
        val stepsRecord = StepsRecord(
            startTime = startTime,
            startZoneOffset = startZoneOffset,
            endTime = endTime,
            endZoneOffset = endZoneOffset,
            count = 1000
        )
        healthConnectClient.insertRecords(listOf(stepsRecord))
    } catch (e: Exception) {
        // Run error handling
    }
}

Odczytywanie danych zbiorczych

Najczęstszym sposobem odczytywania danych o krokach jest agregowanie łącznej liczby kroków w określonym przedziale czasu. Poniższy przykład pokazuje, jak odczytać łączną liczbę kroków użytkownika w określonym przedziale czasu:

suspend fun readStepsAggregate(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Odczytywanie nieprzetworzonych danych

Poniższy przykład pokazuje, jak odczytać surowe dane StepsRecord w okresie między godziną rozpoczęcia a godziną zakończenia:

suspend fun readStepsRaw(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.readRecords(
            ReadRecordsRequest(
                recordType = StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        for (record in response.records) {
            // Process each record
        }
    } catch (e: Exception) {
        // Run error handling here
    }
}