Health Connect מספקת סוג נתונים של צעדים לתיעוד של מספר הצעדים באמצעות StepsRecord. נתוני הצעדים הם מדד בסיסי למעקב אחרי הבריאות והכושר.
קריאה של נתוני הצעדים בנייד
ב-Android 14 (רמת API 34) ובגרסה 20 ומעלה של SDK Extension, Health Connect מספק ספירת צעדים במכשיר. אם אפליקציה כלשהי קיבלה את ההרשאה READ_STEPS, Health Connect מתחיל לתעד את הצעדים מהמכשיר עם Android, והמשתמשים רואים את נתוני הצעדים שנוספו אוטומטית לרשומות צעדים ב-Health Connect.
כדי לבדוק אם יש במכשיר אפשרות לספירת צעדים, צריך לוודא שמערכת ההפעלה היא Android 14 (רמת API 34) לפחות, ושיש במכשיר לפחות SDK extension גרסה 20:
val isStepTrackingAvailable =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20
אם האפליקציה קוראת את מספר הצעדים המצטבר באמצעות aggregate ולא מסננת לפי DataOrigin, מספר הצעדים במכשיר נכלל אוטומטית בסך הכול, ולא נדרשים שינויים לעדכון מיוני 2026.
שינוי השיוך לשלבים במכשיר
החל מהעדכון של יוני 2026, השיוך של צעדים שנמדדים באופן מקורי על ידי Health Connect יהיה לשם חבילה סינתטי (SPN), כמו com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e.
בעבר, שלבים מובנים שויכו לשם החבילה android.
נתוני השלבים ההיסטוריים שנרשמו לפני יוני 2026 ישמרו את שם החבילה android.
מספרי ה-SPN הם ספציפיים למכשיר ומוגבלים לכל אפליקציה בנפרד כדי להגן על פרטיות המשתמשים:
- יציב: ה-SPN של המכשיר הנוכחי יציב עבור האפליקציה שלכם.
- במסגרת האפליקציה: אפליקציות שונות באותו מכשיר רואות SPN שונה לנתוני הצעדים במכשיר.
שאילתה לגבי צעדים במכשיר
מכיוון ש-SPN הם ספציפיים למכשיר ומוגבלים להיקף מסוים, אסור להגדיר ערכי SPN בהארדקוד. במקום זאת, משתמשים ב-API getCurrentDeviceDataSource כדי לאחזר את ה-SPN של המכשיר הנוכחי.
למרות שספירת צעדים במכשיר דורשת גרסת SDK 20 ומעלה, API getCurrentDeviceDataSource() זמין ב-Android 14 (רמת API 34) עם גרסת SDK 22 ומעלה. כדי להשתמש ב-API הזה, צריך להגדיר את compileSdkExtension לערך 22 ומעלה בקובץ build.gradle.kts או build.gradle ברמת המודול:
Kotlin
android { compileSdk = 35 compileSdkExtension = 22 }
מגניב
android { compileSdk 35 compileSdkExtension 22 }
ממשק ה-API של getCurrentDeviceDataSource() עדיין לא זמין בספריית Health Connect Jetpack. בדוגמאות הבאות נעשה שימוש ב-Android framework API, שנדרשים בו Executor וקריאה חוזרת (callback) של OutcomeReceiver:
import android.content.Context
import android.health.connect.DeviceDataSource
import android.health.connect.HealthConnectException
import android.health.connect.HealthConnectManager
import android.os.OutcomeReceiver
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
healthConnectManager?.getCurrentDeviceDataSource(
context.mainExecutor,
object : OutcomeReceiver<DeviceDataSource, HealthConnectException> {
override fun onResult(result: DeviceDataSource) {
val currentDeviceSpn = result.deviceDataOrigin.packageName
}
override fun onError(error: HealthConnectException) {
// Handle error
}
}
)
אם האפליקציה צריכה לקרוא את הנתונים של הצעדים במכשיר, או אם היא מציגה נתוני צעדים שמפורטים לפי אפליקציית המקור או המכשיר, צריך לשלוח שאילתה לגבי רשומות שבהן DataOrigin הוא android או תואם ל-SPN של המכשיר. אם האפליקציה מציגה שיוך לנתוני צעדים, צריך להשתמש ב-metadata.device כדי לזהות את מכשיר המקור של רשומות נפרדות. לשלבים במכשיר שמזוהים על ידי SPN בנתונים מצטברים, אפשר להשתמש במטא-נתונים של המכשיר, כמו model או manufacturer מ-DeviceDataSource, לצורך שיוך, או להשתמש בתווית כללית כמו 'הטלפון שלך' לשלבים במכשיר.
בדוגמה הבאה אפשר לראות איך קוראים נתונים מצטברים של ספירת הצעדים במכשיר על ידי סינון לפי android וגם לפי ה-SPN של המכשיר הנוכחי:
import android.content.Context
import android.health.connect.DeviceDataSource
import android.health.connect.HealthConnectException
import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.OutcomeReceiver
import android.os.ext.SdkExtensions
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.metadata.DataOrigin
import androidx.health.connect.client.request.AggregateRequest
import androidx.health.connect.client.time.TimeRangeFilter
import java.time.Instant
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlinx.coroutines.suspendCancellableCoroutine
suspend fun readDeviceStepsByTimeRange(
healthConnectClient: HealthConnectClient,
context: Context,
startTime: Instant,
endTime: Instant
) {
// 1. Check if SDK Extension 22+ is available for getCurrentDeviceDataSource()
val isDataSourceApiAvailable =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 22
try {
val healthConnectManager = context.getSystemService(HealthConnectManager::class.java)
// 2. Safely fetch the package name only if the API is available
val currentDeviceSpn = if (isDataSourceApiAvailable && healthConnectManager != null) {
suspendCancellableCoroutine { continuation ->
healthConnectManager.getCurrentDeviceDataSource(
context.mainExecutor,
object : OutcomeReceiver<DeviceDataSource, HealthConnectException> {
override fun onResult(result: DeviceDataSource) {
continuation.resume(result.deviceDataOrigin.packageName)
}
override fun onError(error: HealthConnectException) {
continuation.resumeWithException(error)
}
}
)
}
} else {
null
}
val dataOriginFilters = mutableSetOf(DataOrigin("android"))
// 3. Explicit null-safety check using .let
currentDeviceSpn?.let {
dataOriginFilters.add(DataOrigin(it))
}
val response = healthConnectClient.aggregate(
AggregateRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
dataOriginFilter = dataOriginFilters
)
)
val stepCount = response[StepsRecord.COUNT_TOTAL]
} catch (e: Exception) {
// Now this catch block only handles actual runtime exceptions,
// rather than Errors from missing methods.
}
}
ספירת צעדים במכשיר
- שימוש בחיישנים: אפליקציית Health Connect משתמשת בחיישן
TYPE_STEP_COUNTERשלSensorManager. החיישן הזה מותאם לצריכת חשמל נמוכה, ולכן הוא אידיאלי למעקב רציף אחרי צעדים ברקע. - גרנולריות הנתונים: כדי לחסוך בסוללה, נתוני הצעדים בדרך כלל נכתבים בקבוצות למסד הנתונים של Health Connect בתדירות של פעם בדקה לכל היותר.
- שיוך (Attribution): שלבים שתועדו על ידי התכונה הזו לפני יוני 2026 משויכים לשם החבילה
androidב-DataOrigin. אחרי התאריך הזה, הן משויכות למספר SPN ספציפי למכשיר. מידע נוסף זמין במאמר בנושא שינוי השיוך של שלבים במכשיר. - הפעלה: מנגנון ספירת הצעדים במכשיר פעיל רק אם לפחות אפליקציה אחת במכשיר קיבלה את ההרשאה
READ_STEPSב-Health Connect.
בדיקת הזמינות של Health Connect
לפני שמנסים להשתמש ב-Health Connect, האפליקציה צריכה לוודא שהשירות זמין במכשיר של המשתמש. יכול להיות שאפליקציית Health Connect לא מותקנת מראש בחלק מהמכשירים או שהיא מושבתת.
אפשר לבדוק את הזמינות באמצעות ה-method HealthConnectClient.getSdkStatus().
איך בודקים אם אפליקציית 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 }
בהתאם לסטטוס שמוחזר על ידי getSdkStatus(), אפשר להנחות את המשתמש להתקין או לעדכן את Health Connect מחנות Google Play, אם יש צורך בכך.
ההרשאות הנדרשות
הגישה לנתוני הצעדים מוגנת על ידי ההרשאות הבאות:
android.permission.health.READ_STEPSandroid.permission.health.WRITE_STEPS
כדי להוסיף לאפליקציה אפשרות של צעדים, צריך קודם לבקש הרשאות לסוג הנתונים Steps.
זו ההרשאה שצריך להצהיר עליה כדי שיהיה אפשר לכתוב צעדים:
<application>
<uses-permission
android:name="android.permission.health.WRITE_STEPS" />
...
</application>
כדי לקרוא את השלבים, צריך לבקש את ההרשאות הבאות:
<application>
<uses-permission
android:name="android.permission.health.READ_STEPS" />
...
</application>
בקשת הרשאות מהמשתמש
אחרי שיוצרים מופע של לקוח, האפליקציה צריכה לבקש הרשאות מהמשתמש. צריך לאפשר למשתמשים להעניק או לדחות הרשאות בכל שלב. כדי לעשות זאת, יוצרים קבוצת הרשאות לסוגי הנתונים הנדרשים. קודם צריך לוודא שההרשאות בקבוצה מוצהרות במניפסט של Android.
val permissions = setOf( HealthPermission.getReadPermission(StepsRecord::class), HealthPermission.getWritePermission(StepsRecord::class) )
getGrantedPermissions כדי לבדוק אם האפליקציה כבר קיבלה את ההרשאות הנדרשות. אם לא, משתמשים ב-createRequestPermissionResultContract כדי לבקש את ההרשאות האלה. הפעולה הזו תציג את מסך ההרשאות של Health Connect.
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.") } } }
המידע שכלול ברשומה של צעדים
כל StepsRecord מכיל את הפרטים הבאים:
-
count: מספר הצעדים שבוצעו במרווח הזמן, כערךLong. -
startTime: שעת ההתחלה של מרווח המדידה. -
endTime: שעת הסיום של מרווח המדידה. -
startZoneOffset: ההפרש מאזור הזמן של שעת ההתחלה. -
endZoneOffset: ההסטה מאזור הזמן של שעת הסיום.
צבירות נתמכות
הערכים המצטברים הבאים זמינים עבור StepsRecord:
הערכים המצטברים הבאים זמינים עבור StepsCadenceRecord:
דוגמת שימוש
בקטעים הבאים מוסבר איך לקרוא ולכתוב נתונים של StepsRecord.
כתיבה של נתוני הצעדים
האפליקציה יכולה לכתוב נתונים של מספר הצעדים על ידי הוספה של מופעים של StepsRecord
בדוגמה הבאה אפשר לראות איך מתעדים 1,000 צעדים שמשתמש עשה:
val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime) val stepsRecord = StepsRecord( count = 120, startTime = startTime, endTime = endTime, startZoneOffset = zoneOffset, endZoneOffset = zoneOffset, metadata = Metadata.autoRecorded( device = Device(type = Device.TYPE_WATCH) ) ) healthConnectClient.insertRecords(listOf(stepsRecord))
קריאת נתונים מצטברים
הדרך הנפוצה ביותר לקרוא נתוני צעדים היא לצבור את סך הצעדים לאורך תקופת זמן מסוימת. בדוגמה הבאה אפשר לראות איך קוראים את ספירת הצעדים הכוללת של משתמש בטווח תאריכים מסוים:
suspend fun readStepsAggregate(startTime: Instant, endTime: Instant): Long { val response = healthConnectClient.aggregate( AggregateRequest( metrics = setOf(StepsRecord.COUNT_TOTAL), timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) return response[StepsRecord.COUNT_TOTAL] ?: 0L }
קריאת נתונים גולמיים
בדוגמה הבאה אפשר לראות איך קוראים נתוני StepsRecord גולמיים בין שעת התחלה לשעת סיום:
val response = healthConnectClient.readRecords( ReadRecordsRequest( StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime) ) ) response.records.forEach { record -> /* Process records */ }