פיתוח חוויות אימון באמצעות Google Health API

‫Google Health API עוקב אחרי סשנים של אימונים והיסטוריית האימונים של המשתמשים באמצעות סוג נתוני הסשן exercise. הסשן פועל כקונטיינר שמאגד מטא-נתונים של פעילות, אירועי השהיה והמשך, הקפות או פיצולים ומדדי סיכום.

כדי לספק למשתמשים את חוויית השימוש הטובה ביותר, חשוב להבין איך לקרוא, לכתוב ולבנות אימונים באפליקציה.

סוגי נתונים נתמכים

ה-API תומך בסוג הנתונים הבא למעקב אחרי אימונים וסשנים של פעילות:

טבלה: סוגי הנתונים של Google Health API Workouts
סוג הנתונים פעולות
אפשריות
היקף
פעילות גופנית
dataType: exercise
filter parameter: exercise
סוג הרשומה: סשן

מכשירים תואמים

‫list, ‏ get, ‏ reconcile, ‏ create, ‏ update, ‏ batchDelete .activity_and_fitness.readonly
.activity_and_fitness.writeonly

בסשנים של אימונים, סוג הנתונים exercise משמש כמאגר, אבל מכשירים לבישים מתעדים גם נתוני טלמטריה מפורטים בתדירות גבוהה במהלך הסשן. ב-Google Health API, סוגי הנתונים המפורטים האלה של טלמטריה במהלך היום הם לקריאה בלבד, ואי אפשר ליצור או לשנות אותם ישירות דרך נקודות הקצה (endpoints) שלהם ב-REST. כשכותבים אימון באמצעות ה-API בארכיטקטורת REST, מעבירים מדדי אימון מצטברים בתוך האובייקט metricsSummary של הנקודה על הגרף exercise.

בטבלה הבאה מופיע מיפוי של שדות הסיכום ב-exercise.metricsSummary לסוגי הנתונים המתאימים של טלמטריה במהלך היום לקריאה בלבד, שאפשר לשלוח לגביהם שאילתות לחלון הזמן של האימון:

שדה סיכום (metricsSummary) שם סוג הנתונים של הטלמטריה במהלך היום מזהה סוג הנתונים של נתוני הטלמטריה של ה-API (לקריאה בלבד) שדה סינון (?filter=) היקף הרשאות הקריאה הנדרש של OAuth
caloriesKcal אנרגיה שנשרפה בזמן פעילות active-energy-burned active_energy_burned.interval.start_time activity_and_fitness.readonly
distanceMillimeters מרחק distance distance.interval.start_time activity_and_fitness.readonly
steps שלבים steps steps.interval.start_time activity_and_fitness.readonly
averageHeartRateBeatsPerMinute דופק heart-rate heart_rate.sample_time.physical_time health_metrics_and_measurements.readonly
activeZoneMinutes דקות טווח דופק active-zone-minutes active_zone_minutes.interval.start_time activity_and_fitness.readonly

בקטעים הבאים מפורטים פרטים טכניים על סוג הנתונים exercise, כולל דוגמאות לייצוג REST, טיפול במסלולי GPS והנחיות לשילוב.

אימוני כושר

לכתוב פעילויות או אימונים יומיים כנקודות על הגרף של נתוני סשנים ב-exercise. כל נקודה על הגרף מתארת את הסשן הכולל, מפרטת את מרווחי הזמן של האירועים (כמו פעולות השהיה והמשך) ומספקת מדדי סיכום (כמו מרחק כולל, צעדים ודופק ממוצע).

מאפייני סשן

כשמבנים נקודה על הגרף של אימון, צריך לוודא שרכיבי הליבה הבאים קיימים:

  • ‫Session Time (interval): שעת ההתחלה ושעת הסיום של האימון כולו, כולל הפרשי השעות מאזור הזמן שפעילים בנקודות הזמן האלה.
  • סוג הפעילות (exerciseType): קטגוריית הפעילות שבוצעה (למשל RUNNING,‏ WALKING,‏ BIKING או AEROBIC_WORKOUT). צריך לציין את הסוג המדויק של האימון הגופני.
  • שם לתצוגה (displayName): שם ידידותי למשתמש של האימון. כשיוצרים את ה-exerciseType באמצעות ה-API בארכיטקטורת REST, השרת מאכלס את השם המותאם לשפה המקומית שמוצג, למשל "Run" ל-RUNNING.
  • משך הזמן הפעיל (activeDuration): משך הזמן הפעיל בפועל של האימון, לא כולל מרווחי זמן של השהיה. הפורמט הרגיל הוא Duration (לדוגמה, "1800s"). בשרת, הערך של activeDuration מחושב לפי הערך של interval בסשן, פחות כל מרווח של PAUSE/RESUME או AUTO_PAUSE/AUTO_RESUME ב-exerciseEvents.

מדדי סיכום

האובייקט המקונן metricsSummary מכיל מדדים כוללים וממוצעים שמחושבים לאורך כל משך האימון:

  • ‫caloriesKcal: סך הקלוריות הפעילות שנשרפו במהלך האימון, בקילוקלוריות (kcal).
  • ‫distanceMillimeters: המרחק הכולל שנמדד במילימטרים כדי לשמור על דיוק גבוה בכל היחידות.
  • ‫steps: מספר הצעדים הכולל במהלך האימון.
  • ‫averageHeartRateBeatsPerMinute: הדופק הממוצע של המשתמש במהלך דקות הפעילות של הסשן.
  • ‫activeZoneMinutes: מספר מצטבר של דקות טווח דופק שנצברו במהלך האימון.
  • ‫averageSpeedMillimetersPerSecond: מהירות התנועה הממוצעת במילימטרים לשנייה.
  • ‫averagePaceSecondsPerMeter: הקצב הממוצע במהלך הדקות הפעילות בסשן, נמדד בשניות למטר.
  • ‫elevationGainMillimeters: סה"כ עלייה במהלך הסשן.

הקפות ופיצולים

באימונים שכוללים הקפות (כמו ריצה במסלול או שחייה בבריכה) שמסונכרנים ממכשירים נתמכים, splitSummaries מחלק את הסשן לפי הקפה או פיצול.

כל פיצול מכיל:

  • startTime וendTime ספציפיים.
  • activeDuration שמייצג את זמן ההקפה האמיתי.
  • metricsSummary שמוגדר רק לפלח הזה.
  • ‫splitType להגדרת גבולות הפיצול (למשל DISTANCE,‏ DURATION או MANUAL).

אירועי פעילות גופנית

כדי לחשב במדויק את משך הזמן הפעיל, צריך לעקוב אחרי מעברי מצב (כמו אירועי השהיה ידניים או אוטומטיים) באמצעות exerciseEvents.

כל אירוע מכיל את חותמת הזמן (eventTime) ואת הסוג:

  • ‫START / STOP: מציין את חותמות הזמן של הגבולות שבהם המשתמש התחיל או הפסיק את ההקלטה באופן מפורש.
  • ‫PAUSE / RESUME: מציין מתי הסשן הושהה או חודש באופן ידני.
  • ‫AUTO_PAUSE / AUTO_RESUME: מציין השהיות אוטומטיות או המשך אוטומטי שמופעלים על ידי חיישן.

כתיבת נתוני אימון

כדי ליצור, לעדכן או לייבא אימון, כותבים נקודה על הגרף לאוסף סוגי הנתונים של exercise. משתמשים בנקודת הקצה create dataPoints.

דוגמה לייצוג REST

בדוגמה הבאה אפשר לראות איך כותבים אימון באמצעות השיטה POST:

בקשה

POST https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints
Authorization: Bearer access-token
Content-Type: application/json

{
  "dataSource": {
    "recordingMethod": "ACTIVELY_MEASURED",
    "platform": "GOOGLE_WEB_API"
  },
  "exercise": {
    "interval": {
      "startTime": "2026-04-20T08:00:00Z",
      "startUtcOffset": "0s",
      "endTime": "2026-04-20T08:35:00Z",
      "endUtcOffset": "0s"
    },
    "exerciseType": "RUNNING",
    "activeDuration": "1800s",
    "metricsSummary": {
      "caloriesKcal": 380.0,
      "distanceMillimeters": 5000000.0,
      "steps": "6200",
      "averageHeartRateBeatsPerMinute": "148",
      "averagePaceSecondsPerMeter": 0.36
    },
    "exerciseEvents": [
      {
        "eventTime": "2026-04-20T08:15:00Z",
        "eventUtcOffset": "0s",
        "exerciseEventType": "PAUSE"
      },
      {
        "eventTime": "2026-04-20T08:20:00Z",
        "eventUtcOffset": "0s",
        "exerciseEventType": "RESUME"
      }
    ]
  }
}

תשובה

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4.DataPoint",
    "name": "users/999298779973222220/dataTypes/exercise/dataPoints/3054085373369111216",
    "dataSource": {
      "recordingMethod": "ACTIVELY_MEASURED",
      "application": {
        "googleWebClientId": "438076457939-example.apps.googleusercontent.com"
      },
      "platform": "GOOGLE_WEB_API"
    },
    "exercise": {
      "interval": {
        "startTime": "2026-04-20T08:00:00Z",
        "startUtcOffset": "0s",
        "endTime": "2026-04-20T08:35:00Z",
        "endUtcOffset": "0s"
      },
      "exerciseType": "RUNNING",
      "metricsSummary": {
        "caloriesKcal": 380,
        "distanceMillimeters": 5000000,
        "steps": "6200",
        "averagePaceSecondsPerMeter": 0.36,
        "averageHeartRateBeatsPerMinute": "148"
      },
      "exerciseMetadata": {},
      "displayName": "Run",
      "activeDuration": "1800s",
      "exerciseEvents": [
        {
          "eventTime": "2026-04-20T08:15:00Z",
          "eventUtcOffset": "0s",
          "exerciseEventType": "PAUSE"
        },
        {
          "eventTime": "2026-04-20T08:20:00Z",
          "eventUtcOffset": "0s",
          "exerciseEventType": "RESUME"
        }
      ],
      "updateTime": "2026-04-20T08:35:10.123456Z",
      "createTime": "2026-04-20T08:35:10.123456Z"
    }
  }
}

מסלולי GPS ומעקב אחר מיקום

ה-API שומר סיכומי סשנים בסיסיים ישירות בנקודת הנתונים exercise, אבל מטפל בהיסטוריית מיקומים מפורטת ובקואורדינטות של מסלול GPS כסטרימינג נפרד.

כדי להוריד את נתוני המסלול המפורטים של סשן בחוץ, צריך להפעיל את השיטה המותאמת אישית exportExerciseTcx. נקודת הקצה הזו מחזירה את המסלול בפורמט Training Center XML‏ (TCX), שהוא הפורמט המקובל בתחום.

ייצוא מסלול GPS

בקשה

GET https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints/exercise-data-point-id:exportExerciseTcx?alt=media
Authorization: Bearer access-token

תשובה

מטען ייעודי (payload) של HTTP עם Content-Type: application/tcx+xml ועם כותרות שמורות לדפדפן לשמור את הקובץ.

<?xml version="1.0" encoding="UTF-8"?>
<TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2">
  <Activities>
    <Activity Sport="Running">
      <Id>2026-04-20T08:00:00Z</Id>
      <Lap StartTime="2026-04-20T08:00:00Z">
        <TotalTimeSeconds>1800</TotalTimeSeconds>
        <DistanceMeters>5000</DistanceMeters>
        <Calories>380</Calories>
        <Intensity>Active</Intensity>
        <TriggerMethod>Manual</TriggerMethod>
        <Track>
          <Trackpoint>
            <Time>2026-04-20T08:00:00Z</Time>
            <Position>
              <LatitudeDegrees>37.7749</LatitudeDegrees>
              <LongitudeDegrees>-122.4194</LongitudeDegrees>
            </Position>
            <AltitudeMeters>15.0</AltitudeMeters>
            <DistanceMeters>0.0</DistanceMeters>
          </Trackpoint>
        </Track>
      </Lap>
    </Activity>
  </Activities>
</TrainingCenterDatabase>

היקפי ההרשאות והמיקום הנדרשים

כדי להשתמש בתכונה מסלולי GPS ומעקב אחר מיקום, האפליקציה צריכה לבקש את היקפי ההרשאות הבאים של OAuth:

  • קריאה: https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
  • כתיבה: https://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly
  • קריאה: https://www.googleapis.com/auth/googlehealth.location.readonly

הנחיות

כשמשלבים מעקב אחרי אימונים באפליקציה, צריך לפעול לפי ההנחיות הבאות לעיצוב ולהטמעה.

משך הזמן הפעיל לעומת משך הזמן הכולל

כדי לחשב מדדי מהירות או קצב, תמיד צריך להשתמש ב-activeDuration ולא בהפרש בין startTime ל-endTime. כך מרווחים מושהים לא מעוותים את המדדים.

לדוגמה, אם משתמש מתחיל אימון בשעה 08:00 ומסיים בשעה 08:35, משך הזמן הכולל של האימון הוא 2,100 שניות. אם המשתמש השהה את האימון למשך 5 דקות (300 שניות) וכללתם אירועים מסוג PAUSE ו-RESUME ב-exerciseEvents, משך הזמן הפעיל הוא "1800s" (2,100 פחות 300). ה-API משתמש במשך הפעילות כדי לחשב ממוצעים, ומחלק את המרחק הכולל ב-1,800 שניות במקום ב-2,100.

חישוב מהירות וקצב

‫Google Health API משתמש בנוסחאות סטנדרטיות כדי לחשב את המהירות והקצב:

  • מהירות = distance / time(hour)
  • קצב = time(seconds) / distance

הכותרת Accept-Language שצוינה בבקשה קובעת את יחידת המרחק.

בקשת מיקום בשלב מוקדם

אם האפליקציה ממפה מסלולי אימון, צריך לבקש הרשאות מיקום ואת ההיקף של Google Health location בנוסף להיקף של הפעילות והכושר. הסבירו למשתמשים למה האפליקציה צריכה את היקף ההרשאות למיקום כשבודקים אימונים עם GPS.

כשהאפליקציה מבקשת את היקף ההרשאות למיקום (https://www.googleapis.com/auth/googlehealth.location.readonly), מערכת Google OAuth מציגה למשתמש בקשה להסכמה. הסבירו למשתמשים שההרשאה הזו נדרשת כדי להציג שכבות-על של מסלולים ולייצא קובצי מעקב באמצעות GPS ‏(TCX). אם משתמש מעניק את היקף הפעילות אבל דוחה את הרשאת המיקום, הפונקציה exportExerciseTcx מחזירה שגיאת הרשאה, אבל עדיין אפשר לגשת לנתונים מצטברים של סשנים ב-metricsSummary.

סנכרון באמצעות תגובות לפעולה מאתר אחר (webhooks)

נרשמים לסוג הנתונים exercise כדי להודיע לקצה העורפי באמצעות תגובות לפעילות אינטרנט (webhooks) כשנתוני אימון חדשים זמינים. כך תוכלו להפעיל חוויות אחרי אימון באופן אוטומטי.

כשהשרת מקבל התראת webhook, היא מכילה את ה-healthUserId ואת מרווח הזמן האזרחי (civilIso8601TimeInterval) של האימון המעודכן. השרת צריך לאשר את ההתראה באופן מיידי באמצעות 204 No Content, לעבד את המטען הייעודי (payload) באופן אסינכרוני ולשלוח שאילתה לנקודת הקצה (endpoint) המותאמת של exercise באמצעות מסנן exercise.interval.civil_start_time (שימו לב ש-exercise תומך רק בסינון לפי civil_start_time):

GET https://health.googleapis.com/v4/users/healthUserId/dataTypes/exercise/dataPoints:reconcile?filter=exercise.interval.civil_start_time >= "2026-04-20T08:00:00" AND exercise.interval.civil_start_time < "2026-04-20T10:00:00"

במאמר מינויים ל-Webhook מוסבר איך מגדירים מינויים.

שמירה על מדדים עקביים

כדי לספק חוויית אימון מלאה, כדאי לכלול מדדי סיכום כשכותבים סשנים של exercise, ולשלוח שאילתות לנקודות הקצה של הטלמטריה לקריאה בלבד באמצעות מסננים של טווחי תאריכים כשמציגים תרשימים מפורטים.

כתיבת מדדים של סיכום אימון (נתיב כתיבה)

כשמייבאים או כותבים אימון שהושלם ל-Google Health API, צריך לכלול את מדדי הטלמטריה המצטברים של האימון (steps,‏ caloriesKcal,‏ distanceMillimeters,‏ averageHeartRateBeatsPerMinute ו-averagePaceSecondsPerMeter) בתוך האובייקט metricsSummary של נקודה על הגרף exercise:

  • POST https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints

שאילתות על נתונים מפורטים לתרשימים (נתיב קריאה)

כדי ליצור מרכזי בקרה או תרשימים של אימונים לסשן ספציפי, שולחים שאילתה לנקודות הקצה של נתוני הטלמטריה שתואמים לחלון הזמן של האימון:

  1. אחזור של סשן האימון מנקודת הקצה exercise באמצעות מסנן civil_start_time כדי לקבל את הערכים interval ו-metricsSummary:

    GET https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints:reconcile?filter=exercise.interval.civil_start_time >= "2026-04-20T00:00:00" AND exercise.interval.civil_start_time < "2026-04-21T00:00:00"
  2. משתמשים ב-interval.startTime וב-interval.endTime של הסשן כדי לשלוח שאילתות לנקודות הקצה של נתוני הטלמטריה בחלון הזמן הפיזי הזה.

  3. אם הערך של exerciseMetadata.hasGps הוא true, צריך להפעיל את exportExerciseTcx כדי להוריד את הקואורדינטות של המסלול.