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" // 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 راهنمایی کنید.
در دسترس بودن ویژگی
برای تعیین اینکه آیا دستگاه کاربر از برنامههای آموزشی Health Connect پشتیبانی میکند یا خیر، در دسترس بودنFEATURE_PLANNED_EXERCISE
را در کلاینت بررسی کنید:if (healthConnectClient
.features
.getFeatureStatus(
HealthConnectFeatures.FEATURE_PLANNED_EXERCISE
) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {
// Feature is available
} else {
// Feature isn't available
}
مجوزهای مورد نیاز
دسترسی به تمرین برنامهریزیشده توسط مجوزهای زیر محافظت میشود:
-
android.permission.health.READ_PLANNED_EXERCISE
-
android.permission.health.WRITE_PLANNED_EXERCISE
برای افزودن قابلیت تمرین برنامهریزیشده به برنامهتان، با درخواست مجوزهای نوشتن برای نوع دادهی PlannedExerciseSession
شروع کنید.
برای نوشتن تمرین برنامهریزیشده، باید مجوز زیر را اعلام کنید:
<application>
<uses-permission
android:name="android.permission.health.WRITE_PLANNED_EXERCISE" />
...
</application>
برای خواندن تمرین برنامهریزیشده، باید مجوزهای زیر را درخواست کنید:
<application>
<uses-permission
android:name="android.permission.health.READ_PLANNED_EXERCISE" />
...
</application>
درخواست مجوز از کاربر
پس از ایجاد یک نمونه کلاینت، برنامه شما باید از کاربر درخواست مجوز کند. کاربران باید بتوانند در هر زمانی مجوزها را اعطا یا رد کنند.
برای انجام این کار، مجموعهای از مجوزها را برای انواع دادههای مورد نیاز ایجاد کنید. مطمئن شوید که مجوزهای موجود در مجموعه ابتدا در مانیفست اندروید شما تعریف شدهاند.
// Create a set of permissions for required data types
val PERMISSIONS =
setOf(
HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.getWritePermission(HeartRateRecord::class),
HealthPermission.getReadPermission(PlannedExerciseSessionRecord::class),
HealthPermission.getWritePermission(PlannedExerciseSessionRecord::class),
HealthPermission.getReadPermission(ExerciseSessionRecord::class),
HealthPermission.getWritePermission(ExerciseSessionRecord::class)
)
از getGrantedPermissions
برای بررسی اینکه آیا برنامه شما مجوزهای لازم را از قبل دریافت کرده است یا خیر، استفاده کنید. در غیر این صورت، از createRequestPermissionResultContract
برای درخواست این مجوزها استفاده کنید. این کار صفحه مجوزهای 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)
}
}
از آنجا که کاربران میتوانند در هر زمانی مجوزها را اعطا یا لغو کنند، برنامه شما باید به صورت دورهای مجوزهای اعطا شده را بررسی کند و سناریوهایی را که در آنها مجوز از دست میرود، مدیریت کند.
مجوزهای مرتبط
برنامههای تمرینی به جلسات ورزشی مرتبط هستند. بنابراین، کاربر باید برای استفاده کامل از این ویژگی Health Connect، اجازه استفاده از هر نوع رکورد مربوط به یک برنامه تمرینی را بدهد.
برای مثال، اگر یک برنامه تمرینی ضربان قلب کاربر را در طول یک سری دویدن اندازهگیری کند، ممکن است مجوزهای زیر توسط توسعهدهنده اعلام و توسط کاربر اعطا شود تا بتواند جلسه تمرین را بنویسد و نتایج را برای ارزیابی بعدی بخواند:
-
android.permission.health.READ_EXERCISE
-
android.permission.health.READ_EXERCISE_ROUTES
-
android.permission.health.READ_HEART_RATE
-
android.permission.health.WRITE_EXERCISE
-
android.permission.health.WRITE_EXERCISE_ROUTE
-
android.permission.health.WRITE_HEART_RATE
با این حال، اغلب برنامهای که برنامههای تمرینی ایجاد میکند و عملکرد را در مقایسه با برنامهها ارزیابی میکند، با برنامهای که برنامههای تمرینی را مصرف میکند و دادههای تمرینی واقعی را مینویسد، یکسان نیست. بسته به نوع برنامه، به همه مجوزهای خواندن و نوشتن نیاز نیست. به عنوان مثال، ممکن است فقط برای هر نوع برنامه به این مجوزها نیاز داشته باشید:
اپلیکیشن طرح آموزشی | برنامه تمرین |
---|---|
WRITE_PLANNED_EXERCISE | READ_PLANNED_EXERCISE |
READ_EXERCISE | WRITE_EXERCISE |
READ_EXERCISE_ROUTES | WRITE_EXERCISE_ROUTE |
READ_HEART_RATE | WRITE_HEART_RATE |
اطلاعات موجود در پرونده جلسه تمرینی برنامهریزیشده
- عنوان جلسه.
- فهرستی از بلوکهای ورزشی برنامهریزیشده .
- زمان شروع و پایان جلسه.
- نوع تمرین.
- یادداشتهایی برای فعالیت
- فراداده (متادیتا).
- شناسه جلسه تمرینی تکمیلشده — این شناسه بهطور خودکار پس از تکمیل یک جلسه تمرینی مرتبط با این جلسه تمرینی برنامهریزیشده نوشته میشود.
اطلاعات موجود در یک رکورد بلوک تمرینی برنامهریزیشده
یک بلوک تمرینی برنامهریزیشده شامل فهرستی از مراحل تمرینی است تا از تکرار گروههای مختلف مراحل پشتیبانی کند (برای مثال، پنج بار پشت سر هم حرکات جلو بازو، برپی و کرانچ را انجام دهید).
- توضیحات بلوک.
- فهرستی از مراحل ورزشی برنامهریزیشده .
- تعداد تکرارها.
اطلاعات موجود در یک گزارش گام ورزشی برنامهریزیشده
- شرح مرحله.
- دسته بندی ورزش .
- نوع تمرین .
- فهرستی از اهداف عملکردی .
- هدف تکمیل .
تجمیعهای پشتیبانیشده
هیچ تجمیع پشتیبانیشدهای برای این نوع داده وجود ندارد.
مثال استفاده
فرض کنید کاربری برای دو روز آینده یک دویدن ۹۰ دقیقهای برنامهریزی میکند. این دویدن شامل سه دور دور دریاچه با ضربان قلب هدف بین ۹۰ تا ۱۱۰ ضربه در دقیقه خواهد بود.
- یک جلسه تمرینی برنامهریزیشده با موارد زیر توسط کاربر در یک برنامه برنامه تمرینی تعریف میشود:
- شروع و پایان برنامه ریزی شده برای اجرا
- نوع ورزش (دویدن)
- تعداد دورها (تکرارها)
- هدف عملکردی برای ضربان قلب (بین ۹۰ تا ۱۱۰ ضربه در دقیقه)
- این اطلاعات به بلوکهای ورزشی و مراحل دستهبندی شده و توسط برنامهی برنامهی تمرینی به عنوان یک
PlannedExerciseSessionRecord
در Health Connect ثبت میشود. - کاربر جلسه برنامهریزیشده (در حال اجرا) را انجام میدهد.
- دادههای تمرینی مربوط به جلسه به یکی از روشهای زیر ثبت میشوند:
- توسط یک دستگاه پوشیدنی در طول جلسه. به عنوان مثال، ضربان قلب. این دادهها به عنوان نوع رکورد برای فعالیت در Health Connect نوشته میشوند. در این مورد،
HeartRateRecord
. - به صورت دستی توسط کاربر پس از جلسه. به عنوان مثال، نشان دهنده شروع و پایان دویدن واقعی. این داده به عنوان یک
ExerciseSessionRecord
در Health Connect نوشته میشود.
- توسط یک دستگاه پوشیدنی در طول جلسه. به عنوان مثال، ضربان قلب. این دادهها به عنوان نوع رکورد برای فعالیت در Health Connect نوشته میشوند. در این مورد،
- در زمانی دیگر، برنامهی تمرینی، دادههای Health Connect را میخواند تا عملکرد واقعی را در مقایسه با اهداف تعیینشده توسط کاربر در جلسهی تمرینی برنامهریزیشده ارزیابی کند.
تمرینات را برنامهریزی کنید و اهداف را تعیین کنید
کاربر میتواند برای ورزش خود در آینده برنامهریزی کند و اهدافی را تعیین کند. این را به عنوان یک جلسه ورزشی برنامهریزی شده برای Health Connect بنویسید.
در مثالی که در بخش «مثال استفاده» توضیح داده شده است، کاربر برای دو روز آینده یک دویدن ۹۰ دقیقهای برنامهریزی میکند. این دویدن شامل سه دور دویدن دور دریاچه با ضربان قلب هدف بین ۹۰ تا ۱۱۰ ضربه در دقیقه خواهد بود.
قطعه کدی مانند این را میتوان در مدیریت فرم برنامهای که جلسات ورزشی برنامهریزی شده را در Health Connect ثبت میکند، یافت. همچنین میتوان آن را در نقطه ورود برای ادغامها، مثلاً با سرویسی که آموزش ارائه میدهد، یافت.
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(PlannedExerciseSessionRecord::class))) {
// The user hasn't granted the app permission to write planned exercise session data.
return
}
val plannedDuration = Duration.ofMinutes(90)
val plannedStartDate = LocalDate.now().plusDays(2)
val plannedExerciseSessionRecord = PlannedExerciseSessionRecord(
startDate = plannedStartDate,
duration = plannedDuration,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
blocks = listOf(
PlannedExerciseBlock(
repetitions = 1, steps = listOf(
PlannedExerciseStep(
exerciseType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING,
exercisePhase = PlannedExerciseStep.EXERCISE_PHASE_ACTIVE,
completionGoal = ExerciseCompletionGoal.RepetitionsGoal(repetitions = 3),
performanceTargets = listOf(
ExercisePerformanceTarget.HeartRateTarget(
minHeartRate = 90.0, maxHeartRate = 110.0
)
)
),
), description = "Three laps around the lake"
)
),
title = "Run at lake",
notes = null,
metadata = Metadata.manualEntry(
device = Device(type = Device.Companion.TYPE_PHONE)
)
)
val insertedPlannedExerciseSessions =
healthConnectClient.insertRecords(listOf(plannedExerciseSessionRecord)).recordIdsList
val insertedPlannedExerciseSessionId = insertedPlannedExerciseSessions.first()
ثبت دادههای ورزش و فعالیت
دو روز بعد، کاربر جلسه تمرینی واقعی را ثبت میکند. این را به عنوان یک جلسه تمرینی در Health Connect بنویسید.
در این مثال، مدت زمان جلسه کاربر دقیقاً با مدت زمان برنامهریزی شده مطابقت داشت.
قطعه کد زیر ممکن است در کنترلکنندهی فرم برنامهای که جلسات ورزشی را در Health Connect ثبت میکند، یافت شود. همچنین ممکن است در کنترلکنندههای دریافت و ارسال دادهها برای یک دستگاه پوشیدنی که قادر به تشخیص و ثبت جلسات ورزشی است، یافت شود.
در اینجا از مثال قبلی دوباره از شناسهی insertedPlannedExerciseSessionId
استفاده شده است. در یک برنامهی واقعی، شناسه توسط کاربر و با انتخاب یک جلسهی تمرینی برنامهریزیشده از فهرست جلسات موجود تعیین میشود.
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(ExerciseSessionRecord::class))) {
// The user doesn't granted the app permission to write exercise session data.
return
}
val sessionDuration = Duration.ofMinutes(90)
val sessionEndTime = Instant.now()
val sessionStartTime = sessionEndTime.minus(sessionDuration)
val exerciseSessionRecord = ExerciseSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
segments = listOf(
ExerciseSegment(
startTime = sessionStartTime,
endTime = sessionEndTime,
repetitions = 3,
segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING
)
),
title = "Run at lake",
plannedExerciseSessionId = insertedPlannedExerciseSessionId,
metadata = Metadata.manualEntry(
device = Device(type = Device.Companion.TYPE_PHONE)
)
)
val insertedExerciseSessions =
healthConnectClient.insertRecords(listOf(exerciseSessionRecord))
یک دستگاه پوشیدنی همچنین ضربان قلب آنها را در طول دویدن ثبت میکند. قطعه کد زیر میتواند برای تولید رکوردها در محدوده هدف استفاده شود.
در یک برنامه واقعی، بخشهای اصلی این قطعه کد ممکن است در هندلر مربوط به پیام دریافتی از یک گجت پوشیدنی یافت شوند که پس از دریافت، اندازهگیری را در Health Connect مینویسد.
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(HeartRateRecord::class))) {
// The user doesn't granted the app permission to write heart rate record data.
return
}
val samples = mutableListOf<HeartRateRecord.Sample>()
var currentTime = sessionStartTime
while (currentTime.isBefore(sessionEndTime)) {
val bpm = Random.nextInt(21) + 90
val heartRateRecord = HeartRateRecord.Sample(
time = currentTime,
beatsPerMinute = bpm.toLong(),
)
samples.add(heartRateRecord)
currentTime = currentTime.plusSeconds(180)
}
val heartRateRecord = HeartRateRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
samples = samples,
metadata = Metadata.autoRecorded(
device = Device(type = Device.Companion.TYPE_WATCH)
)
)
val insertedHeartRateRecords = healthConnectClient.insertRecords(listOf(heartRateRecord))
ارزیابی اهداف عملکردی
روز بعد از تمرین کاربر، میتوانید تمرین ثبتشده را بازیابی کنید، اهداف تمرینی برنامهریزیشده را بررسی کنید و انواع دادههای اضافی را ارزیابی کنید تا مشخص شود که آیا به اهداف تعیینشده دست یافتهاید یا خیر.
چنین قطعه کدی احتمالاً در یک کار دورهای برای ارزیابی اهداف عملکرد یا هنگام بارگذاری لیستی از تمرینها و نمایش اعلانی در مورد اهداف عملکرد در یک برنامه یافت میشود.
// Verify the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.containsAll(
listOf(
HealthPermission.getReadPermission(ExerciseSessionRecord::class),
HealthPermission.getReadPermission(PlannedExerciseSessionRecord::class),
HealthPermission.getReadPermission(HeartRateRecord::class)
)
)
) {
// The user doesn't granted the app permission to read exercise session record data.
return
}
val searchDuration = Duration.ofDays(1)
val searchEndTime = Instant.now()
val searchStartTime = searchEndTime.minus(searchDuration)
val response = healthConnectClient.readRecords(
ReadRecordsRequest<ExerciseSessionRecord>(
timeRangeFilter = TimeRangeFilter.between(searchStartTime, searchEndTime)
)
)
for (exerciseRecord in response.records) {
val plannedExerciseRecordId = exerciseRecord.plannedExerciseSessionId
val plannedExerciseRecord =
if (plannedExerciseRecordId == null) null else healthConnectClient.readRecord(
PlannedExerciseSessionRecord::class, plannedExerciseRecordId
).record
if (plannedExerciseRecord != null) {
val aggregateRequest = AggregateRequest(
metrics = setOf(HeartRateRecord.BPM_AVG),
timeRangeFilter = TimeRangeFilter.between(
exerciseRecord.startTime, exerciseRecord.endTime
),
)
val aggregationResult = healthConnectClient.aggregate(aggregateRequest)
val maxBpm = aggregationResult[HeartRateRecord.BPM_MAX]
val minBpm = aggregationResult[HeartRateRecord.BPM_MIN]
if (maxBpm != null && minBpm != null) {
plannedExerciseRecord.blocks.forEach { block ->
block.steps.forEach { step ->
step.performanceTargets.forEach { target ->
when (target) {
is ExercisePerformanceTarget.HeartRateTarget -> {
val minTarget = target.minHeartRate
val maxTarget = target.maxHeartRate
if(
minBpm >= minTarget && maxBpm <= maxTarget
) {
// Success!
}
}
// Handle more target types
}
}
}
}
}
}
}
}
جلسات تمرینی
جلسات ورزشی میتواند شامل هر چیزی از دویدن گرفته تا بدمینتون باشد.
جلسات تمرینی بنویسید
نحوهی ساخت یک درخواست درج که شامل یک جلسه (session) است، به این صورت است:
suspend fun writeExerciseSession(healthConnectClient: HealthConnectClient) {
healthConnectClient.insertRecords(
listOf(
ExerciseSessionRecord(
startTime = START_TIME,
startZoneOffset = START_ZONE_OFFSET,
endTime = END_TIME,
endZoneOffset = END_ZONE_OFFSET,
exerciseType = ExerciseSessionRecord.ExerciseType.RUNNING,
title = "My Run"
),
// ... other records
)
)
}
یک جلسه تمرین بخوانید
در اینجا مثالی از نحوه خواندن یک جلسه تمرین آورده شده است:
suspend fun readExerciseSessions(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
val response =
healthConnectClient.readRecords(
ReadRecordsRequest(
ExerciseSessionRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
for (exerciseRecord in response.records) {
// Process each exercise record
// Optionally pull in with other data sources of the same time range.
val distanceRecord =
healthConnectClient
.readRecords(
ReadRecordsRequest(
DistanceRecord::class,
timeRangeFilter =
TimeRangeFilter.between(
exerciseRecord.startTime,
exerciseRecord.endTime
)
)
)
.records
}
}
نوشتن دادههای زیرنوع
جلسات همچنین میتوانند شامل دادههای زیرنوع اختیاری باشند که جلسه را با اطلاعات اضافی غنی میکنند.
برای مثال، جلسات تمرین میتوانند شامل کلاسهای ExerciseSegment
، ExerciseLap
و ExerciseRoute
باشند:
val segments = listOf(
ExerciseSegment(
startTime = Instant.parse("2022-01-02T10:10:10Z"),
endTime = Instant.parse("2022-01-02T10:10:13Z"),
segmentType = ActivitySegmentType.BENCH_PRESS,
repetitions = 373
)
)
val laps = listOf(
ExerciseLap(
startTime = Instant.parse("2022-01-02T10:10:10Z"),
endTime = Instant.parse("2022-01-02T10:10:13Z"),
length = 0.meters
)
)
ExerciseSessionRecord(
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_CALISTHENICS,
startTime = Instant.parse("2022-01-02T10:10:10Z"),
endTime = Instant.parse("2022-01-02T10:10:13Z"),
startZoneOffset = ZoneOffset.UTC,
endZoneOffset = ZoneOffset.UTC,
segments = segments,
laps = laps,
route = route
)