עבודה עם סשנים

סשנים מייצגים מרווח זמן שבו משתמשים מבצעים פעילות כושר. ה-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));

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

  • שעת התחלה: השעה שבה האפליקציה שלך נקראה בשיטה SessionsClient.startSession.

  • שעת סיום: השעה שבה האפליקציה קראה לשיטה 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();

לאחר מכן, תוכלו להשתמש בשיטה 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));

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

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

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

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

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

כדי ליצור כוונה להציג נתוני סשנים באפליקציה אחרת, צריך להשתמש בכיתה 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>

כל כוונה שהאפליקציה מקבלת מ-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());
    }
}