“时段”表示用户进行健身活动的时间间隔。Sessions API 可让您的应用在健身存储区中创建会话。
对于持续的健身活动(用户在开始和结束健身活动时会通知您的应用),您可以实时创建时段。
您还可以在健身活动结束后或者从 Google 健身外部导入数据和健身课程时,将锻炼活动插入健身商店。
实时创建会话
如需为持续性健身活动创建时段,请完成以下步骤:
在用户发起健身活动时,使用
SessionsClient.startSession
方法启动会话。在用户结束健身活动后,使用
SessionsClient.stopSession
方法停止会话。使用
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
对象中的名称。
在健身商店中插入课程
若要插入包含您之前收集的数据的会话,请执行以下操作:
创建一个
Session
对象,用于指定时间间隔和其他所需信息。为该会话创建
SessionInsertRequest
。(可选)添加数据集和聚合数据点。
使用
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 健身中的活动细分数据会指明用户在给定时间间隔内执行的健身活动。活动片段数据的类型为 com.google.activity.segment
(TYPE_ACTIVITY_SEGMENT
),对于支持锻炼期间的暂停尤为有用。
例如,如果您使用 Session.Builder.setActivity()
方法创建一个 30 分钟的跑步会话,但用户在中间休息 10 分钟,您的应用会错误地显示用户跑步了 30 分钟。假设您的应用可以检测用户是在步行还是跑步,那么通过活动片段数据,应用就可以指示用户跑步 10 分钟,步行 10 分钟,然后又跑步 10 分钟。其他应用也可以通过查看您插入的活动细分数据来正确报告 activity。
如需向时段添加活动细分数据,请创建一个包含 com.google.activity.segment
类型的点的数据集。其中每个点都表示用户执行单一活动类型的连续时间间隔。
前面的跑步和步行示例需要三个活动细分点:一个用于在开始的 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()
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
方法。如需同时包含 activity 和会话,请同时使用 includeSleepSessions
和 includeActivitySessions
。
显示其他应用中的会话
如需向用户显示其他应用中特定会话的详细视图,您的应用可以调用包含会话信息的 intent。您可以指定特定应用,例如创建会话的应用。或者,如果设备上未安装创建会话的应用,您可以允许任何可显示健身活动的应用响应 intent。
如需创建 intent 以在其他应用上显示会话数据,请使用 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
如需注册您的应用以接收来自其他健康与保健应用的 intent,请在清单中声明类似于以下内容的 intent 过滤器:
<intent-filter>
<action android:name="vnd.google.fitness.VIEW"/>
<data android:mimeType="vnd.google.fitness.session/running"/>
</intent-filter>
您的应用从 Google 健身收到的每个 intent 都只能是一个 activity,但您可以在单个 intent 过滤器中过滤多种 MIME 类型。应用的 intent 过滤器需要包含应用支持的所有 activity。
健身 intent 包括以下 extra:
vnd.google.gms.fitness.start_time
vnd.google.gms.fitness.end_time
vnd.google.gms.fitness.session
您可以从这些 extra 中获取数据,如下所示:
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()); } }