セッションを扱う

セッションは、ユーザーがフィットネス活動を行う時間を表します。Sessions API を使用すると、アプリはフィットネス ストアでセッションを作成できます。

ユーザーがフィットネス アクティビティの開始時と終了時にアプリに通知する継続的なフィットネス アクティビティについては、リアルタイムでセッションを作成できます。

また、フィットネス アクティビティが終了したら、または Google Fit の外部からデータやセッションをインポートして、セッションをフィットネス ストアに挿入することもできます。

セッションをリアルタイムで作成する

進行中のフィットネス アクティビティのセッションを作成する手順は次のとおりです。

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

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

セッションを停止する

アプリでセッションを停止するには、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));

作成されたセッションには次のパラメータが含まれます。

  • 開始時刻: アプリが 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()

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

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

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

アクティビティ セグメントを挿入

Google Fit のアクティビティ セグメント データは、特定の期間にユーザーが実施したフィットネス アクティビティを示します。アクティビティ セグメント データは com.google.activity.segmentTYPE_ACTIVITY_SEGMENT)型で、ワークアウト中の一時停止をサポートする場合に特に有用です。

たとえば、Session.Builder.setActivity() メソッドで 30 分のランニング セッションを作成し、ユーザーがその後に 10 分の休憩を取った場合、アプリではユーザーが 30 分間稼働したことが誤って表示されます。ユーザーが歩いているか、走っているかをアプリが検出できる場合、アクティビティ セグメント データにより、アプリはユーザーが 10 分間行動し、10 分間歩いた後、さらに 10 分間実行したことが示されます。また、他のアプリは、挿入したアクティビティ セグメント データを参照してアクティビティを正しく報告することもできます。

アクティビティ セグメントのデータをセッションに追加するには、タイプ com.google.activity.segment のポイントを含むデータセットを作成します。これらの各ポイントは、ユーザーが 1 つのアクティビティ タイプを実行している連続する時間間隔を表します。

前述のランニングとウォーキングの例では、3 つのアクティビティ セグメント ポイントが必要です。1 つは最初の 10 分間の実行、1 つは次の 10 分間のウォーキング、もう 1 つは最後の 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()

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

セッションを使用してフィットネス データを読み取る

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

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

次に、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));

セッションを使用して睡眠データを読み取る

睡眠セッションは、他のアクティビティセッションとは区別して扱われます。デフォルトでは、読み取りレスポンスにはアクティビティ セッションのみが含まれ、スリープ セッションは含まれません。

睡眠セッションを含めるには、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)

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

他のアプリからインテントを受信する

他の健康&ウェルネス アプリからインテントを受信するようにアプリを登録するには、次のようなインテント フィルタをマニフェストで宣言します。

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

アプリが Google Fit から受け取るインテントは 1 つしかありませんが、1 つのインテント フィルタで複数の 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)
    }
}

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