Health Services از طریق ExerciseClient
پشتیبانی درجه یک برای برنامه های تمرینی ارائه می دهد. با ExerciseClient
، برنامه شما میتواند زمان انجام تمرین را کنترل کند، اهداف تمرینی را اضافه کند و درباره وضعیت ورزش، رویدادهای ورزشی یا سایر معیارهای مورد نظر بهروزرسانی دریافت کند. برای کسب اطلاعات بیشتر، لیست کامل انواع ورزش را که Health Services پشتیبانی می کند، ببینید.
نمونه تمرین را در GitHub ببینید.
وابستگی ها را اضافه کنید
برای افزودن وابستگی به خدمات سلامت، باید مخزن Google Maven را به پروژه خود اضافه کنید. برای اطلاعات بیشتر، به مخزن Maven Google مراجعه کنید.
سپس، در فایل build.gradle
در سطح ماژول، وابستگی زیر را اضافه کنید:
شیار
dependencies { implementation "androidx.health:health-services-client:1.1.0-alpha03" }
کاتلین
dependencies { implementation("androidx.health:health-services-client:1.1.0-alpha03") }
ساختار برنامه
هنگام ساختن یک برنامه ورزشی با خدمات بهداشتی، از ساختار برنامه زیر استفاده کنید:
- صفحه نمایش و پیمایش خود را در یک فعالیت اصلی نگه دارید.
- وضعیت تمرین، دادههای حسگر، فعالیتهای در حال انجام و دادهها را با یک سرویس پیشزمینه مدیریت کنید.
- داده ها را با Room ذخیره کنید و از WorkManager برای آپلود داده ها استفاده کنید.
هنگام آماده شدن برای تمرین و در طول تمرین، ممکن است فعالیت شما به دلایل مختلفی متوقف شود. کاربر ممکن است به برنامه دیگری تغییر مکان دهد یا به صفحه ساعت بازگردد. ممکن است سیستم چیزی در بالای فعالیت شما نمایش دهد، یا ممکن است صفحه بعد از مدتی عدم فعالیت خاموش شود. از یک ForegroundService
به طور مداوم در حال اجرا همراه با ExerciseClient
استفاده کنید تا از عملکرد صحیح برای کل تمرین اطمینان حاصل کنید.
استفاده از ForegroundService
به شما امکان میدهد از API فعالیت مداوم برای نشان دادن نشانگر روی سطوح ساعت خود استفاده کنید و به کاربر اجازه میدهد به سرعت به تمرین بازگردد.
ضروری است که اطلاعات مکان را به طور مناسب در سرویس پیش زمینه خود درخواست کنید. در فایل مانیفست خود، انواع خدمات پیش زمینه و مجوزهای لازم را مشخص کنید:
<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>
از AmbientLifecycleObserver
برای فعالیت قبل از تمرین خود استفاده کنید، که حاوی فراخوانی prepareExercise()
و برای فعالیت تمرینی شماست. با این حال، نمایشگر را در حین تمرین در حالت محیطی بهروزرسانی نکنید: این به این دلیل است که خدمات بهداشتی زمانی که صفحه دستگاه در حالت محیطی است برای صرفهجویی در مصرف انرژی، دادههای تمرین را دستهبندی میکند، بنابراین ممکن است اطلاعات نمایش دادهشده جدید نباشد. در طول تمرین، داده هایی را نشان دهید که برای کاربر منطقی است، یا اطلاعات به روز یا یک صفحه خالی نمایش داده می شود.
بررسی قابلیت ها
هر ExerciseType
از انواع داده های خاصی برای معیارها و اهداف تمرین پشتیبانی می کند. این قابلیت ها را هنگام راه اندازی بررسی کنید، زیرا بسته به دستگاه می توانند متفاوت باشند. ممکن است یک دستگاه از نوع تمرین خاصی پشتیبانی نکند، یا ممکن است عملکرد خاصی مانند توقف خودکار را پشتیبانی نکند. علاوه بر این، قابلیت های یک دستگاه ممکن است در طول زمان تغییر کند، مانند پس از به روز رسانی نرم افزار.
هنگام راه اندازی برنامه، قابلیت های دستگاه را پرس و جو کنید و موارد زیر را ذخیره و پردازش کنید:
- تمریناتی که پلتفرم پشتیبانی می کند.
- ویژگی هایی که برای هر تمرین پشتیبانی می شود.
- انواع داده های پشتیبانی شده برای هر تمرین.
- مجوزهای مورد نیاز برای هر یک از آن انواع داده ها.
از ExerciseCapabilities.getExerciseTypeCapabilities()
با نوع تمرین مورد نظر خود استفاده کنید تا ببینید چه نوع معیارهایی را می توانید درخواست کنید، چه اهداف ورزشی را می توانید پیکربندی کنید، و چه ویژگی های دیگری برای آن نوع موجود است. این در مثال زیر نشان داده شده است:
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)
}
}
در داخل ExerciseTypeCapabilities
بازگشتی، supportedDataTypes
انواع دادههایی را فهرست میکند که میتوانید برای آنها داده درخواست کنید. این در دستگاه متفاوت است، بنابراین مراقب باشید که DataType
درخواست نکنید که پشتیبانی نمی شود، در غیر این صورت ممکن است درخواست شما با شکست مواجه شود.
از فیلدهای supportedGoals
و supportedMilestones
برای تعیین اینکه آیا تمرین می تواند از هدف تمرینی که می خواهید ایجاد کنید پشتیبانی کند یا خیر استفاده کنید.
اگر برنامه شما به کاربر اجازه می دهد از توقف خودکار استفاده کند، باید بررسی کنید که این عملکرد توسط دستگاه با استفاده از supportsAutoPauseAndResume
پشتیبانی می شود. ExerciseClient
درخواست هایی را که در دستگاه پشتیبانی نمی شوند رد می کند.
مثال زیر پشتیبانی از نوع داده HEART_RATE_BPM
، قابلیت هدف STEPS_TOTAL
و عملکرد توقف خودکار را بررسی میکند:
// 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
برای به روز رسانی وضعیت ورزش ثبت نام کنید
به روز رسانی های تمرین به شنونده تحویل داده می شود. برنامه شما میتواند هر بار فقط یک شنونده را ثبت کند. همانطور که در مثال زیر نشان داده شده است، قبل از شروع تمرین شنونده خود را تنظیم کنید. شنونده شما فقط بهروزرسانیهایی را درباره تمرینهایی که برنامهتان متعلق به شماست دریافت میکند.
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)
طول عمر تمرین را مدیریت کنید
Health Services حداکثر از یک تمرین در هر زمان در همه برنامههای روی دستگاه پشتیبانی میکند. اگر تمرینی در حال ردیابی باشد و برنامه دیگری شروع به ردیابی یک تمرین جدید کند، اولین تمرین خاتمه می یابد.
قبل از شروع ورزش، موارد زیر را انجام دهید:
- بررسی کنید که آیا یک تمرین از قبل ردیابی شده است یا خیر، و مطابق با آن واکنش نشان دهید. به عنوان مثال، قبل از لغو تمرین قبلی و شروع به ردیابی تمرین جدید، از کاربر تأیید بخواهید.
مثال زیر نحوه بررسی یک تمرین موجود با 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.
}
}
مجوزها
هنگام استفاده از ExerciseClient
، مطمئن شوید که برنامه شما مجوزهای لازم را درخواست کرده و حفظ می کند. اگر برنامه شما از داده های LOCATION
استفاده می کند، مطمئن شوید که برنامه شما مجوزهای مناسب را نیز برای آن درخواست کرده و حفظ می کند.
برای همه انواع داده، قبل از فراخوانی prepareExercise()
یا startExercise()
موارد زیر را انجام دهید:
- مجوزهای مناسب را برای انواع داده درخواستی در فایل
AndroidManifest.xml
خود مشخص کنید. - بررسی کنید که کاربر مجوزهای لازم را داده است. برای اطلاعات بیشتر، به درخواست مجوزهای برنامه مراجعه کنید. اگر مجوزهای لازم قبلاً داده نشده باشد، خدمات درمانی درخواست را رد می کند.
برای اطلاعات مکان، مراحل اضافی زیر را انجام دهید:
- بررسی کنید که GPS با استفاده از
isProviderEnabled(LocationManager.GPS_PROVIDER)
روی دستگاه فعال باشد. از کاربر بخواهید در صورت لزوم تنظیمات مکان را باز کند. - مطمئن شوید که یک
ForegroundService
باforegroundServiceType
مناسب در طول تمرین حفظ می شود.
برای یک تمرین آماده شوید
برخی از حسگرها، مانند GPS یا ضربان قلب، ممکن است مدت کوتاهی طول بکشد تا گرم شوند، یا ممکن است کاربر بخواهد قبل از شروع تمرین، اطلاعات خود را ببیند. روش اختیاری prepareExerciseAsync()
به این حسگرها اجازه میدهد تا بدون شروع تایمر تمرین گرم شوند و دادهها دریافت شوند. activeDuration
تحت تأثیر این زمان آماده سازی قرار نمی گیرد.
قبل از برقراری تماس برای prepareExerciseAsync()
، موارد زیر را بررسی کنید:
تنظیم موقعیت مکانی در سطح پلت فرم را بررسی کنید. کاربر این تنظیم را در منوی تنظیمات اصلی کنترل می کند. با بررسی مجوزهای سطح برنامه متفاوت است.
اگر تنظیم خاموش است، به کاربر اطلاع دهید که دسترسی به مکان را رد کرده است، و از او بخواهید در صورتی که برنامه شما به موقعیت مکانی نیاز دارد، آن را فعال کند.
تأیید کنید که برنامه شما دارای مجوزهای زمان اجرا برای حسگرهای بدن، تشخیص فعالیت و مکان دقیق است. برای مجوزهای از دست رفته، از کاربر بخواهید مجوزهای زمان اجرا را دریافت کند و زمینه کافی را فراهم کند. اگر کاربر مجوز خاصی اعطا نمی کند، انواع داده های مرتبط با آن مجوز را از فراخوانی
prepareExerciseAsync()
حذف کنید. اگر مجوزهای حسگر بدن و موقعیت مکانی داده نشده است، باprepareExerciseAsync()
تماس نگیرید، زیرا تماس آماده به طور خاص برای به دست آوردن ضربان قلب ثابت یا اصلاح GPS قبل از شروع تمرین است. این برنامه همچنان میتواند فاصله، سرعت، سرعت و سایر معیارهایی را که به آن مجوزها نیاز ندارند، بر اساس گام دریافت کند.
برای اطمینان از موفقیت آمیز بودن فراخوانی برای prepareExerciseAsync()
موارد زیر را انجام دهید:
- از
AmbientLifecycleObserver
برای فعالیت قبل از تمرین که حاوی تماس آماده است استفاده کنید. - از سرویس پیش زمینه خود
prepareExerciseAsync()
فراخوانی کنید. اگر در سرویس نباشد و با چرخه حیات فعالیت مرتبط باشد، ممکن است آماده سازی حسگر به طور غیر ضروری از بین برود. - برای خاموش کردن حسگرها و کاهش مصرف انرژی اگر کاربر از فعالیت قبل از تمرین دور شد،
endExercise()
فراخوانی کنید.
مثال زیر نحوه فراخوانی prepareExerciseAsync()
نشان می دهد:
val warmUpConfig = WarmUpConfig(
ExerciseType.RUNNING,
setOf(
DataType.HEART_RATE_BPM,
DataType.LOCATION
)
)
// Only necessary to call prepareExerciseAsync if body sensor or location
//permissions are given
exerciseClient.prepareExerciseAsync(warmUpConfig).await()
// Data and availability updates are delivered to the registered listener.
هنگامی که برنامه در حالت PREPARING
قرار گرفت، به روز رسانی های در دسترس بودن حسگر در ExerciseUpdateCallback
از طریق onAvailabilityChanged()
ارائه می شود. سپس این اطلاعات می تواند به کاربر ارائه شود تا بتواند تصمیم بگیرد که آیا تمرین خود را شروع کند یا خیر.
تمرین را شروع کنید
وقتی میخواهید تمرینی را شروع کنید، یک ExerciseConfig
ایجاد کنید تا نوع تمرین، انواع دادههایی که میخواهید معیارها را برای آنها دریافت کنید، و اهداف یا نقاط عطف تمرین را پیکربندی کنید.
اهداف تمرین شامل یک DataType
و یک شرط است. اهداف تمرینی یک هدف یکباره هستند که با برآورده شدن یک شرط، مانند زمانی که کاربر مسافت خاصی را می دود، ایجاد می شوند. یک نقطه عطف تمرین نیز می تواند تعیین شود. نقاط عطف تمرین را می توان چندین بار فعال کرد، مانند هر بار که کاربر یک نقطه مشخص را از فاصله تعیین شده خود عبور می دهد.
نمونه زیر نحوه ایجاد یک هدف از هر نوع را نشان می دهد:
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()
}
همچنین میتوانید دور تمام تمرینها را علامت بزنید. Health Services یک ExerciseLapSummary
با معیارهای جمع آوری شده در طول دوره ارائه می دهد.
مثال قبلی استفاده از isGpsEnabled
را نشان میدهد که هنگام درخواست دادههای مکان باید درست باشد. با این حال، استفاده از GPS می تواند به سایر معیارها نیز کمک کند. اگر ExerciseConfig
فاصله را به عنوان DataType
مشخص کند، به طور پیشفرض از مراحل برای تخمین فاصله استفاده میکند. با فعال کردن اختیاری GPS، میتوان از اطلاعات موقعیت مکانی برای تخمین مسافت استفاده کرد.
تمرین را مکث کنید، از سر بگیرید و پایان دهید
میتوانید با استفاده از روشهای مناسب، مانند pauseExerciseAsync()
یا endExerciseAsync()
تمرینات را مکث، از سرگیری و پایان دهید.
از حالت ExerciseUpdate
به عنوان منبع حقیقت استفاده کنید. هنگامی که فراخوانی به pauseExerciseAsync()
برمیگردد، تمرین متوقف شده در نظر گرفته نمیشود، بلکه زمانی که آن حالت در پیام ExerciseUpdate
منعکس میشود. وقتی صحبت از حالت های رابط کاربری به میان می آید، توجه به این موضوع بسیار مهم است. اگر کاربر pause را فشار داد، دکمه مکث را غیرفعال کنید و pauseExerciseAsync()
را در Health Services فراخوانی کنید. منتظر بمانید تا Health Services با استفاده از ExerciseUpdate.exerciseStateInfo.state
به حالت توقف برسد و سپس دکمه را تغییر دهید تا از سر گرفته شود. این به این دلیل است که تحویل بهروزرسانیهای وضعیت خدمات بهداشتی ممکن است بیشتر از فشار دکمه طول بکشد، بنابراین اگر همه تغییرات رابط کاربری را به فشار دکمهها متصل کنید، رابط کاربری میتواند با وضعیت خدمات بهداشتی هماهنگ نشود.
این را در شرایط زیر در نظر داشته باشید:
- مکث خودکار فعال است: تمرین می تواند بدون تعامل کاربر متوقف شود یا شروع شود.
- برنامه دیگری تمرینی را شروع می کند: ممکن است تمرین شما بدون تعامل کاربر خاتمه یابد.
اگر برنامه تمرینی برنامه شما توسط برنامه دیگری خاتمه یابد، برنامه شما باید با ظرافت این خاتمه را انجام دهد:
- حالت تمرین جزئی را ذخیره کنید تا پیشرفت کاربر پاک نشود.
- نماد «فعالیت در حال انجام» را بردارید و یک اعلان برای کاربر ارسال کنید تا بداند تمرینش توسط برنامه دیگری به پایان رسیده است.
همچنین، به مواردی رسیدگی کنید که مجوزها در طول یک تمرین مداوم لغو شوند. این با استفاده از حالت isEnded
، با ExerciseEndReason
AUTO_END_PERMISSION_LOST
ارسال میشود. این مورد را به روشی مشابه با پرونده پایان رسیدگی کنید: حالت جزئی را ذخیره کنید، نماد فعالیت در حال انجام را بردارید، و یک اعلان در مورد آنچه برای کاربر اتفاق افتاده است ارسال کنید.
مثال زیر نحوه بررسی صحیح فسخ را نشان می دهد:
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
}
...
}
...
}
مدت زمان فعال را مدیریت کنید
در طول تمرین، یک برنامه می تواند مدت زمان فعال تمرین را نمایش دهد. برنامه، خدمات بهداشتی و واحد میکروکنترلر دستگاه (MCU) - پردازنده کم مصرفی که مسئول ردیابی ورزش است - همگی باید با مدت زمان فعال فعلی هماهنگ باشند. برای کمک به مدیریت این موضوع، Health Services یک ActiveDurationCheckpoint
ارسال می کند که یک نقطه لنگر را ارائه می دهد که برنامه می تواند تایمر خود را از آنجا شروع کند.
از آنجایی که مدت زمان فعال از MCU ارسال می شود و ممکن است زمان کمی طول بکشد تا به برنامه برسد، ActiveDurationCheckpoint
دارای دو ویژگی است:
-
activeDuration
: مدت زمانی است که تمرین فعال بوده است -
time
: زمانی که مدت زمان فعال محاسبه شد
بنابراین، در برنامه، مدت زمان فعال یک تمرین را می توان از طریق ActiveDurationCheckpoint
با استفاده از معادله زیر محاسبه کرد:
(اکنون() - checkpoint.time) + checkpoint.activeDuration
این دلتای کوچک بین مدت زمان فعال محاسبه شده در MCU و رسیدن به برنامه را به حساب می آورد. این می تواند برای ایجاد یک کرونومتر در برنامه استفاده شود و به اطمینان حاصل شود که تایمر برنامه کاملاً با زمان در خدمات بهداشتی و MCU هماهنگ است.
اگر تمرین متوقف شود، برنامه منتظر میماند تا تایمر را در رابط کاربری مجدداً راهاندازی کند تا زمانی که زمان محاسبهشده از آنچه که رابط کاربری در حال حاضر نشان میدهد گذشته باشد. این به این دلیل است که سیگنال مکث با کمی تاخیر به خدمات بهداشتی و MCU می رسد. برای مثال، اگر برنامه در t=10 ثانیه متوقف شود، ممکن است Health Services بهروزرسانی PAUSED
را تا t=10.2 ثانیه به برنامه تحویل ندهد.
با داده های ExerciseClient کار کنید
معیارهای مربوط به انواع داده هایی که برنامه شما برای آنها ثبت کرده است در پیام های ExerciseUpdate
ارائه می شود.
پردازشگر پیامها را فقط در حالت بیدار یا زمانی که به حداکثر دوره گزارشدهی رسیده است، مانند هر 150 ثانیه ارسال میکند. برای پیشبرد کرنومتر با activeDuration
به فرکانس ExerciseUpdate
تکیه نکنید. برای نمونه ای از نحوه پیاده سازی یک کرنومتر مستقل ، نمونه تمرین را در GitHub ببینید.
وقتی کاربر تمرینی را شروع میکند، پیامهای ExerciseUpdate
را میتوان به طور مکرر مانند هر ثانیه ارسال کرد. وقتی کاربر تمرین را شروع می کند، ممکن است صفحه نمایش خاموش شود. سپس سرویسهای بهداشتی میتوانند دادهها را کمتر تحویل دهند، اما همچنان با همان فرکانس نمونهبرداری میشوند تا از بیدار شدن پردازنده اصلی جلوگیری شود. هنگامی که کاربر به صفحه نمایش نگاه می کند، هر داده ای که در حال دسته بندی است بلافاصله به برنامه شما تحویل داده می شود.
نرخ بچینگ را کنترل کنید
در برخی سناریوها، ممکن است بخواهید فرکانس دریافت انواع داده های خاص را در حالی که صفحه نمایش خاموش است، کنترل کنید. یک شیء BatchingMode
به برنامه شما اجازه میدهد تا رفتار دستهبندی پیشفرض را لغو کند تا دادهها را به دفعات بیشتری دریافت کند.
برای تنظیم نرخ بچینگ، مراحل زیر را انجام دهید:
بررسی کنید که آیا تعریف
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 }
مشخص کنید که شی
ExerciseConfig
باید از یکBatchingMode
خاص استفاده کند، همانطور که در قطعه کد زیر نشان داده شده است.val config = ExerciseConfig( exerciseType = ExerciseType.WORKOUT, dataTypes = setOf( DataType.HEART_RATE_BPM, DataType.TOTAL_CALORIES ), // ... batchingModeOverrides = setOf(BatchingMode.HEART_RATE_5_SECONDS) )
به صورت اختیاری، میتوانید بهصورت پویا
BatchingMode
در طول تمرین پیکربندی کنید، بهجای اینکه یک رفتار دستهای خاص در طول مدت تمرین ادامه داشته باشد:val desiredModes = setOf(BatchingMode.HEART_RATE_5_SECONDS) exerciseClient.overrideBatchingModesForActiveExercise(desiredModes)
برای پاک کردن
BatchingMode
سفارشیسازیشده و بازگشت به رفتار پیشفرض، یک مجموعه خالی را درexerciseClient.overrideBatchingModesForActiveExercise()
ارسال کنید.
مهر زمانی
نقطه در زمان هر نقطه داده نشان دهنده مدت زمانی است که دستگاه بوت شده است. برای تبدیل آن به زمان، موارد زیر را انجام دهید:
val bootInstant =
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
سپس این مقدار را می توان با getStartInstant()
یا getEndInstant()
برای هر نقطه داده استفاده کرد.
دقت داده ها
برخی از انواع داده ها می توانند اطلاعات صحت مرتبط با هر نقطه داده را داشته باشند. این در ویژگی accuracy
نشان داده شده است.
کلاسهای HrAccuracy
و LocationAccuracy
را میتوان به ترتیب برای انواع دادههای HEART_RATE_BPM
و LOCATION
پر کرد. در صورت وجود، از ویژگی accuracy
برای تعیین اینکه آیا هر نقطه داده از دقت کافی برای برنامه شما برخوردار است استفاده کنید.
ذخیره و آپلود داده ها
از اتاق برای تداوم داده های ارائه شده از خدمات بهداشتی استفاده کنید. آپلود داده ها در پایان تمرین با استفاده از مکانیزمی مانند Work Manager انجام می شود. این تضمین میکند که تماسهای شبکه برای آپلود دادهها تا پایان تمرین به تعویق میافتد، مصرف برق را در طول تمرین به حداقل میرساند و کار را ساده میکند.
چک لیست ادغام
قبل از انتشار برنامه خود که از ExerciseClient
از Health Services استفاده می کند، به چک لیست زیر مراجعه کنید تا مطمئن شوید تجربه کاربری شما از برخی مشکلات رایج جلوگیری می کند. تایید کنید که:
- برنامه شما هر بار که برنامه اجرا می شود ، قابلیت های نوع تمرین و قابلیت های دستگاه را بررسی می کند . به این ترتیب، می توانید تشخیص دهید که یک دستگاه یا تمرین خاص از یکی از انواع داده های مورد نیاز برنامه شما پشتیبانی نمی کند.
- شما مجوزهای لازم را درخواست و حفظ می کنید و آنها را در فایل مانیفست خود مشخص می کنید. قبل از فراخوانی
prepareExerciseAsync()
، برنامه شما تأیید می کند که مجوزهای زمان اجرا داده شده است. - برنامه شما از
getCurrentExerciseInfoAsync()
برای رسیدگی به موارد زیر استفاده می کند:- یک تمرین از قبل در حال پیگیری است و برنامه شما تمرین قبلی را لغو می کند.
- برنامه دیگری تمرین شما را خاتمه داده است. این ممکن است زمانی اتفاق بیفتد که کاربر دوباره برنامه را باز می کند، با پیامی مواجه می شود که توضیح می دهد تمرین متوقف شده است زیرا برنامه دیگری کنترل را به دست گرفته است.
- اگر از داده های
LOCATION
استفاده می کنید:- برنامه شما یک
ForegroundService
باforegroundServiceType
مربوطه را در طول مدت تمرین (از جمله تماس آماده) حفظ می کند. - بررسی کنید که GPS با استفاده از
isProviderEnabled(LocationManager.GPS_PROVIDER)
در دستگاه فعال باشد و در صورت لزوم از کاربر می خواهد تنظیمات مکان را باز کند. - برای موارد استفاده سخت، که دریافت دادههای مکان با تأخیر کم اهمیت زیادی دارد، یکپارچهسازی ارائهدهنده مکان فیوز شده (FLP) و استفاده از دادههای آن بهعنوان یک اصلاح مکان اولیه را در نظر بگیرید. هنگامی که اطلاعات مکان پایدارتری از خدمات بهداشتی در دسترس است، به جای FLP از آن استفاده کنید.
- برنامه شما یک
- اگر برنامه شما به آپلود داده نیاز دارد، هر تماس شبکه برای آپلود داده تا پایان تمرین به تعویق میافتد. در غیر این صورت، در طول تمرین، برنامه شما هر گونه تماس شبکه ضروری را به ندرت انجام می دهد.
برای شما توصیه می شود
- توجه: وقتی جاوا اسکریپت خاموش است، متن پیوند نمایش داده می شود
- به روز رسانی داده های غیرفعال
- خدمات بهداشتی در Wear OS
- با کاشی شروع کنید
Health Services از طریق ExerciseClient
پشتیبانی درجه یک برای برنامه های تمرینی ارائه می دهد. با ExerciseClient
، برنامه شما میتواند زمان انجام تمرین را کنترل کند، اهداف تمرینی را اضافه کند و درباره وضعیت ورزش، رویدادهای ورزشی یا سایر معیارهای مورد نظر بهروزرسانی دریافت کند. برای کسب اطلاعات بیشتر، لیست کامل انواع ورزش را که Health Services پشتیبانی می کند، ببینید.
نمونه تمرین را در GitHub ببینید.
وابستگی ها را اضافه کنید
برای افزودن وابستگی به خدمات سلامت، باید مخزن Google Maven را به پروژه خود اضافه کنید. برای اطلاعات بیشتر، به مخزن Maven Google مراجعه کنید.
سپس، در فایل build.gradle
در سطح ماژول، وابستگی زیر را اضافه کنید:
شیار
dependencies { implementation "androidx.health:health-services-client:1.1.0-alpha03" }
کاتلین
dependencies { implementation("androidx.health:health-services-client:1.1.0-alpha03") }
ساختار برنامه
هنگام ساختن یک برنامه ورزشی با خدمات بهداشتی، از ساختار برنامه زیر استفاده کنید:
- صفحه نمایش و پیمایش خود را در یک فعالیت اصلی نگه دارید.
- وضعیت تمرین، دادههای حسگر، فعالیتهای در حال انجام و دادهها را با یک سرویس پیشزمینه مدیریت کنید.
- داده ها را با Room ذخیره کنید و از WorkManager برای آپلود داده ها استفاده کنید.
هنگام آماده شدن برای تمرین و در طول تمرین، ممکن است فعالیت شما به دلایل مختلفی متوقف شود. کاربر ممکن است به برنامه دیگری تغییر مکان دهد یا به صفحه ساعت بازگردد. ممکن است سیستم چیزی در بالای فعالیت شما نمایش دهد، یا ممکن است صفحه بعد از مدتی عدم فعالیت خاموش شود. از یک ForegroundService
به طور مداوم در حال اجرا همراه با ExerciseClient
استفاده کنید تا از عملکرد صحیح برای کل تمرین اطمینان حاصل کنید.
استفاده از ForegroundService
به شما امکان میدهد از API فعالیت مداوم برای نشان دادن نشانگر روی سطوح ساعت خود استفاده کنید و به کاربر اجازه میدهد به سرعت به تمرین بازگردد.
ضروری است که اطلاعات مکان را به طور مناسب در سرویس پیش زمینه خود درخواست کنید. در فایل مانیفست خود، انواع خدمات پیش زمینه و مجوزهای لازم را مشخص کنید:
<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>
از AmbientLifecycleObserver
برای فعالیت قبل از تمرین خود استفاده کنید، که حاوی فراخوانی prepareExercise()
و برای فعالیت تمرینی شماست. با این حال، نمایشگر را در حین تمرین در حالت محیطی بهروزرسانی نکنید: این به این دلیل است که خدمات بهداشتی زمانی که صفحه دستگاه در حالت محیطی است برای صرفهجویی در مصرف انرژی، دادههای تمرین را دستهبندی میکند، بنابراین ممکن است اطلاعات نمایش دادهشده جدید نباشد. در طول تمرین، داده هایی را نشان دهید که برای کاربر منطقی است، یا اطلاعات به روز یا یک صفحه خالی نمایش داده می شود.
بررسی قابلیت ها
هر ExerciseType
از انواع داده های خاصی برای معیارها و اهداف تمرین پشتیبانی می کند. این قابلیت ها را هنگام راه اندازی بررسی کنید، زیرا بسته به دستگاه می توانند متفاوت باشند. ممکن است یک دستگاه از نوع تمرین خاصی پشتیبانی نکند، یا ممکن است عملکرد خاصی مانند توقف خودکار را پشتیبانی نکند. علاوه بر این، قابلیت های یک دستگاه ممکن است در طول زمان تغییر کند، مانند پس از به روز رسانی نرم افزار.
هنگام راه اندازی برنامه، قابلیت های دستگاه را پرس و جو کنید و موارد زیر را ذخیره و پردازش کنید:
- تمریناتی که پلتفرم پشتیبانی می کند.
- ویژگی هایی که برای هر تمرین پشتیبانی می شود.
- انواع داده های پشتیبانی شده برای هر تمرین.
- مجوزهای مورد نیاز برای هر یک از آن انواع داده ها.
از ExerciseCapabilities.getExerciseTypeCapabilities()
با نوع تمرین مورد نظر خود استفاده کنید تا ببینید چه نوع معیارهایی را می توانید درخواست کنید، چه اهداف ورزشی را می توانید پیکربندی کنید، و چه ویژگی های دیگری برای آن نوع موجود است. این در مثال زیر نشان داده شده است:
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)
}
}
در داخل ExerciseTypeCapabilities
بازگشتی، supportedDataTypes
انواع دادههایی را فهرست میکند که میتوانید برای آنها داده درخواست کنید. این در دستگاه متفاوت است، بنابراین مراقب باشید که DataType
درخواست نکنید که پشتیبانی نمی شود، در غیر این صورت ممکن است درخواست شما با شکست مواجه شود.
از فیلدهای supportedGoals
و supportedMilestones
برای تعیین اینکه آیا تمرین می تواند از هدف تمرینی که می خواهید ایجاد کنید پشتیبانی کند یا خیر استفاده کنید.
اگر برنامه شما به کاربر اجازه می دهد از توقف خودکار استفاده کند، باید بررسی کنید که این عملکرد توسط دستگاه با استفاده از supportsAutoPauseAndResume
پشتیبانی می شود. ExerciseClient
درخواست هایی را که در دستگاه پشتیبانی نمی شوند رد می کند.
مثال زیر پشتیبانی از نوع داده HEART_RATE_BPM
، قابلیت هدف STEPS_TOTAL
و عملکرد توقف خودکار را بررسی میکند:
// 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
برای به روز رسانی وضعیت ورزش ثبت نام کنید
به روز رسانی های تمرین به شنونده تحویل داده می شود. برنامه شما میتواند هر بار فقط یک شنونده را ثبت کند. همانطور که در مثال زیر نشان داده شده است، قبل از شروع تمرین شنونده خود را تنظیم کنید. شنونده شما فقط بهروزرسانیهایی را درباره تمرینهایی که برنامهتان متعلق به شماست دریافت میکند.
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)
طول عمر تمرین را مدیریت کنید
Health Services حداکثر از یک تمرین در هر زمان در همه برنامههای روی دستگاه پشتیبانی میکند. اگر تمرینی در حال ردیابی باشد و برنامه دیگری شروع به ردیابی یک تمرین جدید کند، اولین تمرین خاتمه می یابد.
قبل از شروع ورزش، موارد زیر را انجام دهید:
- بررسی کنید که آیا یک تمرین از قبل ردیابی شده است یا خیر، و مطابق با آن واکنش نشان دهید. به عنوان مثال، قبل از لغو تمرین قبلی و شروع به ردیابی تمرین جدید، از کاربر تأیید بخواهید.
مثال زیر نحوه بررسی یک تمرین موجود با 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.
}
}
مجوزها
هنگام استفاده از ExerciseClient
، مطمئن شوید که برنامه شما مجوزهای لازم را درخواست کرده و حفظ می کند. اگر برنامه شما از داده های LOCATION
استفاده می کند، مطمئن شوید که برنامه شما مجوزهای مناسب را نیز برای آن درخواست کرده و حفظ می کند.
برای همه انواع داده، قبل از فراخوانی prepareExercise()
یا startExercise()
موارد زیر را انجام دهید:
- مجوزهای مناسب را برای انواع داده درخواستی در فایل
AndroidManifest.xml
خود مشخص کنید. - بررسی کنید که کاربر مجوزهای لازم را داده است. برای اطلاعات بیشتر، به درخواست مجوزهای برنامه مراجعه کنید. اگر مجوزهای لازم قبلاً داده نشده باشد، خدمات درمانی درخواست را رد می کند.
برای اطلاعات مکان، مراحل اضافی زیر را انجام دهید:
- بررسی کنید که GPS با استفاده از
isProviderEnabled(LocationManager.GPS_PROVIDER)
روی دستگاه فعال باشد. از کاربر بخواهید در صورت لزوم تنظیمات مکان را باز کند. - مطمئن شوید که یک
ForegroundService
باforegroundServiceType
مناسب در طول تمرین حفظ می شود.
برای یک تمرین آماده شوید
برخی از حسگرها، مانند GPS یا ضربان قلب، ممکن است مدت کوتاهی طول بکشد تا گرم شوند، یا ممکن است کاربر بخواهد قبل از شروع تمرین، اطلاعات خود را ببیند. روش اختیاری prepareExerciseAsync()
به این حسگرها اجازه میدهد تا بدون شروع تایمر تمرین گرم شوند و دادهها دریافت شوند. activeDuration
تحت تأثیر این زمان آماده سازی قرار نمی گیرد.
قبل از برقراری تماس برای prepareExerciseAsync()
، موارد زیر را بررسی کنید:
تنظیم موقعیت مکانی در سطح پلت فرم را بررسی کنید. کاربر این تنظیم را در منوی تنظیمات اصلی کنترل می کند. با بررسی مجوزهای سطح برنامه متفاوت است.
اگر تنظیم خاموش است، به کاربر اطلاع دهید که دسترسی به مکان را رد کرده است، و از او بخواهید در صورتی که برنامه شما به موقعیت مکانی نیاز دارد، آن را فعال کند.
تأیید کنید که برنامه شما دارای مجوزهای زمان اجرا برای حسگرهای بدن، تشخیص فعالیت و مکان دقیق است. برای مجوزهای از دست رفته، از کاربر بخواهید مجوزهای زمان اجرا را دریافت کند و زمینه کافی را فراهم کند. اگر کاربر مجوز خاصی اعطا نمی کند، انواع داده های مرتبط با آن مجوز را از فراخوانی
prepareExerciseAsync()
حذف کنید. اگر مجوزهای حسگر بدن و موقعیت مکانی داده نشده است، باprepareExerciseAsync()
تماس نگیرید، زیرا تماس آماده به طور خاص برای به دست آوردن ضربان قلب ثابت یا اصلاح GPS قبل از شروع تمرین است. این برنامه همچنان میتواند فاصله، سرعت، سرعت و سایر معیارهایی را که به آن مجوزها نیاز ندارند، بر اساس گام دریافت کند.
برای اطمینان از موفقیت آمیز بودن فراخوانی برای prepareExerciseAsync()
موارد زیر را انجام دهید:
- از
AmbientLifecycleObserver
برای فعالیت قبل از تمرین که حاوی تماس آماده است استفاده کنید. - از سرویس پیش زمینه خود
prepareExerciseAsync()
فراخوانی کنید. اگر در سرویس نباشد و با چرخه حیات فعالیت مرتبط باشد، ممکن است آماده سازی حسگر به طور غیر ضروری از بین برود. - برای خاموش کردن حسگرها و کاهش مصرف انرژی اگر کاربر از فعالیت قبل از تمرین دور شد،
endExercise()
فراخوانی کنید.
مثال زیر نحوه فراخوانی prepareExerciseAsync()
نشان می دهد:
val warmUpConfig = WarmUpConfig(
ExerciseType.RUNNING,
setOf(
DataType.HEART_RATE_BPM,
DataType.LOCATION
)
)
// Only necessary to call prepareExerciseAsync if body sensor or location
//permissions are given
exerciseClient.prepareExerciseAsync(warmUpConfig).await()
// Data and availability updates are delivered to the registered listener.
هنگامی که برنامه در حالت PREPARING
قرار گرفت، به روز رسانی های در دسترس بودن حسگر در ExerciseUpdateCallback
از طریق onAvailabilityChanged()
ارائه می شود. سپس این اطلاعات می تواند به کاربر ارائه شود تا بتواند تصمیم بگیرد که آیا تمرین خود را شروع کند یا خیر.
تمرین را شروع کنید
وقتی میخواهید تمرینی را شروع کنید، یک ExerciseConfig
ایجاد کنید تا نوع تمرین، انواع دادههایی که میخواهید معیارها را برای آنها دریافت کنید، و اهداف یا نقاط عطف تمرین را پیکربندی کنید.
اهداف تمرین شامل یک DataType
و یک شرط است. اهداف تمرینی یک هدف یکباره هستند که با برآورده شدن یک شرط، مانند زمانی که کاربر مسافت خاصی را می دود، ایجاد می شوند. یک نقطه عطف تمرین نیز می تواند تعیین شود. نقاط عطف تمرین را می توان چندین بار فعال کرد، مثلاً هر بار که کاربر نقطه خاصی را از فاصله تعیین شده خود می دود.
نمونه زیر نحوه ایجاد یک هدف از هر نوع را نشان می دهد:
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()
}
همچنین می توانید دور تمام تمرینات را علامت بزنید. Health Services یک ExerciseLapSummary
با معیارهای جمع آوری شده در طول دوره ارائه می دهد.
مثال قبلی استفاده از isGpsEnabled
را نشان میدهد که هنگام درخواست دادههای مکان باید درست باشد. با این حال، استفاده از GPS می تواند به سایر معیارها نیز کمک کند. اگر ExerciseConfig
فاصله را به عنوان DataType
مشخص کند، به طور پیشفرض از مراحل برای تخمین فاصله استفاده میکند. با فعال کردن اختیاری GPS، میتوان از اطلاعات موقعیت مکانی برای تخمین مسافت استفاده کرد.
تمرین را مکث کنید، از سر بگیرید و پایان دهید
میتوانید با استفاده از روشهای مناسب، مانند pauseExerciseAsync()
یا endExerciseAsync()
تمرینات را مکث، از سرگیری و پایان دهید.
از حالت ExerciseUpdate
به عنوان منبع حقیقت استفاده کنید. هنگامی که فراخوانی به pauseExerciseAsync()
برمیگردد، تمرین متوقف شده در نظر گرفته نمیشود، بلکه زمانی که آن حالت در پیام ExerciseUpdate
منعکس میشود. وقتی صحبت از حالت های رابط کاربری به میان می آید، توجه به این موضوع بسیار مهم است. اگر کاربر pause را فشار داد، دکمه مکث را غیرفعال کنید و pauseExerciseAsync()
را در Health Services فراخوانی کنید. منتظر بمانید تا Health Services با استفاده از ExerciseUpdate.exerciseStateInfo.state
به حالت توقف برسد و سپس دکمه را تغییر دهید تا از سر گرفته شود. این به این دلیل است که تحویل بهروزرسانیهای وضعیت خدمات بهداشتی ممکن است بیشتر از فشار دکمه طول بکشد، بنابراین اگر همه تغییرات رابط کاربری را به فشار دکمهها متصل کنید، رابط کاربری میتواند با وضعیت خدمات بهداشتی هماهنگ نشود.
این را در شرایط زیر در نظر داشته باشید:
- مکث خودکار فعال است: تمرین می تواند بدون تعامل کاربر متوقف شود یا شروع شود.
- برنامه دیگری تمرینی را شروع می کند: ممکن است تمرین شما بدون تعامل کاربر خاتمه یابد.
اگر برنامه تمرینی برنامه شما توسط برنامه دیگری خاتمه یابد، برنامه شما باید با ظرافت این خاتمه را انجام دهد:
- حالت تمرین جزئی را ذخیره کنید تا پیشرفت کاربر پاک نشود.
- نماد «فعالیت در حال انجام» را بردارید و یک اعلان برای کاربر ارسال کنید تا بداند تمرینش توسط برنامه دیگری به پایان رسیده است.
همچنین، به مواردی رسیدگی کنید که مجوزها در طول یک تمرین مداوم لغو شوند. این با استفاده از وضعیت isEnded
، با ExerciseEndReason
AUTO_END_PERMISSION_LOST
ارسال میشود. این مورد را به روشی مشابه با پرونده پایان رسیدگی کنید: حالت جزئی را ذخیره کنید، نماد فعالیت در حال انجام را بردارید، و یک اعلان در مورد آنچه برای کاربر اتفاق افتاده است ارسال کنید.
مثال زیر نحوه بررسی صحیح فسخ را نشان می دهد:
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
}
...
}
...
}
مدت زمان فعال را مدیریت کنید
در طول تمرین، یک برنامه می تواند مدت زمان فعال تمرین را نمایش دهد. برنامه، خدمات بهداشتی و واحد میکروکنترلر دستگاه (MCU) - پردازنده کم مصرفی که مسئول ردیابی ورزش است - همگی باید با مدت زمان فعال فعلی هماهنگ باشند. برای کمک به مدیریت این، Health Services یک ActiveDurationCheckpoint
ارسال میکند که یک نقطه لنگر را ارائه میکند که برنامه میتواند تایمر خود را از آنجا شروع کند.
از آنجایی که مدت زمان فعال از MCU ارسال می شود و ممکن است زمان کمی طول بکشد تا به برنامه برسد، ActiveDurationCheckpoint
دارای دو ویژگی است:
-
activeDuration
: مدت زمانی است که تمرین فعال بوده است -
time
: زمانی که مدت زمان فعال محاسبه شد
بنابراین، در برنامه، مدت زمان فعال یک تمرین را می توان از طریق ActiveDurationCheckpoint
با استفاده از معادله زیر محاسبه کرد:
(اکنون() - checkpoint.time) + checkpoint.activeDuration
این دلتای کوچک بین مدت زمان فعال محاسبه شده در MCU و رسیدن به برنامه را به حساب می آورد. این می تواند برای ایجاد یک کرونومتر در برنامه استفاده شود و به اطمینان حاصل شود که تایمر برنامه کاملاً با زمان در خدمات بهداشتی و MCU هماهنگ است.
اگر تمرین متوقف شود، برنامه منتظر میماند تا تایمر را در رابط کاربری مجدداً راهاندازی کند تا زمانی که زمان محاسبهشده از آنچه که رابط کاربری در حال حاضر نشان میدهد گذشته باشد. این به این دلیل است که سیگنال مکث با کمی تاخیر به خدمات بهداشتی و MCU می رسد. برای مثال، اگر برنامه در t=10 ثانیه متوقف شود، ممکن است Health Services بهروزرسانی PAUSED
را تا t=10.2 ثانیه به برنامه تحویل ندهد.
با داده های ExerciseClient کار کنید
معیارهای مربوط به انواع داده هایی که برنامه شما برای آنها ثبت کرده است در پیام های ExerciseUpdate
ارائه می شود.
پردازشگر پیامها را فقط در حالت بیدار یا زمانی که به حداکثر دوره گزارشگیری رسیده است، مانند هر 150 ثانیه ارسال میکند. برای پیشبرد کرنومتر با activeDuration
به فرکانس ExerciseUpdate
تکیه نکنید. برای نمونه ای از نحوه پیاده سازی یک کرنومتر مستقل ، نمونه تمرین را در GitHub ببینید.
وقتی کاربر تمرینی را شروع میکند، پیامهای ExerciseUpdate
را میتوان به طور مکرر مانند هر ثانیه ارسال کرد. وقتی کاربر تمرین را شروع می کند، ممکن است صفحه نمایش خاموش شود. سپس سرویسهای بهداشتی میتوانند دادهها را کمتر تحویل دهند، اما همچنان با همان فرکانس نمونهبرداری میشوند تا از بیدار شدن پردازنده اصلی جلوگیری شود. هنگامی که کاربر به صفحه نگاه می کند ، هرگونه داده ای در فرآیند جمع شدن بلافاصله به برنامه شما تحویل داده می شود.
نرخ دسته بندی را کنترل کنید
در برخی از سناریوها ، ممکن است بخواهید فرکانس را کنترل کنید که در آن برنامه شما در حالی که صفحه خاموش است ، انواع خاصی از داده ها را دریافت می کند. یک شیء BatchingMode
به برنامه شما اجازه می دهد تا رفتار پیش فرض دسته بندی را نادیده بگیرد تا بیشتر تحویل داده ها را دریافت کند.
برای پیکربندی نرخ دسته بندی ، مراحل زیر را انجام دهید:
بررسی کنید که آیا تعریف
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 }
مشخص کنید که شیء
ExerciseConfig
باید از یکBatchingMode
خاص استفاده کند ، همانطور که در قطعه کد زیر نشان داده شده است.val config = ExerciseConfig( exerciseType = ExerciseType.WORKOUT, dataTypes = setOf( DataType.HEART_RATE_BPM, DataType.TOTAL_CALORIES ), // ... batchingModeOverrides = setOf(BatchingMode.HEART_RATE_5_SECONDS) )
به صورت اختیاری ، شما می توانید به صورت پویا در طول تمرین
BatchingMode
صورت پویا پیکربندی کنید ، به جای داشتن یک رفتار خاص در طول مدت تمرین ادامه دهید:val desiredModes = setOf(BatchingMode.HEART_RATE_5_SECONDS) exerciseClient.overrideBatchingModesForActiveExercise(desiredModes)
برای پاک کردن mode customized
BatchingMode
و بازگشت به رفتار پیش فرض ، یک مجموعه خالی را بهexerciseClient.overrideBatchingModesForActiveExercise()
.
مهر زمانی
نقطه به زمان هر نقطه داده مدت زمان بوت شدن دستگاه را نشان می دهد. برای تبدیل این کار به یک Timestamp ، موارد زیر را انجام دهید:
val bootInstant =
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
این مقدار می تواند برای هر نقطه داده با getStartInstant()
یا getEndInstant()
استفاده شود.
دقت داده ها
برخی از انواع داده ها می توانند دارای اطلاعات صحت مرتبط با هر نقطه داده باشند. این در خاصیت accuracy
نشان داده شده است.
کلاسهای HrAccuracy
و LocationAccuracy
می توانند به ترتیب برای HEART_RATE_BPM
و انواع داده های LOCATION
جمع شوند. در صورت وجود ، از ویژگی accuracy
استفاده کنید تا مشخص کنید که آیا هر نقطه داده از دقت کافی برای برنامه شما برخوردار است یا خیر.
داده ها را ذخیره و بارگذاری کنید
از اتاق برای ادامه داده های ارائه شده از خدمات درمانی استفاده کنید. بارگذاری داده ها در پایان تمرین با استفاده از مکانیسمی مانند مدیر کار اتفاق می افتد. این تضمین می کند که تماس های شبکه برای بارگذاری داده ها تا پایان تمرین به تعویق می افتد ، به حداقل رساندن مصرف برق در طول تمرین و ساده سازی کار.
لیست چک
قبل از انتشار برنامه خود که ExerciseClient
خدمات بهداشتی استفاده می کند ، با لیست چک زیر مشورت کنید تا اطمینان حاصل کنید که تجربه کاربر شما از برخی موارد مشترک جلوگیری می کند. تایید کنید که:
- برنامه شما قابلیت های نوع تمرین و قابلیت های دستگاه را هر بار که برنامه اجرا می شود ، بررسی می کند . به این ترتیب ، شما می توانید تشخیص دهید که یک دستگاه خاص یا ورزش از یکی از انواع داده های برنامه شما پشتیبانی نمی کند.
- شما مجوزهای لازم را درخواست و نگهداری می کنید و این موارد را در پرونده مانیفست خود مشخص می کنید. قبل از تماس با
prepareExerciseAsync()
، برنامه شما تأیید می کند که مجوزهای زمان اجرا اعطا می شود. - برنامه شما از
getCurrentExerciseInfoAsync()
برای رسیدگی به مواردی که در آن استفاده می کند استفاده می کند:- یک تمرین در حال حاضر ردیابی می شود و برنامه شما از تمرین قبلی غلبه می کند.
- برنامه دیگری تمرین شما را خاتمه داده است. این ممکن است زمانی اتفاق بیفتد که کاربر دوباره برنامه را باز کند ، آنها با پیامی روبرو می شوند که توضیح می دهد که این تمرین متوقف شده است زیرا برنامه دیگری به دست گرفته است.
- اگر از داده های
LOCATION
استفاده می کنید:- برنامه شما در طول مدت تمرین (از جمله آماده سازی آماده سازی) یک
ForegroundService
باforegroundServiceType
مربوطه را حفظ می کند. - بررسی کنید که GPS با استفاده از
isProviderEnabled(LocationManager.GPS_PROVIDER)
در دستگاه فعال شده است و کاربر را وادار می کند در صورت لزوم تنظیمات مکان را باز کند. - برای موارد مورد نیاز استفاده ، که دریافت داده های مکان با تأخیر کم از اهمیت زیادی برخوردار است ، ادغام ارائه دهنده مکان ذوب شده (FLP) را در نظر بگیرید و از داده های آن به عنوان یک مکان اولیه استفاده کنید. هنگامی که اطلاعات مکان پایدارتر از خدمات درمانی در دسترس است ، به جای FLP از آن استفاده کنید.
- برنامه شما در طول مدت تمرین (از جمله آماده سازی آماده سازی) یک
- اگر برنامه شما به بارگذاری داده نیاز دارد ، هرگونه تماس شبکه برای بارگذاری داده ها تا پایان تمرین به تعویق می افتد. در غیر این صورت ، در طول تمرین ، برنامه شما هرگونه تماس با شبکه لازم را به طور کم مصرف می کند.
برای شما توصیه می شود
- توجه: وقتی جاوا اسکریپت خاموش است، متن پیوند نمایش داده می شود
- به روزرسانی داده های منفعل
- خدمات بهداشتی در مورد سیستم عامل
- با کاشی شروع کنید