Health Connect نوع داده مراحل را برای ثبت تعداد مراحل بااستفاده از
StepsRecord ارائه میدهد. تعداد قدمها سنجهای اساسی در ردیابی سلامت و تناسب اندام است.
این راهنما با Health Connect نسخه 1.1.0-alpha12 یا بالاتر سازگار است.
خواندن تعداد قدمها در تلفن همراه
با Android 14 (سطح میانای برنامهسازی کاربردی ۳۴) و «افزونه کیت توسعه نرمافزار» نسخه ۲۰ یا بالاتر،
Health Connect شمارش قدمها را در دستگاه ارائه میدهد. اگر به برنامهای اجازه READ_STEPS داده شده باشد، Health Connect شروع به ضبط تعداد قدمها از دستگاه Android میکند و کاربران میبینند که دادههای تعداد قدمها بهطور خودکار به ورودیهای تعداد قدمها در Health Connect اضافه میشود.
برای بررسی اینکه آیا شمارش گام در دستگاه دردسترس است یا نه، بررسی کنید که دستگاه دارای Android 14 (سطح API ۳۴) باشد و حداقل نسخه ۲۰ افزونه کیت توسعه نرمافزار را داشته باشد:
val isStepTrackingAvailable =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20
اگر برنامهتان تعداد گامهای تجمیعشده را بااستفاده از
aggregate میخواند و براساس DataOrigin فیلتر نمیکند، گامهای
درون دستگاه بهطور خودکار در مجموع گنجانده میشود و برای بهروزرسانی ژوئن ۲۰۲۶
نیازی به تغییر نیست.
تغییر ارجاع برای مراحل دروندستگاهی
از بهروزرسانی ژوئن ۲۰۲۶، تعداد قدمهایی که Health Connect بهطور بومی ردیابی میکند به نام بسته مصنوعی (SPN)، مانند com.android.healthconnect.phone.jd5bdd37e1a8d3667a05d0abebfc4a89e، نسبت داده میشود.
قبلاً، مراحل داخلی به نام بسته android نسبت داده میشد.
دادههای قدیمی مربوط به تعداد قدمها که قبلاز ژوئن ۲۰۲۶ ثبت شدهاند، نام بسته android را حفظ میکنند.
SPN مختص دستگاه است و برای محافظت از حریم خصوصی کاربر، در محدوده هر برنامه تعریف میشود:
- پایدار: SPN برای دستگاه فعلی برای برنامه شما پایدار است.
- محدود به برنامه: برنامههای مختلف در یک دستگاه، «نامهای ارائهدهنده خدمات» متفاوتی را برای دادههای گام دروندستگاهی میبینند.
پرسوجو برای مراحل دروندستگاهی
چون SPNها محدود به دامنه و مختص دستگاه هستند، نباید مقادیر SPN را بهصورت کد ثابت بنویسید. بهجای آن، از
getCurrentDeviceDataSource API برای بازیابی
SPN دستگاه فعلی استفاده کنید.
درحالیکه شمارش گام در دستگاه به کیت توسعه نرمافزار نسخه ۲۰ یا بالاتر نیاز دارد،
getCurrentDeviceDataSource() API در Android 14 (سطح API ۳۴)
با کیت توسعه نرمافزار نسخه ۲۲ یا بالاتر دردسترس است. برای استفاده از این میانای برنامهسازی کاربردی،
compileSdkExtension را روی 22 یا بالاتر در سطح ماژول build.gradle.kts
یا فایل build.gradle تنظیم کنید:
کاتلین
android { compileSdk = 35 compileSdkExtension = 22 }
شیک
android { compileSdk 35 compileSdkExtension 22 }
میانای برنامهسازی کاربردی getCurrentDeviceDataSource() هنوز در کتابخانه Health Connect Jetpack دردسترس نیست. مثالهای زیر از میانای برنامهسازی کاربردی چارچوب Android استفاده میکنند،
که به یک Executor و یک 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 نوشته میشوند.
- ارجاع: مراحل ثبتشده توسط این ویژگی قبلاز ژوئن ۲۰۲۶ به نام بسته
androidدرDataOriginارجاع داده میشود. پساز این تاریخ، این دادهها به SPN مختص دستگاه نسبت داده میشوند. تغییر اسناد برای مراحل دروندستگاهی را ببینید. - فعالسازی: سازوکار شمارش قدم در دستگاه فقط زمانی فعال است که حداقل به یک برنامه در دستگاه اجازه
READ_STEPSدر Health Connect داده شده باشد.
بررسی دردسترس بودن Health Connect
قبلاز تلاش برای استفاده از Health Connect، برنامهتان باید بررسی کند که Health Connect در دستگاه کاربر دردسترس باشد. ممکن است Health Connect در همه دستگاهها ازپیش نصب نشده باشد یا غیرفعال باشد.
میتوانید بااستفاده از روش HealthConnectClient.getSdkStatus()
دردسترس بودن را بررسی کنید.
نحوه بررسی دردسترس بودن Health Connect
fun checkHealthConnectAvailability(context: Context) { val providerPackageName = "com.google.android.apps.healthdata" 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، دادههای تعداد قدمها را بنویسد. مثال زیر نحوه ثبت ۱۰۰۰ قدم برداشتهشده توسط کاربر را نشان میدهد:
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 */ }