Trabaja con sesiones

Las sesiones representan un intervalo de tiempo durante el cual los usuarios realizan una actividad de entrenamiento. La API de Sessions permite que tu app cree sesiones en la tienda de entrenamiento.

Para actividades de fitness en curso en las que el usuario notifica a tu app cuando comienza y finaliza una actividad de entrenamiento, puedes crear sesiones en tiempo real.

También puedes insertar una sesión en la tienda de entrenamiento después de que finalice una actividad física o cuando importes datos y sesiones que no pertenezcan a Google Fit.

Crea sesiones en tiempo real

Para crear sesiones de actividades físicas en curso, completa los siguientes pasos:

  1. Suscríbete a datos de entrenamiento con el método RecordingClient.subscribe.

  2. Inicia una sesión con el método SessionsClient.startSession cuando el usuario inicie la actividad de entrenamiento.

  3. Detén la sesión con el método SessionsClient.stopSession cuando el usuario finalice la actividad de entrenamiento.

  4. Anula la suscripción a los datos de entrenamiento que ya no te interesan con el método RecordingClient.unsubscribe.

Cómo iniciar una sesión

Para iniciar una sesión en tu app, usa el método 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));

Cómo detener una sesión

Para detener una sesión en tu app, usa el método 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));

La sesión resultante tiene los siguientes parámetros:

  • Hora de inicio: Es la hora en que la app llamó al método SessionsClient.startSession.

  • Hora de finalización: Es la hora en que la app llamó al método SessionsClient.stopSession.

  • Nombre: Es el nombre en el objeto Session que pasas a SessionsClient.startSession.

Insertar sesiones en la tienda de entrenamiento

Para insertar sesiones con datos que recopilaste anteriormente, haz lo siguiente:

  1. Crea un objeto Session que especifique un intervalo de tiempo y otra información obligatoria.

  2. Crea un SessionInsertRequest con la sesión.

  3. De forma opcional, puedes agregar conjuntos de datos y datos agregados.

  4. Inserta la sesión con el método SessionsClient.insertSession.

Cómo insertar una sesión

Para insertar datos de entrenamiento que contengan metadatos de sesión en el historial de entrenamiento del usuario, primero crea una instancia de 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();

La clase SessionInsertRequest proporciona métodos prácticos para insertar datos en el historial de entrenamiento y crear una sesión en la misma llamada a SessionsClient.insertSession. Los conjuntos de datos, si los hay, se insertan como si primero hubieras llamado al método HistoryClient.insertData y, luego, se crea la sesión.

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

Cómo insertar segmentos de actividad

Los datos de segmentos de actividad en Google Fit indican la actividad física que realizan los usuarios durante un intervalo de tiempo determinado. Los datos del segmento de actividad son del tipo com.google.activity.segment (TYPE_ACTIVITY_SEGMENT) y son particularmente útiles para admitir las pausas durante los entrenamientos.

Por ejemplo, si creas una sesión de ejecución de 30 minutos con el método Session.Builder.setActivity(), pero el usuario se toma un descanso de 10 minutos entre 10 minutos, la app mostrará de forma incorrecta que el usuario corrió durante 30 minutos. Siempre que tu app pueda detectar si el usuario estaba caminando o corriendo, los datos del segmento de actividad permiten que se indique que el usuario corrió durante 10 minutos, caminó durante 10 minutos y, luego, 10 minutos adicionales. Otras apps también pueden informar la actividad correctamente si miran los datos del segmento de actividad que insertas.

Para agregar datos de segmentos de actividad a una sesión, crea un conjunto de datos que contenga puntos de tipo com.google.activity.segment. Cada uno de estos puntos representa un intervalo continuo durante el cual el usuario realizó un solo tipo de actividad.

El ejemplo anterior de correr y caminar requeriría tres puntos de segmentos de actividad: uno para correr durante los primeros 10 minutos, uno para caminar durante los siguientes 10 minutos y otro para correr durante los últimos 10 minutos.

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

Cómo leer datos de entrenamiento con sesiones

La API de Sessions te permite obtener una lista de sesiones de la tienda de entrenamiento que coinciden con algunos criterios. Por ejemplo, puedes obtener todas las sesiones contenidas en un intervalo de tiempo, o bien obtener una sesión en particular por nombre o ID. También puedes especificar si te interesan las sesiones que crea tu app o cualquier otra.

Para obtener una lista de sesiones que coincidan con algunos criterios, primero crea una instancia de 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();

Luego, usa el método 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));

Cómo leer datos de sueño con sesiones

Las sesiones de sueño se tratan de manera distinta de otras sesiones de actividad. De forma predeterminada, las respuestas de lectura contienen solo sesiones de actividad, no sesiones de sueño.

Para incluir sesiones de sueño, usa el método includeSleepSessions cuando compiles tu SessionReadRequest. Para incluir actividades y sesiones, usa includeSleepSessions y includeActivitySessions.

Mostrar sesiones en otras apps

Para mostrarles a los usuarios una vista más detallada de una sesión específica en una app diferente, tu app puede invocar un intent que contenga la información de la sesión. Puedes especificar una app en particular, como la que creó la sesión. O bien, en caso de que la app que creó la sesión no esté instalada en el dispositivo, puedes permitir que cualquier app que pueda mostrar actividad de entrenamiento responda al intent.

Si quieres crear un intent que muestre datos de sesión en una app diferente, usa la clase 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);

Cómo recibir intents de otras apps

Si quieres registrar tu app para que reciba intents de otras apps de salud y bienestar, declara un filtro de intents en tu manifiesto que sea similar al siguiente:

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

Cada intent que recibe tu app de Google Fit corresponde a una sola actividad, pero puedes filtrar varios tipos de MIME en un solo filtro de intents. El filtro de intents de tu app debe incluir todas las actividades que admite.

Los intents de entrenamiento incluyen los siguientes extras:

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

Puedes obtener datos de estos extras de la siguiente manera:

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