Google Fit是一个平台,使开发人员可以构建专注于用户适应性数据的应用程序。 Google提供的工具之一是适用于Android的Google Fit,可以在Google Play服务中打包获得。
在本系列的前面,我们探讨了如何使用Recording API通过Google Play服务存储健身数据,以及如何通过History API访问和更新数据。 在本教程中,我们使用Sessions API扩展了这些想法,该API允许您按时间间隔组织活动数据。
本教程将引导您完成一个示例项目,该示例项目演示如何使用Sessions API。 可以从GitHub下载完成的项目。
1.项目设置
步骤1:设定开发人员控制台
要使用Google Fit,您需要创建OAuth 2.0客户端ID并通过Google Developer Console注册您的应用程序。 在有关Google Fit Sensors API的教程中,您可以在Google Developer Console中找到有关如何设置项目的详细说明。
步骤2:设定Android专案
在Google Developer Console中配置了用于身份验证的应用程序后,请使用您注册的包名称创建一个新的Android应用程序,该应用程序的Activity
为空。
创建Android项目后,打开build.gradle,并将Google Play服务包含在依赖项节点下,然后同步您的应用。 在此示例中,我还将使用Butter Knife库为点击侦听器减少样板代码并查找View
项。
compile 'com.google.android.gms:play-services-fitness:8.4.0'
compile 'com.jakewharton:butterknife:7.0.1'
同步依赖项后,打开AndroidManifest.xml并包括ACCESS_FINE_LOCATION
权限。 要从Google Fit中读取会话数据,必须具有此权限。 尽管我在本教程中没有详细介绍,但值得注意的是,如果您的目标是API 23或更高版本,则需要向用户请求位置权限 。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
接下来,打开activity_main.xml并对其进行更新,使其包括五个Button
项,这些项将用于演示Sessions API的某些功能。 最终结果应类似于以下内容:
创建布局后,打开MainActivity.java并连接到Google Play服务。
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private final String SESSION_NAME = "session name";
private GoogleApiClient mGoogleApiClient = null;
private Session mSession;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SESSIONS_API)
.addApi(Fitness.HISTORY_API)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(this)
.enableAutoManage(this, 0, this)
.build();
}
@Override
protected void onDestroy() {
super.onDestroy();
ButterKnife.unbind(this);
}
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
}
您可能已经注意到,您将包括History API和Sessions API。 这是必需的,因为History API用于删除会话数据,我们将在本教程的后面部分讨论。 您还需要将FITNESS_LOCATION_READ_WRITE
和FITNESS_ACTIVITY_READ_WRITE
范围属性同时用于我们将要讨论的Sessions API功能。
设置好应用程序以连接到Google Play服务和Google Fit后,就该开始尝试Sessions API了。
2.使用会话API
Sessions API是Google Fit的另一个工具,用于为用户存储健身数据。 因此,它并不是要取代Recording或History API,而是要改善应用程序以获得更好的用户体验的另一种方法。
在本部分中,您将学习如何启动和停止实时会话数据收集,如何将会话插入Google Fit数据存储区,如何读取以前存储的会话数据以及如何删除不必要或不正确的会话。 与History API相似,Sessions API调用必须脱离主线程。 虽然History API的教程在AsyncTask
调用中包装了操作,但本教程将重点介绍如何使用PendingResult
回调来跟踪任务。
开始和停止会话
Sessions API的最常见方案是在用户启动健身活动之后记录信息。 这通常与Recording API同时开始,以便可以将传感器数据与会话时间范围关联。 要开始记录会话,您需要使用名称,唯一标识符,描述,开始时间以及用户正在执行的活动类型来创建会话对象。
mSession = new Session.Builder()
.setName(SESSION_NAME)
.setIdentifier(getString(R.string.app_name) + " " + System.currentTimeMillis())
.setDescription("Yoga Session Description")
.setStartTime(Calendar.getInstance().getTimeInMillis(), TimeUnit.MILLISECONDS)
.setActivity(FitnessActivities.YOGA)
.build();
创建Session
对象后,您可以在Sessions API上调用startSession
来开始记录用户的活动。
PendingResult<Status> pendingResult =
Fitness.SessionsApi.startSession(mGoogleApiClient, mSession);
pendingResult.setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i("Tuts+", "Successfully started session");
} else {
Log.i("Tuts+", "Failed to start session: " + status.getStatusMessage());
}
}
}
);
用户完成活动后,可以通过调用带有Session
唯一标识符的stopSession
来结束Session
。
PendingResult<SessionStopResult> pendingResult =
Fitness.SessionsApi.stopSession(mGoogleApiClient, mSession.getIdentifier());
pendingResult.setResultCallback(new ResultCallback<SessionStopResult>() {
@Override
public void onResult(SessionStopResult sessionStopResult) {
if( sessionStopResult.getStatus().isSuccess() ) {
Log.i("Tuts+", "Successfully stopped session");
} else {
Log.i("Tuts+", "Failed to stop session: " +
sessionStopResult.getStatus().getStatusMessage());
}
}
});
这里值得一提的是Session
对象实现了Parcelable
接口,因此可以将其存储在Bundle
中,以防您需要将其存储或传递给应用程序中的另一个组件。 如果用户先启动活动然后关闭应用程序,则此功能很有用,因为稍后您可能需要该会话数据来停止记录会话。
插入Google Fit
既然您知道如何记录实时会话信息,那么下一步就是可以在事后插入会话。 尽管您可以插入一段时间作为会话,但Sessions API还允许您将活动与会话的各个部分相关联。 这对于用户在整个健身过程中可能无法连续进行相同活动的情况很有用。
例如,当您的应用检测到用户跑步,步行休息一小段时间然后再次跑步时。 在下面的示例中,您将插入一个Session
,用户在其中跟踪15分钟,步行5分钟,然后通过跟踪用户何时开始和停止每个活动再运行15分钟。 您还记录了每个活动的平均速度。
Calendar calendar = Calendar.getInstance();
Date now = new Date();
calendar.setTime(now);
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.MINUTE, -15);
long walkEndTime = calendar.getTimeInMillis();
calendar.add(Calendar.MINUTE, -5);
long walkStartTime = calendar.getTimeInMillis();
calendar.add(Calendar.MINUTE, -15);
long startTime = calendar.getTimeInMillis();
float firstRunSpeed = 15;
float walkSpeed = 5;
float secondRunSpeed = 13;
获得关键的时间和速度值后,需要创建两个DataSet
组来存储有关活动和速度的信息。 可以从一组具有适当DataType
属性集的DataSource
对象中创建这些对象。
DataSource speedSegmentDataSource = new DataSource.Builder()
.setAppPackageName(this.getPackageName())
.setDataType(DataType.TYPE_SPEED)
.setName("Tuts+ speed dataset")
.setType(DataSource.TYPE_RAW)
.build();
DataSource activitySegmentDataSource = new DataSource.Builder()
.setAppPackageName(this.getPackageName())
.setDataType(DataType.TYPE_ACTIVITY_SEGMENT)
.setName("Tuts+ activity segments dataset")
.setType(DataSource.TYPE_RAW)
.build();
DataSet speedDataSet = DataSet.create(speedSegmentDataSource);
DataSet activityDataSet = DataSet.create(activitySegmentDataSource);
接下来,您需要创建将插入Google Fit数据存储区的DataPoint
对象。 每个DataPoint
都有一个时间间隔和一组存储相关数据的Field
属性。 配置完每个DataPoint
,您需要将其插入适当的DataSet
。 为简洁起见,我仅在下面显示了为第一个运行段创建DataPoint
对象的代码片段,尽管其他数据点对象显示在GitHub上的本教程的源代码中。
//Create speed data point for first run segment
DataPoint firstRunSpeedDataPoint = speedDataSet.createDataPoint()
.setTimeInterval(startTime, walkStartTime, TimeUnit.MILLISECONDS);
firstRunSpeedDataPoint.getValue(Field.FIELD_SPEED).setFloat(firstRunSpeed);
speedDataSet.add(firstRunSpeedDataPoint);
//Create activity data point for second run segment
DataPoint secondRunActivityDataPoint = activityDataSet.createDataPoint()
.setTimeInterval(walkEndTime, endTime, TimeUnit.MILLISECONDS);
secondRunActivityDataPoint.getValue(Field.FIELD_ACTIVITY).setActivity(FitnessActivities.RUNNING);
activityDataSet.add(secondRunActivityDataPoint);
一旦填充了两个DataSet
组,就该创建要插入的Session
了。 该Session
将需要设置名称,唯一标识符,描述,开始和结束时间以及活动属性。 要注意的一件事是,插入Session
时使用的名称是稍后尝试读取此会话时需要使用的名称。
Session session = new Session.Builder()
.setName(SESSION_NAME)
.setIdentifier(getString(R.string.app_name) + " " + System.currentTimeMillis())
.setDescription("Running in Segments")
.setStartTime(startTime, TimeUnit.MILLISECONDS)
.setEndTime(endTime, TimeUnit.MILLISECONDS)
.setActivity(FitnessActivities.RUNNING)
.build();
现在,您的Session
已创建,您需要创建一个SessionInsertRequest
,向其中添加DataSet
对象,然后将该Session
插入到Google Fit中。
SessionInsertRequest insertRequest = new SessionInsertRequest.Builder()
.setSession(session)
.addDataSet(speedDataSet)
.addDataSet(activityDataSet)
.build();
PendingResult<Status> pendingResult =
Fitness.SessionsApi.insertSession(mGoogleApiClient, insertRequest);
pendingResult.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if( status.isSuccess() ) {
Log.i("Tuts+", "successfully inserted running session");
} else {
Log.i("Tuts+", "Failed to insert running session: " + status.getStatusMessage());
}
}
});
读取会话数据
无论您在应用程序中存储了多少会话数据,除非您能够读取该数据并使用它来使您的应用程序更适合用户,否则它不会对您有多大帮助。 幸运的是,通过Google Fit,您可以在设定的时间内轻松接收会话数据。
首先,您需要选择要接收的数据的开始和结束时间。 在此示例中,我们请求上个月的会话数据。
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.MONTH, -1);
long startTime = cal.getTimeInMillis();
选择时间范围后,您需要创建一个SessionReadRequest
。 该请求包括所需会话数据的时间间隔,正在寻找的会话数据的类型(本教程将仅查找速度数据)以及所请求的会话的名称,但是时间间隔是仅必需的属性。
SessionReadRequest readRequest = new SessionReadRequest.Builder()
.setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
.read(DataType.TYPE_SPEED)
.setSessionName(SESSION_NAME)
.build();
PendingResult<SessionReadResult> sessionReadResult =
Fitness.SessionsApi.readSession(mGoogleApiClient, readRequest);
调用SessionsApi.readSession
,您将收到一个SessionReadResult
对象,该对象包含可以在应用程序中使用的Session
和DataSet
对象的列表。 对于本教程,我们仅记录数据。
sessionReadResult.setResultCallback(new ResultCallback<SessionReadResult>() {
@Override
public void onResult(SessionReadResult sessionReadResult) {
if (sessionReadResult.getStatus().isSuccess()) {
Log.i("Tuts+", "Successfully read session data");
for (Session session : sessionReadResult.getSessions()) {
Log.i("Tuts+", "Session name: " + session.getName());
for (DataSet dataSet : sessionReadResult.getDataSet(session)) {
for (DataPoint dataPoint : dataSet.getDataPoints()) {
Log.i("Tuts+", "Speed: " + dataPoint.getValue(Field.FIELD_SPEED));
}
}
}
} else {
Log.i("Tuts+", "Failed to read session data");
}
}
});
如果现在运行应用程序并使用插入和读取操作,则应收到在上一节中创建的三个速度DataPoint
对象。
I/Tuts+: Speed: 15.0
I/Tuts+: Speed: 5.0
I/Tuts+: Speed: 13.0
删除会话数据
有时您可能需要删除一些不正确或不必要的会话信息。 这可以通过使用History API删除已保存在Google Fit数据存储区中的会话来完成。
首先,您需要确定删除操作的时间间隔。 然后,您可以添加其他信息,例如要删除的DataType
或其他Session
属性,或者可以简单地删除该时间间隔内的所有会话数据。
Calendar calendar = Calendar.getInstance();
Date now = new Date();
calendar.setTime(now);
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.DAY_OF_YEAR, -1);
long startTime = calendar.getTimeInMillis();
DataDeleteRequest request = new DataDeleteRequest.Builder()
.setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
.addDataType(DataType.TYPE_SPEED)
.deleteAllSessions()
.build();
PendingResult<Status> deleteRequest = Fitness.HistoryApi.deleteData(mGoogleApiClient, request);
deleteRequest.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(@NonNull Status status) {
if( status.isSuccess() ) {
Log.i("Tuts+", "Successfully deleted sessions");
} else {
Log.i("Tuts+", "Failed to delete sessions");
}
}
});
结论
正如您在本教程中了解到的那样,Sessions API是一个强大的工具,可以按时间段组织收集的数据。 这是对其他Google Fit API的很好的补充。 与历史记录和记录API结合使用时,您可以做很多事情来了解应用程序用户的活动,并为他们提供健身应用程序的出色体验。
翻译自: https://code.tutsplus.com/tutorials/google-fit-for-android-sessions-api--cms-25857