Health Services, ExerciseClient
के ज़रिए, वर्कआउट ऐप्लिकेशन के लिए बेहतरीन सहायता उपलब्ध कराती है.
ExerciseClient
की मदद से, आपका ऐप्लिकेशन यह कंट्रोल कर सकता है कि कोई गतिविधि कब शुरू हो रही है. साथ ही, गतिविधि के लक्ष्य जोड़े जा सकते हैं और गतिविधि की स्थिति, गतिविधि से जुड़े इवेंट या अन्य मेट्रिक के बारे में अपडेट भी मिल सकते हैं. ज़्यादा जानकारी के लिए, ऐसी कसरत के टाइप की पूरी सूची देखें जिनके लिए Health Services काम करती है.
GitHub पर, सैंपल एक्सरसाइज़ देखें.
डिपेंडेंसी जोड़ें
Health Services पर डिपेंडेंसी जोड़ने के लिए, आपको अपने प्रोजेक्ट में Google Maven रिपॉज़िटरी जोड़नी होगी. ज़्यादा जानकारी के लिए, Google का मेवन रिपॉज़िटरी देखें.
इसके बाद, अपने मॉड्यूल-लेवल की build.gradle
फ़ाइल में, यह डिपेंडेंसी जोड़ें:
ग्रूवी
dependencies { implementation "androidx.health:health-services-client:1.1.0-alpha05" }
Kotlin
dependencies { implementation("androidx.health:health-services-client:1.1.0-alpha05") }
ऐप्लिकेशन का स्ट्रक्चर
कसरत से जुड़ा ऐप्लिकेशन बनाते समय, यहां दिए गए ऐप्लिकेशन स्ट्रक्चर का इस्तेमाल करें. इसके लिए, आपको Health Services का इस्तेमाल करना होगा:
- अपनी स्क्रीन और नेविगेशन को मुख्य गतिविधि में ही रखें.
- फ़ोरग्राउंड सेवा की मदद से, वर्कआउट की स्थिति, सेंसर डेटा, मौजूदा गतिविधि, और डेटा को मैनेज करें.
- Room की मदद से डेटा सेव करें और डेटा अपलोड करने के लिए, WorkManager का इस्तेमाल करें.
कसरत की तैयारी करते समय और कसरत के दौरान, कई वजहों से आपकी गतिविधि रुक सकती है. ऐसा हो सकता है कि उपयोगकर्ता किसी दूसरे ऐप्लिकेशन पर स्विच कर दे या स्मार्टवॉच की होम स्क्रीन पर वापस आ जाए. हो सकता है कि सिस्टम आपकी गतिविधि के ऊपर कुछ दिखाए या कुछ समय तक कोई गतिविधि न होने पर स्क्रीन बंद हो जाए.
पूरे वर्कआउट के दौरान सही तरीके से काम करने के लिए, ExerciseClient
के साथ लगातार चलने वाले ForegroundService
का इस्तेमाल करें.
ForegroundService
का इस्तेमाल करके, चल रही गतिविधि के एपीआई का इस्तेमाल करके, स्मार्टवॉच की होम स्क्रीन पर एक इंंडिकेटर दिखाया जा सकता है. इससे उपयोगकर्ता, कसरत पर तुरंत वापस आ सकता है.
यह ज़रूरी है कि आपने फ़ोरग्राउंड सेवा में, जगह की जानकारी के डेटा का सही तरीके से अनुरोध किया हो. अपनी मेनिफ़ेस्ट फ़ाइल में, ज़रूरी फ़ोरग्राउंड सेवा के टाइप और अनुमतियां बताएं:
<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()
कॉल और कसरत की गतिविधि शामिल है. हालांकि, ऐंबियंट मोड के दौरान कसरत के दौरान डिसप्ले को अपडेट न करें: ऐसा इसलिए है, क्योंकि डिवाइस की स्क्रीन ऐंबियंट मोड में होने पर, Health Services कसरत का डेटा एक साथ इकट्ठा करता है, ताकि बैटरी बचाई जा सके. इसलिए, हो सकता है कि डिसप्ले पर दिखने वाली जानकारी हाल की न हो. कसरत के दौरान, उपयोगकर्ता के लिए काम का डेटा दिखाएं. इसमें अप-टू-डेट जानकारी या खाली स्क्रीन दिखाएं.
सुविधाओं की जांच करना
हर 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
कसरत की स्थिति के अपडेट पाने के लिए रजिस्टर करना
कसरत के अपडेट, सुनने वाले को भेजे जाते हैं. आपका ऐप्लिकेशन एक बार में सिर्फ़ एक Listener को रजिस्टर कर सकता है. वर्कआउट शुरू करने से पहले, अपने लिसनर को सेट अप करें, जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है. आपके ऐप्लिकेशन के उपयोगकर्ता को सिर्फ़ उन कसरत के बारे में अपडेट मिलते हैं जिनका मालिकाना हक आपके ऐप्लिकेशन के पास है.
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
फ़ाइल में, अनुरोध किए गए डेटा टाइप के लिए सही अनुमतियां दें. - पुष्टि करें कि उपयोगकर्ता ने ज़रूरी अनुमतियां दी हैं. ज़्यादा जानकारी के लिए, ऐप्लिकेशन की अनुमतियां मांगना लेख पढ़ें. अगर ज़रूरी अनुमतियां पहले से नहीं दी गई हैं, तो Health Services ऐप्लिकेशन आपके अनुरोध को अस्वीकार कर देता है.
जगह की जानकारी के डेटा के लिए, ये अतिरिक्त चरण पूरे करें:
isProviderEnabled(LocationManager.GPS_PROVIDER)
का इस्तेमाल करके, देखें कि डिवाइस पर जीपीएस चालू है या नहीं. अगर ज़रूरी हो, तो उपयोगकर्ता को जगह की जानकारी की सेटिंग खोलने के लिए कहें.- पक्का करें कि कसरत के दौरान, सही
foregroundServiceType
के साथForegroundService
बनाए रखा जाए.
कसरत के लिए तैयार होना
जीपीएस या दिल की धड़कन जैसे कुछ सेंसर को गर्म होने में थोड़ा समय लग सकता है. इसके अलावा, हो सकता है कि उपयोगकर्ता कसरत शुरू करने से पहले अपना डेटा देखना चाहे. ज़रूरी नहीं है कि prepareExerciseAsync()
वाला तरीका अपनाया जाए. इसकी मदद से, इन सेंसर को वॉर्म अप किया जा सकता है और वर्कआउट के लिए टाइमर शुरू किए बिना ही डेटा पाया जा सकता है. तैयारी में लगने वाले इस समय का असर activeDuration
पर नहीं पड़ता.
prepareExerciseAsync()
को कॉल करने से पहले, इन बातों का ध्यान रखें:
प्लैटफ़ॉर्म पर जगह की जानकारी की सेटिंग देखें. उपयोगकर्ता, मुख्य सेटिंग मेन्यू में जाकर इस सेटिंग को कंट्रोल करता है. यह ऐप्लिकेशन-लेवल की अनुमतियों की जांच से अलग है.
अगर सेटिंग बंद है, तो उपयोगकर्ता को सूचना दें कि उन्होंने जगह की जानकारी का ऐक्सेस देने से मना कर दिया है. साथ ही, अगर आपके ऐप्लिकेशन को जगह की जानकारी की ज़रूरत है, तो उसे चालू करने के लिए कहें.
पुष्टि करें कि आपके ऐप्लिकेशन के पास, रनटाइम की अनुमतियां हैं. इनमें, शरीर के सेंसर (एपीआई लेवल 35 या उससे पहले के वर्शन) या दिल की धड़कन (एपीआई लेवल 36 और उसके बाद के वर्शन), गतिविधि की पहचान करने की सुविधा, और सटीक जगह की जानकारी शामिल है. जिन अनुमतियों के लिए अनुरोध नहीं किया गया है उनके लिए, उपयोगकर्ता से रनटाइम की अनुमतियां मांगें. साथ ही, ज़रूरी जानकारी दें. अगर उपयोगकर्ता किसी खास अनुमति को स्वीकार नहीं करता है, तो
prepareExerciseAsync()
को किए जाने वाले कॉल से उस अनुमति से जुड़े डेटा टाइप हटाएं. अगर बॉडी सेंसर (एपीआई लेवल 36 और उसके बाद के वर्शन पर, धड़कन की दर) या जगह की जानकारी की अनुमतियां नहीं दी गई हैं, तोprepareExerciseAsync()
को कॉल न करें. ऐसा इसलिए, क्योंकि 'प्रिपेयर कॉल' खास तौर पर, कसरत शुरू करने से पहले, धड़कन की दर को स्थिर करने या जीपीएस फ़िक्स करने के लिए होता है. ऐप्लिकेशन अब भी कदमों के आधार पर तय की गई दूरी, रफ़्तार, और ऐसी अन्य मेट्रिक ऐक्सेस कर सकता है जिनके लिए इन अनुमतियों की ज़रूरत नहीं होती.
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 (API level 35
// or lower), heart rate (API level 36+), or location permissions are given.
exerciseClient.prepareExerciseAsync(warmUpConfig).await()
// Data and availability updates are delivered to the registered listener.
ऐप्लिकेशन के PREPARING
स्टेटस में होने के बाद, सेंसर की उपलब्धता के अपडेट, onAvailabilityChanged()
के ज़रिए ExerciseUpdateCallback
में डिलीवर किए जाते हैं.
इसके बाद, इस जानकारी को उपयोगकर्ता को दिखाया जा सकता है, ताकि वह यह तय कर सके कि उसे वर्कआउट शुरू करना है या नहीं.
वर्कआउट शुरू करना
जब आपको कोई गतिविधि शुरू करनी हो, तो 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()
}
सभी कसरत के लिए भी लैप मार्क किए जा सकते हैं. स्वास्थ्य सेवाएं, लैप अवधि के दौरान इकट्ठा की गई मेट्रिक के साथ एक ExerciseLapSummary
उपलब्ध कराती हैं.
पिछले उदाहरण में isGpsEnabled
का इस्तेमाल दिखाया गया है. जगह की जानकारी के डेटा का अनुरोध करते समय, इसकी वैल्यू 'सही' होनी चाहिए. हालांकि, जीपीएस का इस्तेमाल करके अन्य मेट्रिक का भी पता लगाया जा सकता है.
अगर ExerciseConfig
में दूरी को DataType
के तौर पर बताया गया है, तो दूरी का अनुमान लगाने के लिए डिफ़ॉल्ट रूप से कदमों का इस्तेमाल किया जाता है. जीपीएस को चालू करके, जगह की जानकारी का इस्तेमाल करके भी दूरी का अनुमान लगाया जा सकता है. हालांकि, ऐसा करना ज़रूरी नहीं है.
कसरत को रोकना, फिर से शुरू करना, और खत्म करना
सही तरीके का इस्तेमाल करके, वर्कआउट को रोका, फिर से शुरू किया, और खत्म किया जा सकता है. जैसे,
pauseExerciseAsync()
या
endExerciseAsync()
.
ExerciseUpdate
की स्थिति को सोर्स ऑफ़ ट्रूथ के तौर पर इस्तेमाल करें. pauseExerciseAsync()
को कॉल करने पर, वर्कआउट को रुका हुआ नहीं माना जाता. इसके बजाय, ExerciseUpdate
मैसेज में उस स्थिति को दिखाने पर, वर्कआउट को रुका हुआ माना जाता है. यूज़र इंटरफ़ेस (यूआई) के स्टेटस के लिए, इस बात का ध्यान रखना ज़रूरी है. अगर उपयोगकर्ता 'रोकें' बटन दबाता है, तो 'रोकें' बटन को बंद करें और pauseExerciseAsync()
पर कॉल करें. ExerciseUpdate.exerciseStateInfo.state
का इस्तेमाल करके, Health Services के रोके जाने की स्थिति तक पहुंचने का इंतज़ार करें. इसके बाद, बटन को फिर से शुरू करने के लिए स्विच करें. ऐसा इसलिए है, क्योंकि बटन दबाने के मुकाबले, Health Services की स्थिति के अपडेट को डिलीवर होने में ज़्यादा समय लग सकता है. इसलिए, अगर यूज़र इंटरफ़ेस (यूआई) में होने वाले सभी बदलावों को बटन दबाने से जोड़ा जाता है, तो यूआई, Health Services की स्थिति के साथ सिंक नहीं हो सकता.
इन स्थितियों में इस बात का ध्यान रखें:
- अपने-आप रुकने की सुविधा चालू है: कसरत, उपयोगकर्ता के इंटरैक्शन के बिना रुक सकती है या शुरू हो सकती है.
- कोई दूसरा ऐप्लिकेशन कसरत शुरू करता है: ऐसा हो सकता है कि उपयोगकर्ता के इंटरैक्शन के बिना ही आपकी कसरत खत्म हो जाए.
अगर आपके ऐप्लिकेशन के वर्कआउट को किसी दूसरे ऐप्लिकेशन ने बंद कर दिया है, तो आपके ऐप्लिकेशन को इस स्थिति को ठीक से मैनेज करना चाहिए:
- कसरत के कुछ हिस्से की स्थिति सेव करें, ताकि उपयोगकर्ता की प्रोग्रेस मिट न जाए.
- 'चल रही गतिविधि' आइकॉन हटाएं और उपयोगकर्ता को सूचना भेजें कि किसी दूसरे ऐप्लिकेशन ने उसकी कसरत खत्म कर दी है.
साथ ही, उस स्थिति को भी मैनेज करें जहां किसी गतिविधि के दौरान अनुमतियां रद्द कर दी जाती हैं. इसे isEnded
स्टेटस का इस्तेमाल करके भेजा जाता है. इसमें AUTO_END_PERMISSION_LOST
का ExerciseEndReason
होता है. इस मामले को, प्रोसेस खत्म होने के मामले की तरह ही मैनेज करें: आंशिक स्थिति सेव करें, 'गतिविधि जारी है' आइकॉन हटाएं, और उपयोगकर्ता को इस बारे में सूचना भेजें कि क्या हुआ.
यहां दिए गए उदाहरण में, सदस्यता खत्म होने की जांच करने का सही तरीका बताया गया है:
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
}
...
}
...
}
डिवाइस के चालू रहने की अवधि मैनेज करना
कसरत के दौरान, कोई ऐप्लिकेशन वर्कआउट के चालू रहने की अवधि दिखा सकता है. ऐप्लिकेशन, Health Services, और डिवाइस की माइक्रो कंट्रोलर यूनिट (एमसीयू) को एक साथ सिंक करना ज़रूरी है. एमसीयू, कम बैटरी वाले प्रोसेसर होते हैं, जो गतिविधि ट्रैकिंग की सुविधा देते हैं. इन सभी की चालू रहने की अवधि एक जैसी होनी चाहिए. इसे मैनेज करने के लिए, Health Services एक ActiveDurationCheckpoint
भेजता है. इससे ऐप्लिकेशन को एक ऐंकर पॉइंट मिलता है, जिससे वह अपना टाइमर शुरू कर सकता है.
ऐक्टिव रहने की अवधि, एमसीयू से भेजी जाती है और ऐप्लिकेशन में पहुंचने में थोड़ा समय लग सकता है. इसलिए, ActiveDurationCheckpoint
में दो प्रॉपर्टी होती हैं:
activeDuration
: कसरत कितने समय से चालू हैtime
: सक्रिय रहने की अवधि का हिसाब कब लगाया गया
इसलिए, ऐप्लिकेशन में किसी गतिविधि के चालू रहने की अवधि का हिसाब, ActiveDurationCheckpoint
से लगाया जा सकता है. इसके लिए, इस समीकरण का इस्तेमाल करें:
(now() - checkpoint.time) + checkpoint.activeDuration
इससे, एमसीयू पर ऐक्टिव रहने के कुल समय और ऐप्लिकेशन पर दिखने वाले कुल समय के बीच के छोटे अंतर का पता चलता है. इसका इस्तेमाल, ऐप्लिकेशन में क्रोनोमीटर सेट करने के लिए किया जा सकता है. साथ ही, यह पक्का करने में भी मदद मिलती है कि ऐप्लिकेशन का टाइमर, Health Services और एमसीयू में दिखने वाले समय के साथ पूरी तरह से अलाइन हो.
अगर कसरत रोक दी जाती है, तो ऐप्लिकेशन यूज़र इंटरफ़ेस (यूआई) में टाइमर को तब तक फिर से शुरू नहीं करता, जब तक कि कैलकुलेट किया गया समय, यूज़र इंटरफ़ेस (यूआई) में दिखने वाले समय से ज़्यादा न हो जाए.
ऐसा इसलिए होता है, क्योंकि रोकने का सिग्नल, हेल्थ सर्विसेज़ और एमसीयू तक थोड़ी देरी से पहुंचता है. उदाहरण के लिए, अगर ऐप्लिकेशन को t=10 सेकंड पर रोका जाता है, तो हो सकता है कि Health Services, t=10.2 सेकंड तक ऐप्लिकेशन में PAUSED
अपडेट न भेजे.
ExerciseClient से मिले डेटा का इस्तेमाल करना
आपके ऐप्लिकेशन ने जिन डेटा टाइप के लिए रजिस्टर किया है उनकी मेट्रिक, ExerciseUpdate
मैसेज में डिलीवर की जाती हैं.
प्रोसेसर सिर्फ़ तब मैसेज डिलीवर करता है, जब वह चालू हो या रिपोर्टिंग की तय अवधि पूरी हो गई हो. जैसे, हर 150 सेकंड में. activeDuration
की मदद से क्रोनोमीटर को आगे बढ़ाने के लिए,
ExerciseUpdate
फ़्रीक्वेंसी पर भरोसा न करें. अलग से काम करने वाले क्रोनोमीटर को लागू करने का उदाहरण देखने के लिए, GitHub पर इस्तेमाल के उदाहरण देखें.
जब कोई उपयोगकर्ता कसरत शुरू करता है, तो ExerciseUpdate
मैसेज बार-बार डिलीवर किए जा सकते हैं, जैसे कि हर सेकंड. जब उपयोगकर्ता कसरत शुरू करता है, तो हो सकता है कि स्क्रीन बंद हो जाए. इसके बाद, Health Services कम बार डेटा डिलीवर कर सकती है. हालांकि, मुख्य प्रोसेसर को चालू होने से रोकने के लिए, डेटा की सैंपलिंग की फ़्रीक्वेंसी में कोई बदलाव नहीं होता. जब उपयोगकर्ता स्क्रीन पर नज़र डालता है, तो बैच में डाले जा रहे डेटा को तुरंत आपके ऐप्लिकेशन पर डिलीवर कर दिया जाता है.
एक साथ कई फ़ाइलें अपलोड करने की दर कंट्रोल करना
कुछ मामलों में, हो सकता है कि आप यह कंट्रोल करना चाहें कि स्क्रीन बंद होने पर, आपके ऐप्लिकेशन को किस तरह का डेटा कितनी बार मिले. 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
प्रॉपर्टी मौजूद है, तो इसका इस्तेमाल करके यह तय करें कि आपके ऐप्लिकेशन के लिए हर डेटा पॉइंट काफ़ी सटीक है या नहीं.
डेटा सेव और अपलोड करना
Health Services से मिले डेटा को सेव करने के लिए, Room का इस्तेमाल करें. Work Manager जैसी सुविधा का इस्तेमाल करके, एक्सरसाइज़ के आखिर में डेटा अपलोड किया जाता है. इससे यह पक्का होता है कि डेटा अपलोड करने के लिए नेटवर्क कॉल, गतिविधि खत्म होने तक रोके जाते हैं. इससे गतिविधि के दौरान बैटरी की खपत कम होती है और काम आसान हो जाता है.
एकीकरण चेकलिस्ट
Health Services के ExerciseClient
का इस्तेमाल करने वाले ऐप्लिकेशन को पब्लिश करने से पहले, यहां दी गई चेकलिस्ट देखें. इससे यह पक्का किया जा सकेगा कि आपके ऐप्लिकेशन का इस्तेमाल करने वाले लोगों को कुछ सामान्य समस्याओं का सामना न करना पड़े.
पुष्टि करें कि:
- आपका ऐप्लिकेशन हर बार चलने पर, गतिविधि के टाइप और डिवाइस की क्षमताओं की जांच करता है. इससे, यह पता लगाया जा सकता है कि कोई डिवाइस या कसरत, आपके ऐप्लिकेशन के लिए ज़रूरी किसी डेटा टाइप के साथ काम करती है या नहीं.
- आपने ज़रूरी अनुमतियों का अनुरोध किया है और उन्हें बनाए रखा है. साथ ही, इनके बारे में अपनी मेनिफ़ेस्ट फ़ाइल में बताया है.
prepareExerciseAsync()
को कॉल करने से पहले, आपका ऐप्लिकेशन इस बात की पुष्टि करता है कि रनटाइम की अनुमतियां दी गई हैं. - आपका ऐप्लिकेशन
getCurrentExerciseInfoAsync()
का इस्तेमाल, इन मामलों में करने के लिए करता है:- किसी गतिविधि को पहले से ट्रैक किया जा रहा है और आपका ऐप्लिकेशन पिछली गतिविधि को बदल देता है.
- किसी दूसरे ऐप्लिकेशन ने आपकी गतिविधि को बंद कर दिया है. ऐसा तब हो सकता है, जब उपयोगकर्ता ऐप्लिकेशन को फिर से खोले और उसे एक मैसेज दिखे. इसमें बताया गया हो कि कसरत इसलिए रुकी है, क्योंकि कोई दूसरा ऐप्लिकेशन चालू हो गया है.
- अगर
LOCATION
डेटा का इस्तेमाल किया जा रहा है, तो:- आपका ऐप्लिकेशन, गतिविधि के दौरान
ForegroundService
को उससे जुड़ेforegroundServiceType
के साथ बनाए रखता है. इसमें, गतिविधि के लिए तैयारी करने वाला कॉल भी शामिल है. isProviderEnabled(LocationManager.GPS_PROVIDER)
का इस्तेमाल करके, यह देखें कि डिवाइस पर जीपीएस चालू है या नहीं. साथ ही, ज़रूरत पड़ने पर उपयोगकर्ता को जगह की जानकारी की सेटिंग खोलने के लिए कहें.- ज़्यादा मांग वाले इस्तेमाल के उदाहरणों के लिए, जहां जगह की जानकारी का डेटा कम समय में पाना बहुत ज़रूरी है, वहां फ़्यूज़्ड जगह की जानकारी देने वाली सेवा (एफ़एलपी) को इंटिग्रेट करें और उसके डेटा का इस्तेमाल, जगह की जानकारी को ठीक करने के लिए शुरुआती डेटा के तौर पर करें. जब Health Services से जगह की जानकारी ज़्यादा सटीक हो, तो FLP के बजाय उसका इस्तेमाल करें.
- आपका ऐप्लिकेशन, गतिविधि के दौरान
- अगर आपके ऐप्लिकेशन को डेटा अपलोड करना है, तो डेटा अपलोड करने के लिए किए जाने वाले सभी नेटवर्क कॉल, एक्सरसाइज़ खत्म होने तक के लिए रोक दिए जाते हैं. ऐसा न होने पर, गतिविधि के दौरान आपका ऐप्लिकेशन ज़रूरत के हिसाब से नेटवर्क कॉल करता है.
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक टेक्स्ट दिखता है
- पैसिव डेटा अपडेट
- Wear OS पर स्वास्थ्य से जुड़ी सेवाएं
- टाइल का इस्तेमाल शुरू करना