עבודה עם ביקורים

סשנים מייצגים מרווח זמן שבמהלכו משתמשים מבצעים פעילות כושר. ה-Sessions API מאפשר לאפליקציה ליצור פעילויות בחנות הכושר.

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

ניתן גם להוסיף פעילות לחנות הכושר אחרי שפעילות כושר כלשהי הסתיימה או כשמייבאים נתונים וסשנים מחוץ ל-Google Fit.

יצירת סשנים בזמן אמת

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

  1. הרשמה לנתוני הכושר באמצעות השיטה RecordingClient.subscribe.

  2. התחלת סשן באמצעות השיטה SessionsClient.startSession כשהמשתמש מתחיל את פעילות הכושר.

  3. להפסיק את הסשן באמצעות השיטה SessionsClient.stopSession כשהמשתמש מסיים את פעילות הכושר.

  4. לבטל את ההרשמה לנתוני הכושר שאתם לא רוצים יותר להשתמש בהם בשיטת RecordingClient.unsubscribe.

להתחלת סשן

כדי להתחיל סשן באפליקציה, צריך להשתמש בשיטה SessionsClient.startSession:

Kotlin

// 1. Subscribe to fitness data
// 2. Create a session object
// (provide a name, identifier, description, activity and start time)
val session = Session.Builder()
    .setName(sessionName)
    .setIdentifier("UniqueIdentifierHere")
    .setDescription("Morning run")
    .setActivity(FitnessActivities.RUNNING)
    .setStartTime(startTime, TimeUnit.MILLISECONDS)
    .build()

// 3. Use the Sessions client to start a session:
Fitness.getSessionsClient(this, googleSigninAccount)
    .startSession(session)
    .addOnSuccessListener {
        Log.i(TAG, "Session started successfully!")
    }
    .addOnFailureListener { e ->
        Log.w(TAG, "There was an error starting the session", e)
    }

Java

// 1. Subscribe to fitness data
// 2. Create a session object
// (provide a name, identifier, description, activity and start time)
Session session = new Session.Builder()
        .setName(sessionName)
        .setIdentifier("UniqueIdentifierHere")
        .setDescription("Morning run")
        .setActivity(FitnessActivities.RUNNING)
        .setStartTime(startTime, TimeUnit.MILLISECONDS)
        .build();

// 3. Use the Sessions client to start a session:
Fitness.getSessionsClient(this, googleSigninAccount)
        .startSession(session)
        .addOnSuccessListener(unused ->
                Log.i(TAG, "Session started successfully!"))
        .addOnFailureListener(e ->
                Log.w(TAG, "There was an error starting the session", e));

עצירת סשן

כדי להפסיק סשן באפליקציה, צריך להשתמש בשיטה SessionsClient.stopSession:

Kotlin

// Invoke the SessionsClient with the session identifier
Fitness.getSessionsClient(this, googleSigninAccount)
    .stopSession(session.getIdentifier())
    .addOnSuccessListener {
        Log.i(TAG, "Session stopped successfully!")

        // Now unsubscribe from the fitness data (see
        // Recording Fitness data)
    }
    .addOnFailureListener { e ->
        Log.w(TAG, "There was an error stopping the session", e)
    }

Java

// Invoke the SessionsClient with the session identifier
Fitness.getSessionsClient(this, googleSigninAccount)
        .stopSession(session.getIdentifier())
        .addOnSuccessListener (unused -> {
            Log.i(TAG, "Session stopped successfully!");
            // Now unsubscribe from the fitness data (see
            // Recording Fitness data)
        })
        .addOnFailureListener(e ->
                Log.w(TAG, "There was an error stopping the session", e));

הסשן שנוצר כולל את הפרמטרים הבאים:

  • שעת התחלה: השעה שבה האפליקציה קראה ל-method SessionsClient.startSession.

  • שעת סיום: השעה שבה האפליקציה קראה ל-method SessionsClient.stopSession.

  • שם: השם באובייקט Session שמעבירים אל SessionsClient.startSession.

הוספת פעילויות בחנות הכושר

כדי להוסיף ביקורים עם נתונים שנאספו בעבר:

  1. יוצרים אובייקט Session שמציין מרווח זמן ומידע נדרש נוסף.

  2. יצירת SessionInsertRequest עם הסשן.

  3. אפשר להוסיף מערכי נתונים ונקודות על הגרף.

  4. מוסיפים את הסשן באמצעות השיטה SessionsClient.insertSession.

הוספת סשן

כדי להוסיף נתוני כושר שמכילים מטא-נתונים של סשנים להיסטוריית הכושר של המשתמש, קודם צריך ליצור מופע של SessionInsertRequest:

Kotlin

// Create a session with metadata about the activity.
val session = Session.Builder()
    .setName(SAMPLE_SESSION_NAME)
    .setIdentifier("UniqueIdentifierHere")
    .setDescription("Long run around Shoreline Park")

    .setActivity(FitnessActivities.RUNNING)
    .setStartTime(startTime, TimeUnit.MILLISECONDS)
    .setEndTime(endTime, TimeUnit.MILLISECONDS)
    .build()

// Build a session insert request
val insertRequest = SessionInsertRequest.Builder()
    .setSession(session)
    // Optionally add DataSets for this session.
    .addDataSet(dataset)
    .build()

Java

// Create a session with metadata about the activity.
Session session = new Session.Builder()
        .setName(SAMPLE_SESSION_NAME)
        .setIdentifier("UniqueIdentifierHere")
        .setDescription("Long run around Shoreline Park")

        .setActivity(FitnessActivities.RUNNING)
        .setStartTime(startTime, TimeUnit.MILLISECONDS)
        .setEndTime(endTime, TimeUnit.MILLISECONDS)
        .build();

// Build a session insert request
SessionInsertRequest insertRequest = new SessionInsertRequest.Builder()
        .setSession(session)
        // Optionally add DataSets for this session.
        .addDataSet(dataset)
        .build();

בכיתה SessionInsertRequest יש שיטות נוחות שמאפשרות להוסיף נתונים להיסטוריית הכושר וליצור סשן באותה שיחה אל SessionsClient.insertSession. מערכי הנתונים, אם יש, מתווספים כאילו קראתם קודם את השיטה HistoryClient.insertData, ואז סשן נוצר.

Kotlin

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
    .insertSession(insertRequest)
    .addOnSuccessListener {
        Log.i(TAG, "Session insert was successful!")
    }
    .addOnFailureListener { e ->
        Log.w(TAG, "There was a problem inserting the session: ", e)
    }

Java

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
        .insertSession(insertRequest)
        .addOnSuccessListener (unused ->
                Log.i(TAG, "Session insert was successful!"))
        .addOnFailureListener(e ->
        Log.w(TAG, "There was a problem inserting the session: ", e));

הוספת מקטעי פעילות

הנתונים לגבי 'פלחי פעילות' ב-Google Fit מציינים את פעילות הכושר שהמשתמשים מבצעים במהלך פרק זמן נתון. הנתונים לגבי פלח הפעילות הם מסוג com.google.activity.segment (TYPE_ACTIVITY_SEGMENT) והם שימושיים במיוחד כדי לעזור בהשהיות במהלך אימוני כושר.

לדוגמה, אם יצרתם סשן ריצה של 30 דקות בשיטה Session.Builder.setActivity() אבל המשתמש יוצא להפסקה של 10 דקות ביניהן, האפליקציה תציג באופן שגוי שהמשתמש פעל במשך 30 דקות. בתנאי שהאפליקציה יכולה לזהות אם המשתמש הולך או רץ, נתוני פלח הפעילות מאפשרים לאפליקציה לציין שהמשתמש רצה במשך 10 דקות, הלך במשך 10 דקות ואז רץ במשך 10 דקות נוספות. אפליקציות אחרות יכולות גם לדווח על הפעילות כמו שצריך על ידי עיון בנתונים של פלח הפעילות שהוספתם.

כדי להוסיף נתונים של פלח פעילות לסשן, צריך ליצור מערך נתונים שמכיל נקודות מסוג com.google.activity.segment. כל אחת מהנקודות האלה מייצגת מרווח זמן רציף שבמהלכו המשתמש ביצע סוג פעילות אחד.

בדוגמה הקודמת של ריצה והליכה, נדרשות שלוש נקודות בקטעי פעילות: אחת לריצה במהלך 10 הדקות הראשונות, אחת להליכה ב-10 הדקות הבאות ואחת לריצה במהלך 10 הדקות האחרונות.

Kotlin

// Create a DataSet of ActivitySegments to indicate the runner walked for
// 10 minutes in the middle of a run.
val activitySegmentDataSource = DataSource.Builder()
    .setAppPackageName(this.packageName)
    .setDataType(DataType.TYPE_ACTIVITY_SEGMENT)
    .setStreamName(SAMPLE_SESSION_NAME + "-activity segments")
    .setType(DataSource.TYPE_RAW)
    .build()

val firstRunningDp = DataPoint.builder(activitySegmentDataSource)
    .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
    .setTimeInterval(startTime, startWalkTime, TimeUnit.MILLISECONDS)
    .build()

val walkingDp = DataPoint.builder(activitySegmentDataSource)
    .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.WALKING)
    .setTimeInterval(startWalkTime, endWalkTime, TimeUnit.MILLISECONDS)
    .build()

val secondRunningDp = DataPoint.builder(activitySegmentDataSource)
    .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
    .setTimeInterval(endWalkTime, endTime, TimeUnit.MILLISECONDS)
    .build()

val activitySegments = DataSet.builder(activitySegmentDataSource)
    .addAll(listOf(firstRunningDp, walkingDp, secondRunningDp))
    .build()

// Create a session with metadata about the activity.
val session = Session.Builder()
    .setName(SAMPLE_SESSION_NAME)
    .setDescription("Long run around Shoreline Park")
    .setIdentifier("UniqueIdentifierHere")
    .setActivity(FitnessActivities.RUNNING)
    .setStartTime(startTime, TimeUnit.MILLISECONDS)
    .setEndTime(endTime, TimeUnit.MILLISECONDS)
    .build()

// Build a session insert request
val insertRequest = SessionInsertRequest.Builder()
    .setSession(session)
    .addDataSet(activitySegments)
    .build()

Java

// Create a DataSet of ActivitySegments to indicate the runner walked for
// 10 minutes in the middle of a run.
DataSource activitySegmentDataSource = new DataSource.Builder()
        .setAppPackageName(getPackageName())
        .setDataType(DataType.TYPE_ACTIVITY_SEGMENT)
        .setStreamName(SAMPLE_SESSION_NAME + "-activity segments")
        .setType(DataSource.TYPE_RAW)
        .build();

DataPoint firstRunningDp = DataPoint.builder(activitySegmentDataSource)
        .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
        .setTimeInterval(startTime, startWalkTime, TimeUnit.MILLISECONDS)
        .build();

DataPoint walkingDp = DataPoint.builder(activitySegmentDataSource)
        .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.WALKING)
        .setTimeInterval(startWalkTime, endWalkTime, TimeUnit.MILLISECONDS)
        .build();

DataPoint secondRunningDp = DataPoint.builder(activitySegmentDataSource)
        .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
        .setTimeInterval(endWalkTime, endTime, TimeUnit.MILLISECONDS)
        .build();

DataSet activitySegments = DataSet.builder(activitySegmentDataSource)
        .addAll(Arrays.asList(firstRunningDp, walkingDp, secondRunningDp))
        .build();

// Create a session with metadata about the activity.
Session session = new Session.Builder()
        .setName(SAMPLE_SESSION_NAME)
        .setDescription("Long run around Shoreline Park")
        .setIdentifier("UniqueIdentifierHere")
        .setActivity(FitnessActivities.RUNNING)
        .setStartTime(startTime, TimeUnit.MILLISECONDS)
        .setEndTime(endTime, TimeUnit.MILLISECONDS)
        .build();

// Build a session insert request
SessionInsertRequest insertRequest = new SessionInsertRequest.Builder()
        .setSession(session)
        .addDataSet(activitySegments)
        .build();

קריאת נתוני כושר גופני באמצעות פעילויות באתר

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

כדי לקבל רשימת סשנים שתואמים לקריטריונים מסוימים, קודם יוצרים מכונת SessionReadRequest:

Kotlin

// Use a start time of 1 week ago and an end time of now.
val endTime = LocalDateTime.now().atZone(ZoneId.systemDefault())
val startTime = endTime.minusWeeks(1)

// Build a session read request
val readRequest = SessionReadRequest.Builder()
    .setTimeInterval(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.SECONDS)
    .read(DataType.TYPE_SPEED)
    .setSessionName(SAMPLE_SESSION_NAME)
    .build()

Java

// Use a start time of 1 week ago and an end time of now.
ZonedDateTime endTime = LocalDateTime.now().atZone(ZoneId.systemDefault())
ZonedDateTime startTime = endTime.minusWeeks(1)

// Build a session read request
SessionReadRequest readRequest = new SessionReadRequest.Builder()
        .setTimeInterval(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.SECONDS)
        .read(DataType.TYPE_SPEED)
        .setSessionName(SAMPLE_SESSION_NAME)
        .build();

לאחר מכן משתמשים ב-method SessionsClient.readSession:

Kotlin

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
    .readSession(readRequest)
    .addOnSuccessListener { response ->
        // Get a list of the sessions that match the criteria to check the result.
        val sessions = response.sessions
        Log.i(TAG, "Number of returned sessions is: ${sessions.size}")
        for (session in sessions) {
            // Process the session
            dumpSession(session)

            // Process the data sets for this session
            val dataSets = response.getDataSet(session)
            for (dataSet in dataSets) {
                // ...
            }
        }
    }
    .addOnFailureListener { e ->
        Log.w(TAG,"Failed to read session", e)
    }

Java

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
        .readSession(readRequest)
        .addOnSuccessListener(response -> {
            // Get a list of the sessions that match the criteria to check the
            // result.
            List<Session> sessions = response.getSessions();
            Log.i(TAG, "Number of returned sessions is: ${sessions.size}");
            for (Session session : sessions) {
                // Process the session
                dumpSession(session);

                // Process the data sets for this session
                List<DataSet> dataSets = response.getDataSet(session);
                for (DataSet dataSet : dataSets) {
                    // ...
                }
            }
        })
        .addOnFailureListener(e ->
                Log.w(TAG,"Failed to read session", e));

קריאת נתוני השינה באמצעות סשנים

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

כדי לכלול סשנים של שינה, צריך להשתמש ב-method includeSleepSessions כשיוצרים את SessionReadRequest. כדי לכלול גם פעילויות וגם סשנים, צריך להשתמש גם ב-includeSleepSessions וגם ב-includeActivitySessions.

הצגת סשנים באפליקציות אחרות

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

כדי ליצור אובייקט Intent להצגת נתוני סשנים באפליקציה אחרת, צריך להשתמש במחלקה SessionsApi.ViewIntentBuilder:

Kotlin

// Pass your activity object to the constructor
val intent = SessionsApi.ViewIntentBuilder(this)
    .setPreferredApplication("com.example.someapp") // optional
    .setSession(session)
    .build()

// Invoke the intent
startActivity(intent)

Java

// Pass your activity object to the constructor
Intent intent = new SessionsApi.ViewIntentBuilder(this)
        .setPreferredApplication("com.example.someapp") // optional
        .setSession(session)
        .build();

// Invoke the intent
startActivity(intent);

קבלת כוונות מאפליקציות אחרות

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

<intent-filter>
    <action android:name="vnd.google.fitness.VIEW"/>
    <data android:mimeType="vnd.google.fitness.session/running"/>
</intent-filter>

כל Intent שהאפליקציה שלכם מקבלת מ-Google Fit כוללת פעילות אחת בלבד, אבל ניתן לסנן לפי מספר סוגי MIME במסנן Intent יחיד. מסנן Intent של האפליקציה צריך לכלול את כל הפעילויות שהאפליקציה תומכת בה.

כוונות הכושר כוללות את התוספות הבאות:

  • vnd.google.gms.fitness.start_time
  • vnd.google.gms.fitness.end_time
  • vnd.google.gms.fitness.session

אפשר לקבל נתונים מתוספות אלה באופן הבא:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    val supportedType = Session.getMimeType(FitnessActivities.RUNNING)

    if (Intent.ACTION_VIEW == intent.action && supportedType == intent.type) {
        // Get the intent extras
        val startTime = Fitness.getStartTime(intent, TimeUnit.MILLISECONDS);
        val endTime = Fitness.getEndTime(intent, TimeUnit.MILLISECONDS)
        val session = Session.extract(intent)
    }
}

Java

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...

    String supportedType = Session.getMimeType(FitnessActivities.RUNNING);

    if (Intent.ACTION_VIEW.equals(getIntent().getAction()) && supportedType.equals(getIntent().getType())) {
        // Get the intent extras
        long startTime = Fitness.getStartTime(getIntent(), TimeUnit.MILLISECONDS);
        long endTime = Fitness.getEndTime(getIntent(), TimeUnit.MILLISECONDS);
        Session session = Session.extract(getIntent());
    }
}