שירותי Health מספקים תמיכה ברמה הגבוהה ביותר לאפליקציות אימון באמצעות ExerciseClient
.
באמצעות ExerciseClient
, האפליקציה יכולה לקבוע מתי מתבצע אימון, להוסיף יעדי אימון ולקבל עדכונים על מצב האימון, על אירועי אימון או על מדדים אחרים. למידע נוסף, ראו את הרשימה המלאה של סוגי האימונים שנתמכים ב-Health Services.
הדוגמה לתרגול ב-GitHub.
הוספת יחסי תלות
כדי להוסיף תלות ב-Health Services, צריך להוסיף את מאגר Google Maven לפרויקט. למידע נוסף, ראו מאגר Maven של Google.
לאחר מכן, מוסיפים את התלות הבאה לקובץ build.gradle
ברמת המודול:
Groovy
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 כדי להעלות נתונים.
בזמן ההכנה לאימון ובמהלך האימון, יכול להיות שהפעילות שלכם תופסק מסיבות שונות. המשתמש עשוי לעבור לאפליקציה אחרת או לחזור לתצוגת השעון. יכול להיות שהמערכת תציג משהו מעל הפעילות שלכם, או שהמסך יכבה אחרי פרק זמן של חוסר פעילות.
כדי לוודא שהאימון יתבצע בצורה תקינה, מומלץ להשתמש ב-ForegroundService
שפועל באופן רציף בשילוב עם ExerciseClient
.
שימוש ב-ForegroundService
מאפשר להשתמש ב-Ongoing Activity 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()
, ולפעילות האימון. עם זאת, אל תעדכנו את המסך במהלך האימון במצב אווירה: הסיבה לכך היא ששירותי Health אוספים את נתוני האימון כאשר מסך המכשיר במצב אווירה כדי לחסוך בחשמל, ולכן יכול להיות שהמידע שמוצג לא יהיה עדכני. במהלך האימונים, כדאי להציג נתונים שיהיו הגיוניים למשתמש, כמו מידע עדכני או מסך ריק.
בדיקת היכולות
כל 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)
ניהול משך החיים של האימון
שירותי Google Health תומכים בביצוע של אימון אחד בכל פעם בכל האפליקציות במכשיר. אם מתבצע מעקב אחר אימון ואפליקציה אחרת מתחילה לעקוב אחרי אימון חדש, האימון הראשון מסתיים.
לפני שמתחילים את האימון, מבצעים את הפעולות הבאות:
- בודקים אם כבר מתבצע מעקב אחרי פעילות מסוימת, ומגיבים בהתאם. לדוגמה, אפשר לבקש מהמשתמש לאשר לפני שמבטלים אימון קודם ומתחילים לעקוב אחרי אימון חדש.
הדוגמה הבאה מראה איך לבדוק אם יש תרגול קיים באמצעות 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()
, צריך לבדוק את הדברים הבאים:
בודקים את הגדרת המיקום ברמת הפלטפורמה. המשתמש קובע את ההגדרה הזו בתפריט ההגדרות הראשי. היא שונה מבדיקת ההרשאות ברמת האפליקציה.
אם ההגדרה מושבתת, צריך להודיע למשתמש שהוא דחה את הגישה למיקום, ולבקש ממנו להפעיל אותה אם האפליקציה שלכם דורשת גישה למיקום.
מוודאים שלאפליקציה יש הרשאות בסביבת זמן הריצה לחיישנים של הגוף (רמת API 35 ומטה) או לקצב הלב (רמת API 36 ואילך), לזיהוי פעילות ולמיקום מדויק. אם חסרות הרשאות, צריך לבקש מהמשתמש הרשאות זמן ריצה, תוך מתן הקשר מתאים. אם המשתמש לא מעניק הרשאה ספציפית, צריך להסיר את סוגי הנתונים המשויכים להרשאה הזו מהקריאה ל-
prepareExerciseAsync()
. אם לא ניתנו הרשאות למיקום או לחיישן הגוף (דופק ברמת API 36 ואילך), אל תפעילו את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 (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
, עדכוני הזמינות של החיישנים מועברים ב-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
, שצריך להיות true כשמבקשים נתוני מיקום. עם זאת, השימוש ב-GPS יכול לעזור גם במדדים אחרים.
אם ב-ExerciseConfig
מצוין המרחק כ-DataType
, ברירת המחדל היא להשתמש בצעדים כדי להעריך את המרחק. אם מפעילים את ה-GPS, אפשר להשתמש בנתוני המיקום כדי להעריך את המרחק.
השהיה, המשך והפסקה של אימון
אפשר להשהות, להמשיך ולסיים אימונים באמצעות הלחצן המתאים, למשל pauseExerciseAsync()
או endExerciseAsync()
.
משתמשים במצב מ-ExerciseUpdate
כמקור האמת. האימון נחשב להשהיה רק כשהמצב הזה משתקף בהודעה ExerciseUpdate
, ולא כשהקריאה ל-pauseExerciseAsync()
חוזרת. חשוב במיוחד להביא את הנושא הזה בחשבון כשמדובר במצבים של ממשק המשתמש. אם המשתמש לוחץ על 'השהיה', משביתים את לחצן ההשהיה ומפעילים את pauseExerciseAsync()
בשירותי הבריאות. ממתינים עד ששירותי הבריאות מגיעים למצב מושהה באמצעות ExerciseUpdate.exerciseStateInfo.state
, ואז מעבירים את הלחצן למצב 'המשך'. הסיבה לכך היא שזמן האספקה של עדכוני המצב של Health Services יכול להיות ארוך יותר מזמן הלחיצה על הלחצן, כך שאם תקשרו את כל השינויים בממשק המשתמש ללחיצות על לחצנים, יכול להיות שממשק המשתמש לא יתואם למצב של Health Services.
חשוב לזכור את זה במצבים הבאים:
- השהיה אוטומטית מופעלת: האימון יכול להתחיל או להשהות ללא אינטראקציה של המשתמש.
- אפליקציה אחרת מתחילה אימון: יכול להיות שהאימון יופסק ללא אינטראקציה של המשתמש.
אם האימון באפליקציה שלכם יופסק על ידי אפליקציה אחרת, האפליקציה שלכם צריכה לטפל בהפסקה בצורה נעימה:
- שומרים את מצב האימון החלקי כדי שההתקדמות של המשתמש לא תימחק.
- להסיר את סמל הפעילות המתמשכת ולשלוח למשתמש התראה על כך שהאימון שלו הסתיים על ידי אפליקציה אחרת.
בנוסף, צריך לטפל במקרה שבו ההרשאות בוטלו במהלך אימון מתמשך. הוא נשלח במצב 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
}
...
}
...
}
ניהול משך הפעילות הפעילה
במהלך אימון, האפליקציה יכולה להציג את משך הזמן הפעיל של האימון. האפליקציה, שירותי Health והיחידה הבקרת המיקרו (MCU) של המכשיר – המעבד בעל צריכת החשמל הנמוכה שאחראי למעקב אחר האימונים – צריכים להיות מסונכרנים, עם אותו משך זמן פעיל נוכחי. כדי לעזור בניהול הבעיה הזו, שירותי הבריאות שולחים ActiveDurationCheckpoint
שמספק נקודת עיגון שממנה האפליקציה יכולה להפעיל את הטיימר שלה.
מכיוון שמשך הפעילות הפעילה נשלח מה-MCU ויכול להיות שיחלוף זמן מה עד שהוא יגיע לאפליקציה, השדה ActiveDurationCheckpoint
מכיל שני מאפיינים:
activeDuration
: משך הזמן שבו התרגיל היה פעילtime
: מתי נקבע משך הזמן הפעיל
לכן, באפליקציה אפשר לחשב את משך הפעילות של האימון לפי ActiveDurationCheckpoint
באמצעות המשוואה הבאה:
(now() - checkpoint.time) + checkpoint.activeDuration
כך ניתן להסביר את ההפרש הקטן בין משך הפעילות שמחושב ב-MCU לבין משך הפעילות שמגיע לאפליקציה. אפשר להשתמש בנתונים האלה כדי להגדיר את הזמן בכרונומטר באפליקציה, וכך לוודא שהשעון של האפליקציה תואם לחלוטין לשעון ב-Health Services וב-MCU.
אם התרגיל מושהה, האפליקציה ממתינה להפעלה מחדש של הטיימר בממשק המשתמש עד שהזמן המחושב יחלוף מהזמן שמוצג כרגע בממשק המשתמש.
הסיבה לכך היא שאות ההשהיה מגיע ל-Health Services ול-MCU עם עיכוב קל. לדוגמה, אם האפליקציה מושהית בשעה t=10 שניות, יכול להיות ש-Health Services לא יעביר את העדכון PAUSED
לאפליקציה עד לשעה t=10.2 שניות.
עבודה עם נתונים מ-ExerciseClient
המדדים של סוגי הנתונים שהאפליקציה שלכם רשומה אליהם מועברים באמצעות הודעות ExerciseUpdate
.
המעבד שולח הודעות רק כשהמכשיר פעיל או כשמגיעים לפרק הזמן המקסימלי לדיווח, למשל כל 150 שניות. אל תסתמכו על התדירות ExerciseUpdate
כדי להעביר את הכרונומטר באמצעות activeDuration
. בדוגמה הזו ב-GitHub מוסבר איך להטמיע שעון כרונומטר עצמאי.
כשמשתמש מתחיל אימון, אפשר לשלוח הודעות ExerciseUpdate
בתדירות גבוהה, למשל בכל שנייה. כשהמשתמש מתחיל את האימון, יכול להיות שהמסך יכבה. לאחר מכן, שירותי Health יוכלו לשלוח נתונים בתדירות נמוכה יותר, אבל עדיין לדגום אותם באותה תדירות, כדי להימנע מהפעלה של המעבד הראשי. כשהמשתמש מביט במסך, כל הנתונים שנמצאים בתהליך קיבוץ נשלחים לאפליקציה באופן מיידי.
שליטה בקצב הקיבוץ
בתרחישים מסוימים, יכול להיות שתרצו לקבוע את התדירות שבה האפליקציה תקבל סוגי נתונים מסוימים כשהמסך כבוי. אובייקט 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
קיים, אפשר להשתמש בו כדי לקבוע אם רמת הדיוק של כל נקודה בנתונים מספיקה לאפליקציה.
אחסון והעלאה של נתונים
שימוש ב-Room כדי לשמור נתונים שנשלחים מ-Health Services. העלאת הנתונים מתבצעת בסוף התרגיל באמצעות מנגנון כמו Work Manager. כך אפשר לוודא שהקריאות לרשת להעלאת נתונים יושהו עד לסיום התרגיל, וכך לצמצם את צריכת החשמל במהלך התרגיל ולפשט את העבודה.
רשימת בדיקה לאינטגרציה
לפני שמפרסמים אפליקציה שמשתמשת ב-ExerciseClient
של שירותי הבריאות, כדאי לעיין ברשימת המשימות הבאה כדי לוודא שחוויית המשתמש לא תכלול בעיות נפוצות.
ודאו ש:
- האפליקציה בודקת את היכולות של סוג התרגיל ואת היכולות של המכשיר בכל פעם שהיא פועלת. כך תוכלו לזהות מתי מכשיר או תרגיל מסוימים לא תומכים באחד מסוגי הנתונים שהאפליקציה שלכם זקוקה להם.
- אתם מבקשים את ההרשאות הנדרשות, שומרים עליהן ומציינים אותן בקובץ המניפסט. לפני שמפעילים את
prepareExerciseAsync()
, האפליקציה מאשרת שההרשאות בסביבת זמן הריצה הוענקו. - האפליקציה שלכם משתמשת ב-
getCurrentExerciseInfoAsync()
כדי לטפל במקרים שבהם:- כבר מתבצע מעקב אחרי אימון מסוים, והאפליקציה מבטלת את האימון הקודם.
- אפליקציה אחרת סיימה את האימון. המצב הזה יכול לקרות כשהמשתמש פותח מחדש את האפליקציה, ומופיעה הודעה שמסבירה שהתרגיל הופסק כי אפליקציה אחרת לקחה את השליטה.
- אם אתם משתמשים בנתונים של
LOCATION
:- האפליקציה שומרת
ForegroundService
עםforegroundServiceType
התואם לכל משך התרגיל (כולל קריאת ההכנה). - בודקים אם ה-GPS מופעל במכשיר באמצעות
isProviderEnabled(LocationManager.GPS_PROVIDER)
, ומבקשים מהמשתמש לפתוח את הגדרות המיקום במקרה הצורך. - בתרחישי שימוש תובעניים שבהם חשוב מאוד לקבל נתוני מיקום עם זמן אחזור קצר, מומלץ לשלב את ספק המיקום המשולב (FLP) ולהשתמש בנתונים שלו כנקודה ראשונית לקביעת המיקום. כשיש מידע יציב יותר על המיקום משירותי Health, משתמשים בו במקום ב-FLP.
- האפליקציה שומרת
- אם האפליקציה שלכם דורשת העלאת נתונים, כל הקריאות לרשת להעלאת נתונים יושהו עד לסיום התרגיל. אחרת, במהלך התרגיל האפליקציה תבצע את הקריאות הנחוצות לרשת באופן חסכוני.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- עדכוני נתונים פסיביים
- שירותי בריאות ב-Wear OS
- תחילת העבודה עם משבצות