适用于Android的Google Fit:History API

Google Fit是一个平台,使开发人员可以构建专注于用户适应性数据的应用程序。 Google提供的工具之一是适用于Android的Google Fit,可以在Google Play服务中打包获得。

上一教程中 ,我们探讨了如何使用Google Fit Recording API通过Google Play服务存储健身数据。 本教程通过探讨如何使用History API访问和更新Google Fit中存储的数据来扩展该主题。

使Google Fit强大的原因是健身数据是通过Google Cloud Services存储的,因此以后可以访问和分析。 虽然SensorsRecording API专注于从Android设备收集健身数据,但History API旨在使开发人员可以轻松访问该存储的数据。

本教程将引导您完成一个示例项目,该示例项目演示如何使用History 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应用程序,该SDK的最低SDK为9, Activity为空。

创建基本的Android应用程序后,打开build.gradle并将Google Play服务包含在依赖项节点下,然后同步您的应用程序。

compile 'com.google.android.gms:play-services-fitness:8.4.0'

现在,您应该可以在应用程序中包含必要的Google Play服务类。 在开始学习本教程的Java代码之前,请打开activity_main.xml并对其进行修改,以使其包含五个Button项,我们将使用它们来演示History API的某些功能。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_view_week"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="View this weeks steps" />

    <Button
        android:id="@+id/btn_view_today"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="View today's steps"/>

    <Button
        android:id="@+id/btn_add_steps"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add step data for today" />

    <Button
        android:id="@+id/btn_update_steps"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update step data for yesterday" />

    <Button
        android:id="@+id/btn_delete_steps"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Delete step data for yesterday" />

</LinearLayout>

运行应用程序时,用户界面应如下所示:


要继续设置项目,请打开MainActivity.java并实现以下回调和必需的方法:

  • GoogleApiClient.ConnectionCallbacks
  • GoogleAPiClient.OnConnectionFailedListener
  • View.OnClickListener

您还需要为GoogleApiClient添加成员变量和对Button对象的一组引用,如下所示。

public class MainActivity extends AppCompatActivity implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    View.OnClickListener {
 
    private Button mButtonViewWeek;
    private Button mButtonViewToday;
    private Button mButtonAddSteps;
    private Button mButtonUpdateSteps;
    private Button mButtonDeleteSteps;

    private GoogleApiClient mGoogleApiClient;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        mButtonViewWeek = (Button) findViewById(R.id.btn_view_week);
        mButtonViewToday = (Button) findViewById(R.id.btn_view_today);
        mButtonAddSteps = (Button) findViewById(R.id.btn_add_steps);
        mButtonUpdateSteps = (Button) findViewById(R.id.btn_update_steps);
        mButtonDeleteSteps = (Button) findViewById(R.id.btn_delete_steps);

        mButtonViewWeek.setOnClickListener(this);
        mButtonViewToday.setOnClickListener(this);
        mButtonAddSteps.setOnClickListener(this);
        mButtonUpdateSteps.setOnClickListener(this);
        mButtonDeleteSteps.setOnClickListener(this);
    }
 
    @Override
    public void onConnectionSuspended(int i) {
        Log.e("HistoryAPI", "onConnectionSuspended");
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e("HistoryAPI", "onConnectionFailed");
    }
 
    public void onConnected(@Nullable Bundle bundle) {
        Log.e("HistoryAPI", "onConnected");
    }

 
    @Override
    public void onClick(View v) {
    }
}

设置示例项目所需要做的最后一件事就是连接到Google Play服务。 这可以在onCreate()方法的末尾完成。

mGoogleApiClient = new GoogleApiClient.Builder(this)
        .addApi(Fitness.HISTORY_API)
        .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
        .addConnectionCallbacks(this)
        .enableAutoManage(this, 0, this)
        .build();

使用上述代码,我们将连接到Google Play服务,并请求访问Google Fit中的History API以及读取和写入活动数据的权限。 通过添加enableAutoManage属性,Google Play服务可以正确管理连接和断开连接。

2.使用Google Fit History API

使用History API,您可以检索和汇总数据,插入在应用程序中收集的值或删除可能存储的数据。 需要注意的重要一件事是,本教程中的所有History API操作都必须在主线程之外完成。 换句话说,每个操作都在AsyncTask

private class ViewWeekStepCountTask extends AsyncTask<Void, Void, Void> {
    protected Void doInBackground(Void... params) {
        displayLastWeeksData();
        return null;
    }
}

步骤1:随着时间显示数据

您可能要执行的一项任务是使用或显示随时间推移收集的数据。 您可以通过为适合某些查询参数的特定类型的数据创建一个新的DataReadRequest来做到这一点。

您可以按时间或会话将这些数据分组到Bucket对象中。 在此示例中,您请求上周的汇总步骤数据,并按日期对这些数据进行存储。

Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.WEEK_OF_YEAR, -1);
long startTime = cal.getTimeInMillis();

java.text.DateFormat dateFormat = DateFormat.getDateInstance();
Log.e("History", "Range Start: " + dateFormat.format(startTime));
Log.e("History", "Range End: " + dateFormat.format(endTime));

//Check how many steps were walked and recorded in the last 7 days
DataReadRequest readRequest = new DataReadRequest.Builder()
        .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
        .bucketByTime(1, TimeUnit.DAYS)
        .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
        .build();

创建DataReadRequest ,您可以使用Fitness.HistoryApi.readData命令从GoogleApiClient请求数据。 您还可以在API客户端上调用await ,以便线程在等待查询时停滞多达一分钟。 如果出现问题,则该线程在该分钟后继续。

DataReadResult dataReadResult = Fitness.HistoryApi.readData(mGoogleApiClient, readRequest).await(1, TimeUnit.MINUTES);

如果呼叫成功返回,则可以从DataReadResult对象访问用户的适应性数据。 您的步骤数据请求将在Bucket对象中返回,尽管其他类型的数据也将作为DataSet对象的List返回。 根据返回的数据类型,可以使用以下代码访问它:

//Used for aggregated data
if (dataReadResult.getBuckets().size() > 0) {
    Log.e("History", "Number of buckets: " + dataReadResult.getBuckets().size());
    for (Bucket bucket : dataReadResult.getBuckets()) {
        List<DataSet> dataSets = bucket.getDataSets();
        for (DataSet dataSet : dataSets) {
            showDataSet(dataSet);
        }
    }
}
//Used for non-aggregated data
else if (dataReadResult.getDataSets().size() > 0) {
    Log.e("History", "Number of returned DataSets: " + dataReadResult.getDataSets().size());
    for (DataSet dataSet : dataReadResult.getDataSets()) {
        showDataSet(dataSet);
    }
}

然后,您可以从返回的DataSet对象中检索每个DataPoint

private void showDataSet(DataSet dataSet) {
    Log.e("History", "Data returned for Data type: " + dataSet.getDataType().getName());
    DateFormat dateFormat = DateFormat.getDateInstance();
    DateFormat timeFormat = DateFormat.getTimeInstance();

    for (DataPoint dp : dataSet.getDataPoints()) {
        Log.e("History", "Data point:");
        Log.e("History", "\tType: " + dp.getDataType().getName());
        Log.e("History", "\tStart: " + dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)) + " " + timeFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)));
        Log.e("History", "\tEnd: " + dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS)) + " " + timeFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)));
        for(Field field : dp.getDataType().getFields()) {
            Log.e("History", "\tField: " + field.getName() +
                    " Value: " + dp.getValue(field));
        }
    }
}

如果用户设备上的应用在上周内已打开Recording API,则您会收到该应用每天处于活动状态的数据。 上面代码中的日志应类似于以下内容:

E/History: Range Start: Feb 17, 2016
E/History: Range End: Feb 24, 2016
E/History: Number of buckets: 7
E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:  Type: com.google.step_count.delta
E/History:  Start: Feb 17, 2016 11:01:46 PM
E/History:  End: Feb 17, 2016 11:01:46 PM
E/History:  Field: steps Value: 9360
E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:  Type: com.google.step_count.delta
E/History:  Start: Feb 21, 2016 9:58:03 AM
E/History:  End: Feb 21, 2016 9:58:03 AM
E/History:  Field: steps Value: 10041
E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:  Type: com.google.step_count.delta
E/History:  Start: Feb 21, 2016 11:22:53 PM
E/History:  End: Feb 22, 2016 11:22:53 PM
E/History:  Field: steps Value: 10786
E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:  Type: com.google.step_count.delta
E/History:  Start: Feb 22, 2016 11:06:31 PM
E/History:  End: Feb 23, 2016 11:06:31 PM
E/History:  Field: steps Value: 13099
E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:  Type: com.google.step_count.delta
E/History:  Start: Feb 23, 2016 11:02:31 PM
E/History:  End: Feb 24, 2016 11:02:31 PM
E/History:  Field: steps Value: 9765

步骤2:显示今天的数据

现在,您知道如何根据时间范围检索Google Fit数据。 开发人员常用的一种用例是需要当天的数据。 幸运的是,Google通过添加Fitness.HistoryApi.readDailyTotal调用Fitness.HistoryApi.readDailyTotal了此操作,该调用创建了DailyTotalResult对象,其中包含当天收集的数据。

private void displayStepDataForToday() {
    DailyTotalResult result = Fitness.HistoryApi.readDailyTotal( mGoogleApiClient, DataType.TYPE_STEP_COUNT_DELTA ).await(1, TimeUnit.MINUTES);
    showDataSet(result.getTotal());
}

上面的代码注销了用户当天的步数数据。

E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:     Type: com.google.step_count.delta
E/History:     Start: Feb 24, 2016 8:39:59 AM
E/History:     End: Feb 24, 2016 8:39:59 AM
E/History:     Field: steps Value: 9474

步骤3:将资料插入Google Fit

能够从Google Fit读取数据很重要,但有时您可能需要将自己收集的数据添加到Google Fit数据存储中。 为此,您需要为数据选择一个时间范围,并创建一个DataSource对象,该对象表示您放入Google Fit中的信息的种类。 接下来,创建一个DataSet对象,并将新的DataPoint放入其中以进行插入操作。

对于此示例,我们将假设用户走了100万步,或大约500英里,并将原始步数据插入用户活动的最后一小时。

重要的是要注意,如果您选择一个跨越多天的时间范围,则插入的步数将在这些天之间平均分配。

Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.HOUR_OF_DAY, -1);
long startTime = cal.getTimeInMillis();

DataSource dataSource = new DataSource.Builder()
    .setAppPackageName(this)
    .setDataType(DataType.TYPE_STEP_COUNT_DELTA)
    .setName("Step Count")
    .setType(DataSource.TYPE_RAW)
    .build();
    
int stepCountDelta = 1000000;
DataSet dataSet = DataSet.create(dataSource);

DataPoint point = dataSet.createDataPoint()
        .setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS);
point.getValue(Field.FIELD_STEPS).setInt(stepCountDelta);
dataSet.add(point);

创建DataSet对象后,您可以使用History API的insertData调用将其插入Google Fit数据存储insertData

Fitness.HistoryApi.insertData(mGoogleApiClient, dataSet).await(1, TimeUnit.MINUTES);

如果插入用户的步骤,然后阅读活动日志,则应该看到类似以下内容的内容:

E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:     Type: com.google.step_count.delta
E/History: 	Start: Feb 27, 2016 10:05:18 PM
E/History: 	End: Feb 28, 2016 10:05:18 PM
E/History: 	Field: steps Value: 1008747

步骤4:在Google Fit上更新资料

将数据插入Google Fit后,如果该数据与现有数据重叠,则无法再插入该类型的数据。 如果用户先走了500英里然后又走了500英里,这可能会引起问题。

要解决此问题,您需要使用updateData调用。 幸运的是,更新数据几乎与插入新数据相同,只不过您创建的是DataUpdateRequest

Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.HOUR_OF_DAY, -1);
long startTime = cal.getTimeInMillis();

DataSource dataSource = new DataSource.Builder()
        .setAppPackageName(this)
        .setDataType(DataType.TYPE_STEP_COUNT_DELTA)
        .setName("Step Count")
        .setType(DataSource.TYPE_RAW)
        .build();

int stepCountDelta = 2000000;
DataSet dataSet = DataSet.create(dataSource);

DataPoint point = dataSet.createDataPoint()
        .setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS);
point.getValue(Field.FIELD_STEPS).setInt(stepCountDelta);
dataSet.add(point);

DataUpdateRequest updateRequest = new DataUpdateRequest.Builder().setDataSet(dataSet).setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS).build();
Fitness.HistoryApi.updateData(mGoogleApiClient, updateRequest).await(1, TimeUnit.MINUTES);

如果要在执行上述操作后第二天注销用户的步骤,则应该看到超过200万个步骤。

E/History: Data returned for Data type: com.google.step_count.delta
E/History: Data point:
E/History:     Type: com.google.step_count.delta
E/History: 	Start: Feb 27, 2016 10:05:18 PM
E/History: 	End: Feb 28, 2016 10:05:18 PM
E/History: 	Field: steps Value: 2008747

第5步:从Google Fit中删除数据

通过Google Fit History API可以执行的最终操作是删除存储在Google Fit中的数据的功能。 这可以通过选择日期范围,创建DataDeleteRequest对象并从History API调用deleteData来完成。 虽然您可以删除自己插入的数据,但不会删除Google Fit存储的数据。

Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.DAY_OF_YEAR, -1);
long startTime = cal.getTimeInMillis();

DataDeleteRequest request = new DataDeleteRequest.Builder()
        .setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
        .addDataType(DataType.TYPE_STEP_COUNT_DELTA)
        .build();

Fitness.HistoryApi.deleteData(mGoogleApiClient, request).await(1, TimeUnit.MINUTES);

结论

如您所见,History API是用于访问和操纵Google Fit数据存储的功能强大的工具。 虽然其他Google Fit API旨在收集数据,但History API允许您维护和访问数据以进行分析。 现在,您应该能够使用该功能创建出色的应用程序。

翻译自: https://code.tutsplus.com/tutorials/google-fit-for-android-history-api--cms-25856

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
google play service最新版本,基于firebase的sdk,9.2.0.包含了 全部需要的jar,另外还有aar版本 play-services-ads-9.2.0.jar play-services-analytics-9.2.0.jar play-services-analytics-impl-9.2.0.jar play-services-appindexing-9.2.0.jar play-services-appinvite-9.2.0.jar play-services-appstate-8.4.0.jar play-services-auth-9.2.0.jar play-services-auth-base-9.2.0.jar play-services-base-9.2.0.jar play-services-basement-9.2.0.jar play-services-cast-9.2.0.jar play-services-cast-framework-9.2.0.jar play-services-clearcut-9.2.0.jar play-services-contextmanager-9.2.0.jar play-services-drive-9.2.0.jar play-services-fitness-9.2.0.jar play-services-games-9.2.0.jar play-services-gass-9.2.0.jar play-services-gcm-9.2.0.jar play-services-identity-9.2.0.jar play-services-iid-9.2.0.jar play-services-location-9.2.0.jar play-services-maps-9.2.0.jar play-services-measurement-8.4.0.jar play-services-nearby-9.2.0.jar play-services-panorama-9.2.0.jar play-services-places-9.2.0.jar play-services-plus-9.2.0.jar play-services-safetynet-9.2.0.jar play-services-tagmanager-9.2.0.jar play-services-tagmanager-api-9.2.0.jar play-services-tasks-9.2.0.jar play-services-vision-9.2.0.jar play-services-wallet-9.2.0.jar play-services-wearable-9.2.0.jar play-services-ads-lite-9.2.0.jar firebase-analytics-9.2.0.jar firebase-analytics-impl-9.2.0.jar firebase-auth-9.2.0.jar firebase-auth-common-9.2.0.jar firebase-auth-module-9.2.0.jar firebase-common-9.2.0.jar firebase-config-9.2.0.jar firebase-crash-9.2.0.jar firebase-database-9.2.0.jar firebase-database-connection-9.2.0.jar firebase-iid-9.2.0.jar firebase-messaging-9.2.0.jar firebase-storage-9.2.0.jar firebase-storage-common-9.2.0.jar

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值