[Sessions](https://developers.google.com/fit/android/sessions) represent a time interval during which users
perform a fitness activity. The Sessions API lets your app create sessions in
the fitness store.

For ongoing fitness activities where the user notifies your app when they start
and finish a fitness activity, you can create sessions in real time.

You can also insert a session into the fitness store after a fitness activity
finishes or when you import data and sessions from outside Google Fit.

> [!NOTE]
> **Note:** For best practices when you manage user data, see [Google Fit Developer and User Data Policy](https://developers.google.com/fit/policy).

## Create sessions in real time

To create sessions for ongoing fitness activities, complete the following steps:

1. [Subscribe to fitness data](https://developers.google.com/fit/android/record#subscribe)
   using the [`RecordingClient.subscribe`](https://developers.google.com/android/reference/com/google/android/gms/fitness/RecordingClient)
   method.

2. [Start a session](https://developers.google.com/fit/android/using-sessions#start-session) using the
   [`SessionsClient.startSession`](https://developers.google.com/android/reference/com/google/android/gms/fitness/SessionsClient#public-taskvoid-startsession-session-session)
   method when the user initiates the fitness activity.

3. [Stop the session](https://developers.google.com/fit/android/using-sessions#stop-session) using the
   [`SessionsClient.stopSession`](https://developers.google.com/android/reference/com/google/android/gms/fitness/SessionsClient#public-tasklistsession-stopsession-string-identifier)
   method when the user ends the fitness activity.

4. [Unsubscribe from the fitness data](https://developers.google.com/fit/android/record#unsubscribe)
   that you're no longer interested in using the
   [`RecordingClient.unsubscribe`](https://developers.google.com/android/reference/com/google/android/gms/fitness/RecordingClient#public-taskvoid-unsubscribe-subscription-subscription)
   method.

## Start a session

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

### Kotlin

```kotlin
// 1. https://developers.google.com/fit/android/record#subscribe
// 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

```java
// 1. https://developers.google.com/fit/android/record#subscribe
// 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));
```

## Stop a session

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

### Kotlin

```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
        // https://developers.google.com/fit/android/record)
    }
    .addOnFailureListener { e ->
        Log.w(TAG, "There was an error stopping the session", e)
    }
```

### Java

```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
            // https://developers.google.com/fit/android/record)
        })
        .addOnFailureListener(e ->
                Log.w(TAG, "There was an error stopping the session", e));
```

The resulting session has the following parameters:

- Start time: The time when your app called the `SessionsClient.startSession`
  method.

- End time: The time when your app called the `SessionsClient.stopSession`
  method.

- Name: The name in the `Session` object that you pass to
  `SessionsClient.startSession`.

## Insert sessions in the fitness store

To insert sessions with data you previously collected, do the following:

1. Create a `Session` object that specifies a time interval and other required
   information.

2. Create a
   [`SessionInsertRequest`](https://developers.google.com/android/reference/com/google/android/gms/fitness/request/SessionInsertRequest)
   with the session.

3. Optionally, add datasets and aggregate data points.

4. Insert the session using the
   [`SessionsClient.insertSession`](https://developers.google.com/android/reference/com/google/android/gms/fitness/SessionsClient#public-taskvoid-insertsession-sessioninsertrequest-request)
   method.

### Insert a session

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

### Kotlin

```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

```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();
```

The `SessionInsertRequest` class provides convenience methods to insert data
into the fitness history and create a session in the same call to
`SessionsClient.insertSession`. The datasets, if any, are inserted as if you
had called the
[`HistoryClient.insertData`](https://developers.google.com/android/reference/com/google/android/gms/fitness/HistoryClient#public-taskvoid-insertdata-dataset-dataset)
method first, and then the session is created.

### Kotlin

```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

```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));
```

### Insert activity segments

Activity segment data in Google Fit indicates what fitness activity
users are performing throughout a given time interval. Activity segment data is
of type `com.google.activity.segment`
([`TYPE_ACTIVITY_SEGMENT`](https://developers.google.com/android/reference/com/google/android/gms/fitness/data/DataType#public-static-final-datatype-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()`](https://developers.google.com/android/reference/com/google/android/gms/fitness/data/Session.Builder#public-session.builder-setactivity-string-activity)
method but the user takes a 10-minute break in between, your app will
incorrectly show that the user ran for 30 minutes. Provided that your app can
detect whether the user was walking or running, activity segment data lets your
app indicate that the user ran for 10 minutes, walked for 10 minutes, then ran
for an additional 10 minutes. Other apps can also report the activity correctly
by looking at the activity segment data you insert.

To add activity segment data to a session, create a dataset that contains points
of type `com.google.activity.segment`. Each of these points represents a
continuous time interval during which the user performed 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.

### Kotlin

```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

```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();
```

## 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, or get a particular session by name or ID. You can also specify
whether you're interested in sessions created by your app or by any app.

> [!NOTE]
> **Note:** When you read sessions created by other apps, you're encouraged to show users which apps contributed the sessions so users know where that data came from. You can obtain the contributing app name and icon, along with an intent to launch the app, as described in [Data Attribution](https://developers.google.com/fit/android/data-attribution).

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

### Kotlin

```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

```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();
```

Then use the
[`SessionsClient.readSession`](https://developers.google.com/android/reference/com/google/android/gms/fitness/SessionsClient#public-tasksessionreadresponse-readsession-sessionreadrequest-request)
method:

### Kotlin

```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

```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));
```

## Read sleep data using sessions

Sleep sessions are treated as distinct from other activity sessions. By default,
read responses contain only activity sessions, not sleep sessions.

To include sleep sessions, use the
[`includeSleepSessions`](https://developers.google.com/android/reference/com/google/android/gms/fitness/request/SessionReadRequest.Builder#includeSleepSessions())
method when you build your `SessionReadRequest`. To include both activities and
sessions, use both `includeSleepSessions` and
[`includeActivitySessions`](https://developers.google.com/android/reference/com/google/android/gms/fitness/request/SessionReadRequest.Builder#includeActivitySessions()).

## Show sessions in other apps

To show users a more detailed view of a particular session in a different app,
your app can invoke an intent that contains the session information. You can
specify a particular app, like the app that created the session. Or, in case the
app that created the session isn't installed on the device, you can allow any
app that can show fitness activity to respond to the intent.

To create an intent to show session data on a different app, use the
[`SessionsApi.ViewIntentBuilder`](https://developers.google.com/android/reference/com/google/android/gms/fitness/SessionsApi.ViewIntentBuilder)
class:

### Kotlin

```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

```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);
```

## Receive intents from other apps

To register your app to receive intents from other health and wellness apps,
declare an intent filter in your manifest that's similar to the following:

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

> [!NOTE]
> **Note:** Don't include the `DEFAULT` category in your intent filter, unless you want your app to receive intents for sessions created by other apps.

Each intent that your app receives from Google Fit is of only one
activity, but you can filter for multiple MIME types in a single intent filter.
Your app's intent filter needs to include all of the activities that your app
supports.

The fitness intents include the following extras:

- `vnd.google.gms.fitness.start_time`
- `vnd.google.gms.fitness.end_time`
- `vnd.google.gms.fitness.session`

You can obtain data from these extras as follows:

### Kotlin

```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

```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());
    }
}
```