세션으로 작업하기

세션은 사용자가 피트니스 활동을 하는 동안의 시간 간격을 나타냅니다. Sessions API를 사용하면 앱에서 피트니스 저장소에 세션을 만들 수 있습니다.

사용자가 피트니스 활동을 시작하고 완료할 때 앱에 알림을 보내는 지속적인 피트니스 활동의 경우 실시간으로 세션을 만들 수 있습니다.

피트니스 활동이 끝난 후 또는 Google 피트니스 외부에서 데이터와 세션을 가져올 때 피트니스 저장소에 세션을 삽입할 수도 있습니다.

실시간으로 세션 만들기

진행 중인 피트니스 활동에 관한 세션을 만들려면 다음 단계를 완료하세요.

  1. RecordingClient.subscribe 메서드를 사용하여 피트니스 데이터를 구독합니다.

  2. 사용자가 피트니스 활동을 시작할 때 SessionsClient.startSession 메서드를 사용하여 세션을 시작합니다.

  3. 사용자가 피트니스 활동을 종료할 때 SessionsClient.stopSession 메서드를 사용하여 세션을 중지합니다.

  4. 더 이상 RecordingClient.unsubscribe 메서드 사용을 원하지 않는 피트니스 데이터를 구독 취소합니다.

세션 시작

앱에서 세션을 시작하려면 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)
    }

자바

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

세션 중지

앱에서 세션을 중지하려면 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)
    }

자바

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

결과 세션에는 다음과 같은 매개변수가 있습니다.

  • 시작 시간: 앱에서 SessionsClient.startSession 메서드를 호출한 시간입니다.

  • 종료 시간: 앱에서 SessionsClient.stopSession 메서드를 호출한 시간입니다.

  • 이름: SessionsClient.startSession에 전달하는 Session 객체의 이름입니다.

피트니스 스토어에 세션 삽입하기

이전에 수집한 데이터로 세션을 삽입하려면 다음 단계를 따르세요.

  1. 시간 간격 및 기타 필수 정보를 지정하는 Session 객체를 만듭니다.

  2. 세션으로 SessionInsertRequest를 만듭니다.

  3. 원하는 경우 데이터 세트를 추가하고 데이터 포인트를 집계합니다.

  4. SessionsClient.insertSession 메서드를 사용하여 세션을 삽입합니다.

세션 삽입

세션 메타데이터가 포함된 피트니스 데이터를 사용자의 피트니스 기록에 삽입하려면 먼저 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()

자바

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

SessionInsertRequest 클래스는 피트니스 기록에 데이터를 삽입하고 동일한 SessionsClient.insertSession 호출에서 세션을 만들 수 있는 편리한 메서드를 제공합니다. 데이터 세트가 있는 경우 먼저 HistoryClient.insertData 메서드를 호출한 것처럼 데이터 세트가 삽입된 후 세션이 생성됩니다.

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

자바

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

활동 세그먼트 삽입

Google 피트니스의 활동 세그먼트 데이터는 사용자가 특정 시간 간격 동안 수행하는 피트니스 활동을 나타냅니다. 활동 세그먼트 데이터는 com.google.activity.segment 유형(TYPE_ACTIVITY_SEGMENT)이며 특히 운동 중 일시중지를 지원하는 데 유용합니다.

예를 들어 Session.Builder.setActivity() 메서드로 30분 달리기 세션을 만들었지만 사용자가 10분간 휴식을 취하는 경우 앱은 사용자가 30분 동안 실행한 것으로 잘못 표시합니다. 앱에서 사용자의 걷기 또는 달리기 여부를 감지할 수 있다면 활동 세그먼트 데이터를 통해 사용자가 10분 동안 달리고 10분 동안 걸은 다음 추가로 10분 동안 실행했음을 나타낼 수 있습니다. 또한 다른 활동에서는 삽입된 활동 세그먼트 데이터를 보고 활동을 올바르게 보고할 수 있습니다.

세션에 활동 세그먼트 데이터를 추가하려면 com.google.activity.segment 유형의 점이 포함된 데이터 세트를 만드세요. 이러한 각 점은 사용자가 단일 활동 유형을 수행하는 연속적인 시간 간격을 나타냅니다.

이전의 달리기 및 걷기 예시에는 활동 세그먼트 지점 3개가 필요합니다. 하나는 첫 10분 동안 실행하기 위한 것이고, 다른 하나는 다음 10분 동안의 걷기입니다. 다른 하나는 마지막 10분 동안의 달리기입니다.

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

자바

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

세션을 사용하여 피트니스 데이터 읽기

Sessions API를 사용하면 피트니스 스토어에서 일부 기준과 일치하는 세션 목록을 가져올 수 있습니다. 예를 들어 시간 간격에 포함된 모든 세션을 가져오거나 특정 세션을 이름 또는 ID로 가져올 수 있습니다. 앱 또는 앱에서 만든 세션에 관심이 있는지 지정할 수도 있습니다.

일부 기준과 일치하는 세션 목록을 가져오려면 먼저 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()

자바

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

그런 다음 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)
    }

자바

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

세션을 사용하여 수면 데이터 읽기

수면 세션은 다른 활동 세션과 구별되는 것으로 간주됩니다. 기본적으로 읽기 응답에는 활동 세션만 포함되며 수면 세션은 포함되지 않습니다.

수면 세션을 포함하려면 SessionReadRequest를 빌드할 때 includeSleepSessions 메서드를 사용합니다. 활동과 세션을 모두 포함하려면 includeSleepSessionsincludeActivitySessions을 모두 사용하세요.

다른 앱에 세션 표시

사용자에게 다른 앱의 특정 세션을 더 자세히 보여주기 위해 앱이 세션 정보가 포함된 인텐트를 호출할 수 있습니다. 세션을 만든 앱과 같은 특정 앱을 지정할 수 있습니다. 또는 세션을 만든 앱이 기기에 설치되어 있지 않은 경우 피트니스 활동을 표시할 수 있는 모든 앱이 인텐트에 응답하도록 허용할 수 있습니다.

다른 앱에 세션 데이터를 표시하는 인텐트를 만들려면 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)

자바

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

다른 앱에서 인텐트 수신

다른 건강 및 웰빙 앱에서 인텐트를 수신하도록 앱을 등록하려면 매니페스트에서 다음과 유사한 인텐트 필터를 선언합니다.

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

앱이 Google 피트니스에서 수신하는 각 인텐트는 활동 하나뿐이지만 단일 인텐트 필터에서 여러 MIME 유형을 필터링할 수 있습니다. 앱의 인텐트 필터에는 앱에서 지원하는 모든 활동이 포함되어야 합니다.

피트니스 인텐트에는 다음 추가 항목이 포함됩니다.

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

이러한 추가 데이터에서 다음과 같은 데이터를 얻을 수 있습니다.

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

자바

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