Praca z sesjami

Sesje to przedział czasu, w którym użytkownicy wykonują aktywność fizyczną. Dzięki interfejsowi Sessions API Twoja aplikacja może tworzyć sesje w sklepie fitness.

W przypadku trwających ćwiczeń fitnessowych, w których użytkownik powiadamia aplikację o rozpoczęciu i zakończeniu aktywności fizycznej, możesz tworzyć sesje w czasie rzeczywistym.

Sesję możesz też wstawić w sklepie fitness po zakończeniu aktywności fizycznej lub po zaimportowaniu danych i sesji spoza Google Fit.

Twórz sesje w czasie rzeczywistym

Aby utworzyć sesje dla ciągłych aktywności fitness, wykonaj te czynności:

  1. Subskrybuj dane o aktywności fizycznej za pomocą metody RecordingClient.subscribe.

  2. Rozpocznij sesję za pomocą metody SessionsClient.startSession, gdy użytkownik rozpoczyna aktywność fizyczną.

  3. Zatrzymaj sesję za pomocą metody SessionsClient.stopSession, gdy użytkownik zakończy aktywność fizyczną.

  4. Anuluj subskrypcję danych o aktywności fizycznej, jeśli nie chcesz już korzystać z metody RecordingClient.unsubscribe.

Rozpocznij sesję

Aby rozpocząć sesję w aplikacji, użyj metody 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));

Kończenie sesji

Aby zatrzymać sesję w aplikacji, użyj metody 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));

Wynikowa sesja zawiera te parametry:

  • Czas rozpoczęcia: czas wywołania metody SessionsClient.startSession przez aplikację.

  • Czas zakończenia: czas wywołania metody SessionsClient.stopSession przez aplikację.

  • Nazwa: nazwa w obiekcie Session przekazywanym do SessionsClient.startSession.

Wstawiaj sesje w sklepie fitness

Aby wstawić sesje z danymi zebranymi wcześniej:

  1. Utwórz obiekt Session, który określa przedział czasu i inne wymagane informacje.

  2. Utwórz SessionInsertRequest z sesją.

  3. Opcjonalnie dodaj zbiory danych i punkty danych zbiorczych.

  4. Wstaw sesję za pomocą metody SessionsClient.insertSession.

Wstaw sesję

Aby wstawić dane fitness zawierające metadane sesji do historii aktywności fizycznej użytkownika, najpierw utwórz instancję 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();

Klasa SessionInsertRequest udostępnia wygodne metody wstawiania danych do historii aktywności fizycznej i tworzenia sesji w tym samym wywołaniu funkcji SessionsClient.insertSession. Zbiory danych (jeśli istnieją) są wstawiane w taki sposób, jakby metoda HistoryClient.insertData była najpierw wywoływana, a dopiero potem tworzona jest sesja.

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

Wstaw segmenty aktywności

Dane o segmentach aktywności w Google Fit pokazują, jaką aktywność fizyczną użytkownicy wykonali w danym przedziale czasu. Dane segmentu aktywności są typu com.google.activity.segment (TYPE_ACTIVITY_SEGMENT) i przydają się szczególnie przy przerwach na trening.

Jeśli np. utworzysz 30-minutową sesję trwającą przy użyciu metody Session.Builder.setActivity(), a użytkownik zrobi sobie 10-minutową przerwę, aplikacja niepoprawnie wyświetli, że działał przez 30 minut. Jeśli aplikacja wykrywa, czy użytkownik chodzi, czy biega, dane o segmentach aktywności umożliwiają aplikacji określenie, że użytkownik biegał przez 10 minut, szedł przez 10 minut, a potem działał przez kolejne 10 minut. Inne aplikacje mogą też prawidłowo raportować aktywność, na podstawie wpisanych przez Ciebie danych o segmentach aktywności.

Aby dodać do sesji dane segmentu aktywności, utwórz zbiór danych zawierający punkty typu com.google.activity.segment. Każdy z tych punktów reprezentuje ciągły przedział czasu, w którym użytkownik wykonał 1 rodzaj działania.

Poprzedni przykład dotyczący biegu i spaceru wymagałoby trzech punktów aktywności: jeden za bieganie w ciągu pierwszych 10 minut, jeden za bieganie w ciągu następnych 10 minut i jeden za bieganie w ciągu ostatnich 10 minut.

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

Odczytywanie danych o aktywności fizycznej z użyciem sesji

Interfejs Sessions API umożliwia uzyskanie listy sesji ze sklepu fitness, które spełniają określone kryteria. Możesz na przykład sprawdzić wszystkie sesje zawarte w danym przedziale czasu albo wybrać nazwę lub identyfikator konkretnej sesji. Możesz też określić, czy interesują Cię sesje utworzone przez Twoją aplikację, czy przez dowolną aplikację.

Aby uzyskać listę sesji spełniających określone kryteria, najpierw utwórz instancję 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();

Następnie użyj metody 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));

Odczytuj dane o śnie za pomocą sesji

Sesje snu są traktowane jak inne sesje aktywności. Domyślnie odpowiedzi odczytu zawierają tylko sesje aktywności, a nie sesje snu.

Aby uwzględnić sesje snu, podczas tworzenia SessionReadRequest używaj metody includeSleepSessions. Aby uwzględnić zarówno działania, jak i sesje, użyj zarówno właściwości includeSleepSessions, jak i includeActivitySessions.

Pokazuj sesje w innych aplikacjach

Aby wyświetlić użytkownikom bardziej szczegółowy widok konkretnej sesji w innej aplikacji, aplikacja może wywoływać intencję zawierającą informacje o sesji. Możesz wskazać konkretną aplikację, np. aplikację, która utworzyła sesję. Jeśli na urządzeniu nie jest zainstalowana aplikacja, która utworzyła sesję fitness, możesz zezwolić każdej aplikacji, która może wyświetlać aktywność fizyczną, na zareagowanie na intencję.

Aby utworzyć intencję wyświetlania danych sesji w innej aplikacji, użyj klasy 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);

Odbieranie intencji z innych aplikacji

Aby zarejestrować aplikację w celu otrzymywania intencji z innych aplikacji dotyczących zdrowia i samopoczucia, zadeklaruj w pliku manifestu filtr intencji podobny do tego:

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

Każda intencja otrzymywana przez aplikację z Google Fit obejmuje tylko jedną aktywność, ale w jednym filtrze intencji możesz wyświetlić wiele typów MIME. Filtr intencji aplikacji musi obejmować wszystkie obsługiwane przez nią działania.

Intencje związane z aktywnością fizyczną obejmują takie dodatkowe korzyści:

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

Dane z tych dodatków możesz uzyskać w następujący sposób:

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