Work with Sessions

Sessions represent a time interval during which users perform a fitness activity. The Sessions API enables your app to create sessions in the fitness store using real time data or data you previously collected using the Sensors API or outside Google Fit.

For ongoing fitness activities where the user notifies your app when he or she starts and finishes a fitness activity, you can create sessions in real time.

You can also insert a session into the fitness store after a fitness activity finished, or when you are importing data and sessions from outside Google Fit.

Create sessions in real time

To create sessions for ongoing fitness activities:

  1. Subscribe to fitness data with the RecordingApi.subscribe method.
  2. Start a session with the SessionsApi.startSession method when the user initiates the fitness activity.
  3. Stop the session with the SessionsApi.stopSession method when the user ends the fitness activity.
  4. Unsubscribe from fitness data you are no longer interested in with the RecordingApi.unsubscribe method.

Start a session

To start a session in your app, use the SessionsApi.startSession method:

// 1. Subscribe to fitness data (see Recording Fitness Data)

// 2. Create a session object
// (provide a name, identifier, description and start time)
Session session = new Session.Builder()
    .setName(sessionName)
    .setIdentifier(identifier)
    .setDescription(description)
    .setStartTime(startTime.getMillis(), TimeUnit.MILLISECONDS)
    // optional - if your app knows what activity:
    .setActivity(FitnessActivities.RUNNING)
    .build();

// 3. Invoke the Sessions API with:
// - The Google API client object
// - The request object
PendingResult<Status> pendingResult =
    Fitness.SessionsApi.startSession(mClient, session);

// 4. Check the result (see other examples)

Stop a session

To stop a session in your app, use the SessionsApi.stopSession method:

// 1. Invoke the Sessions API with:
// - The Google API client object
// - The name of the session
// - The session indentifier
PendingResult<SessionStopResult> pendingResult =
    Fitness.SessionsApi.stopSession(mClient, session.getIdentifier());

// 2. Check the result (see other examples)

// 3. Unsubscribe from fitness data (see Recording Fitness Data)

The resulting session has these parameters:

Insert sessions in the fitness store

To insert sessions with data you previously collected:

  1. Create a Session object specifying a time interval and other required information.
  2. Create a SessionInsertRequest with the session and optionally add datasets and aggreagte data points.
  3. Insert the session with the SessionsApi.insertSession. method.

Insert a session

To insert fitness data with session metadata into the user's fitness history, first create a SessionInsertRequest instance:

// 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(speedDataSet)
        .addDataSet(activitySegments)
        .build();

The SessionInsertRequest class provides convenience methods to insert data into the fitness history and create a session in the same call to SessionsApi.insertSession, since this is a common use case when importing data. The datasets (if any) are inserted as if you had called the HistoryApi.insertData method first, and then the session is created.

// Then, invoke the Sessions API to insert the session and await the result,
// which is possible here because of the AsyncTask. Always include a timeout when
// calling await() to avoid hanging that can occur from the service being shutdown
// because of low memory or other conditions.
Log.i(TAG, "Inserting the session in the History API");
com.google.android.gms.common.api.Status insertStatus =
        Fitness.SessionsApi.insertSession(mClient, insertRequest)
                .await(1, TimeUnit.MINUTES);

// Before querying the session, check to see if the insertion succeeded.
if (!insertStatus.isSuccess()) {
    Log.i(TAG, "There was a problem inserting the session: " +
            insertStatus.getStatusMessage());
    return null;
}

// At this point, the session has been inserted and can be read.
Log.i(TAG, "Session insert was successful!");

Insert activity segments

Activity segment data in Google Fit indicates what fitness activity users are performing in a given time interval. Activity segment data is of type com.google.activity.segment (TYPE_ACTIVITY_SEGMENT) and is particularly useful to support pauses during workouts.

For example, if you create a 30-minute running session with the Session.Builder.setActivity() method but the user takes a 10-minute break in between, your app will incorrectly show that the user run for 30 minutes. Provided your app can detect whether the user was walking or running, activity segment data lets your app indicate that the user was running for 10 minutes, walking for 10 minutes, and running for 10 minutes. Other apps can also report the activity correctly by looking at the activity segment data you inserted.

To add activity segment data to a session, you create an additional dataset that contains points of type com.google.activity.segment. Each of these points represents a continous time interval during which the user was performing a single activity type. The previous running and walking example would require three activity segment points: one for running during the first 10 minutes, one for walking during the next 10 minutes, and one for running during the final 10 minutes.

// Create a second DataSet of ActivitySegments to indicate the runner took a 10-minute walk
// in the middle of the run.
DataSource activitySegmentDataSource = new DataSource.Builder()
        .setAppPackageName(this.getPackageName())
        .setDataType(DataType.TYPE_ACTIVITY_SEGMENT)
        .setName(SAMPLE_SESSION_NAME + "-activity segments")
        .setType(DataSource.TYPE_RAW)
        .build();
DataSet activitySegments = DataSet.create(activitySegmentDataSource);

DataPoint firstRunningDp = activitySegments.createDataPoint()
        .setTimeInterval(startTime, startWalkTime, TimeUnit.MILLISECONDS);
firstRunningDp.getValue(Field.FIELD_ACTIVITY).setActivity(FitnessActivities.RUNNING);
activitySegments.add(firstRunningDp);

DataPoint walkingDp = activitySegments.createDataPoint()
        .setTimeInterval(startWalkTime, endWalkTime, TimeUnit.MILLISECONDS);
walkingDp.getValue(Field.FIELD_ACTIVITY).setActivity(FitnessActivities.WALKING);
activitySegments.add(walkingDp);

DataPoint secondRunningDp = activitySegments.createDataPoint()
        .setTimeInterval(endWalkTime, endTime, TimeUnit.MILLISECONDS);
secondRunningDp.getValue(Field.FIELD_ACTIVITY).setActivity(FitnessActivities.RUNNING);
activitySegments.add(secondRunningDp);

// 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(speedDataSet)
        .addDataSet(activitySegments)
        .build();

Read fitness data using sessions

The Sessions API lets you obtain a list of sessions from the fitness store that match some criteria. For example, you can obtain all the sessions contained in a time interval for a particular data, or get a particular session by name or ID. You can also specify if you are interested in sessions created by your app or by any app.

To obtain a list of sessions that match some criteria, first create a SessionReadRequest instance:

// Set a start and end time for our query, using a start time of 1 week before this moment.
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.WEEK_OF_YEAR, -1);
long startTime = cal.getTimeInMillis();

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

Then use the SessionsApi.readSession method:

// Invoke the Sessions API to fetch the session with the query and wait for the result
// of the read request. Note: Fitness.SessionsApi.readSession() requires the
// ACCESS_FINE_LOCATION permission.
SessionReadResult sessionReadResult =
        Fitness.SessionsApi.readSession(mClient, readRequest)
                .await(1, TimeUnit.MINUTES);

// Get a list of the sessions that match the criteria to check the result.
Log.i(TAG, "Session read was successful. Number of returned sessions is: "
        + sessionReadResult.getSessions().size());
for (Session session : sessionReadResult.getSessions()) {
    // Process the session
    dumpSession(session);

    // Process the data sets for this session
    List<DataSet> dataSets = sessionReadResult.getDataSet(session);
    for (DataSet dataSet : dataSets) {
        dumpDataSet(dataSet);
    }
}

Show sessions in other apps

To show users a more detailed view of a particular session in a different app, your app can fire an intent with the session information. You can specify a particular app (like the app that created the session), or you can let any app that can show data from that fitness activity respond to the intent if the app that created the session is not installed on the device. Your app can also register an intent filter to display detailed session data from some activity types.

To create an intent to show session data on a different app, use the SessionsApi.ViewIntentBuilder class:

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

// Fire the intent
startActivity(intent);

To register a listener in your app for the types of session data your app can show, include an intent filter like the following for your activity in the manifest file:

<activity android:name="com.example.ViewSessionActivity" android:exported="true">
    <intent-filter>
        <action android:name="vnd.google.fitness.VIEW" />
        <data android:mimeType="vnd.google.fitness.session/biking" />
        <data android:mimeType="vnd.google.fitness.session/running" />
    </intent-filter>
</activity>

Session broadcast intents

Google Fit broadcasts intents when any app starts or stops recording a session on behalf of the user. Fitness apps can register a listener to receive these intents.

Session start intents

When you start recording a session, Google Fit broadcasts an intent with:

  • The action set to ACTION_SESSION_START
  • The type set to MIME_ACTIVITY_TYPE_PREFIX/<activity_type>
  • The EXTRA_SESSION extra set to the new session

activity_type is the constant string value for the activity associated with this session (see the API reference for FitnessActivities).

To register a listener in your app for session start intents with activity type RUNNING, add the following to your manifest file:

<receiver android:name="com.example.SessionStartBroadcastReceiver" >
    <intent-filter>
        <action android:name="com.google.android.gms.fitness.session_start" />
        <data android:mimeType="vnd.google.fitness.activity_type/running" />
    </intent-filter>
</receiver>

Session end intents

When an app stops recording a session, Google Fit broadcasts an intent with:

  • The action set to ACTION_SESSION_END
  • The type set to MIME_ACTIVITY_TYPE_PREFIX/<activity_type>
  • The EXTRA_SESSION extra set to the session

To register a listener in your app for session end intents with activity type RUNNING, add the following your manifest file:

<receiver android:name="com.example.SessionEndBroadcastReceiver" >
    <intent-filter>
        <action android:name="com.google.android.gms.fitness.session_end" />
        <data android:mimeType="vnd.google.fitness.activity_type/running" />
    </intent-filter>
</receiver>

Send feedback about...