Praca z sesjami

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

W przypadku bieżących aktywności, w których użytkownik powiadomi aplikację, gdy rozpoczyna i kończy swoją aktywność, możesz tworzyć sesje w czasie rzeczywistym.

Możesz też wstawić sesję w fitnessie po zakończeniu ćwiczenia albo gdy zaimportujesz dane i sesje z Google Fit.

Tworzenie sesji w czasie rzeczywistym

Aby utworzyć sesje trwającej aktywności fizycznej, wykonaj te czynności:

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

  2. Rozpocznij sesję przy użyciu metody SessionsClient.startSession, gdy użytkownik rozpocznie aktywność fizyczną.

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

  4. Anuluj subskrypcję danych o aktywności, których nie chcesz już używać, korzystając 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));

Powstała sesja zawiera te parametry:

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

  • Czas zakończenia: czas, w jakim aplikacja wywołała metodę SessionsClient.stopSession.

  • Nazwa: nazwa obiektu Session, który jest przekazywany do SessionsClient.startSession.

Wstaw sesje w sklepie fitness

Aby wstawić sesje z zebranymi wcześniej danymi:

  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.

Wstawianie sesji

Aby wstawić do historii aktywności użytkownika dane o aktywności fizycznej zawierające metadane sesji, 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 zapewnia wygodne metody wstawiania danych do historii fitnessu i tworzenia sesji w tej samej rozmowie z funkcją SessionsClient.insertSession. Zbiory danych (jeśli istnieją) są wstawiane w taki sposób, jak gdyby została wywołana metoda HistoryClient.insertData, a potem sesja jest tworzona.

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 aktywności z segmentu aktywności w Google Fit wskazują, co użytkownicy robią w danym okresie. Dane o segmentach aktywności mają typ com.google.activity.segment (TYPE_ACTIVITY_SEGMENT) i są szczególnie przydatne podczas obsługi przerw podczas treningów.

Jeśli np. utworzysz 30-minutową sesję biegową z użyciem metody Session.Builder.setActivity(), ale użytkownik zrobi 10 minut przerwy, Twoja aplikacja będzie niezgodnie z prawdą informować, że użytkownik trwał 30 minut. Jeśli aplikacja wykryje, czy użytkownik chodzi lub biegał, dane o segmentach aktywności pozwalają wskazać, że użytkownik biegał przez 10 minut, w ciągu 10 minut, a potem przez dodatkowe 10 minut. Inne aplikacje mogą też zgłaszać działania prawidłowo, korzystając z danych wstawionych przez Ciebie segmentu aktywności.

Aby dodać do sesji dane o segmentach 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ł pojedynczy typ aktywności.

W poprzednim przykładzie biegu i spaceru wymagane były trzy punkty aktywności: jeden dla biegu w ciągu pierwszych 10 minut, jeden dla spaceru w ciągu najbliższych 10 minut i jeden dla biegu 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 za pomocą sesji

Dzięki sesjom API z listy fitness możesz uzyskać listę sesji spełniających określone kryteria. Możesz np. pobrać wszystkie sesje w określonym przedziale czasu lub wybrać konkretną sesję według nazwy lub identyfikatora. Możesz też określić, czy interesują Cię sesje utworzone przez Twoją aplikację czy 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));

Odczytywanie danych o śnie za pomocą sesji

Sesje snu są traktowane jako oddzielne od innych sesji aktywności. Domyślnie odpowiedzi odczytu zawierają tylko sesje aktywności, a nie sesje snu.

Aby uwzględnić sesje snu, podczas tworzenia elementu SessionReadRequest użyj metody includeSleepSessions. Aby uwzględnić zarówno działania, jak i sesje, użyj obu typów: includeSleepSessions i includeActivitySessions.

Pokazuj sesje w innych aplikacjach

Aby wyświetlić użytkownikom bardziej szczegółowy widok danej sesji w innej aplikacji, może ona wywołać intencję zawierającą informacje o sesji. Możesz wskazać konkretną aplikację, np. aplikację, która utworzyła sesję. Jeśli aplikacja, która utworzyła sesję, nie jest zainstalowana na urządzeniu, możesz zezwolić na to, aby aplikacja odpowiadała 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);

Otrzymuj intencje z innych aplikacji

Aby zarejestrować swoją aplikację i otrzymywać zamiary innych aplikacji związanych ze zdrowiem i dobrym samopoczuciem, w pliku manifestu zadeklaruj 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 odbierana przez Google Fit z Google Fit obejmuje tylko jedną aktywność, ale w jednym filtrze intencji możesz filtrować wiele typów MIME. Filtr intencji aplikacji musi zawierać wszystkie działania obsługiwane przez Twoją aplikację.

Zamiary fitness to między innymi:

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

Dane te możesz uzyskać w ten 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());
    }
}