You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Fit API计步问题:如何获取当日步数而非累计总步数

解决Google Fit API获取当日步数的问题

嘿,我看到你现在在用Google Fit API开发时遇到了一个小问题——当前代码返回的是累计总步数,但你需要的是当日的步数。咱们来一步步把这个问题搞定!

问题分析

你当前的代码用的是DataType.TYPE_STEP_COUNT_CUMULATIVE(累计步数)结合Sensors API来监听数据,这个API的作用是实时推送设备从开始记录以来的总累计步数,所以每次回调得到的都是从设备激活至今的总步数,自然不是你想要的当日数据。

要获取当日步数,咱们需要用到Google Fit的History API,它可以帮我们查询指定时间范围内的步数统计,或者直接调用官方提供的便捷方法获取当日总步数。

解决方案步骤

1. 更新GoogleApiClient配置

首先,我们需要在GoogleApiClient的构建中添加History API的支持,同时调整权限(如果只需要读取步数,用FITNESS_ACTIVITY_READ更严谨):

mApiClient = GoogleApiClient.Builder(this)
    .addApi(Fitness.SENSORS_API)
    .addApi(Fitness.HISTORY_API) // 新增History API支持
    .addScope(Scope(Scopes.FITNESS_ACTIVITY_READ)) // 仅读取权限即可
    .addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this)
    .build()

2. 编写获取当日步数的方法

这里提供两种方式,你可以根据需求选择:

方式一:使用官方便捷方法readDailyTotal

这个方法会直接帮你计算当日的总步数,代码非常简洁:

private fun fetchDailySteps() {
    Fitness.HistoryApi.readDailyTotal(mApiClient, DataType.TYPE_STEP_COUNT_DELTA)
        .setResultCallback { dataReadResult ->
            if (dataReadResult.isSuccess) {
                // 获取当日总步数,没有数据则为0
                val dailySteps = dataReadResult.total?.toInt() ?: 0
                runOnUiThread {
                    Toast.makeText(applicationContext, "当日步数: $dailySteps", Toast.LENGTH_LONG).show()
                }
            } else {
                Log.e("GoogleFit", "读取步数失败: ${dataReadResult.status.statusMessage}")
            }
        }
}

方式二:自定义时间范围查询

如果你需要更灵活的时间范围(比如查询本周、昨天的步数),可以用这种方式手动指定时间段:

private fun fetchDailySteps() {
    // 获取当日0点到当前时间的时间戳(UTC时区,避免时区问题)
    val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
    val endTime = calendar.timeInMillis
    calendar.set(Calendar.HOUR_OF_DAY, 0)
    calendar.set(Calendar.MINUTE, 0)
    calendar.set(Calendar.SECOND, 0)
    val startTime = calendar.timeInMillis

    // 构建读取请求,聚合当日的步数增量
    val readRequest = DataReadRequest.Builder()
        .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
        .bucketByTime(1, TimeUnit.DAYS) // 按天分组
        .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
        .build()

    Fitness.HistoryApi.readData(mApiClient, readRequest)
        .setResultCallback { dataReadResult ->
            if (dataReadResult.isSuccess) {
                var dailySteps = 0
                // 遍历分组数据,累加步数
                if (dataReadResult.buckets.isNotEmpty()) {
                    for (bucket in dataReadResult.buckets) {
                        for (dataSet in bucket.dataSets) {
                            for (dataPoint in dataSet.dataPoints) {
                                for (field in dataPoint.dataType.fields) {
                                    dailySteps += dataPoint.getValue(field).asInt()
                                }
                            }
                        }
                    }
                }
                runOnUiThread {
                    Toast.makeText(applicationContext, "当日步数: $dailySteps", Toast.LENGTH_LONG).show()
                }
            } else {
                Log.e("GoogleFit", "读取步数失败: ${dataReadResult.status.statusMessage}")
            }
        }
}

3. 在连接成功后调用方法

在onConnected回调里,调用我们刚写的fetchDailySteps()方法,这样客户端连接成功后就会自动获取当日步数:

override fun onConnected(bundle: Bundle?) {
    // 如果你还需要实时监听累计步数,可以保留原来的Sensors API代码
    val dataSourceRequest = DataSourcesRequest.Builder()
        .setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
        .setDataSourceTypes(DataSource.TYPE_RAW)
        .build()
    val dataSourcesResultCallback = ResultCallback<DataSourcesResult> { dataSourcesResult ->
        for (dataSource in dataSourcesResult.dataSources) {
            if (DataType.TYPE_STEP_COUNT_CUMULATIVE == dataSource.dataType) {
                registerFitnessDataListener(
                    dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE
                )
            }
        }
    }
    Fitness.SensorsApi.findDataSources(mApiClient, dataSourceRequest)
        .setResultCallback(dataSourcesResultCallback)

    // 调用获取当日步数的方法
    fetchDailySteps()
}

4. 权限注意事项

别忘了在AndroidManifest.xml中添加必要的权限,并且在Android 10及以上系统中动态申请ACTIVITY_RECOGNITION权限:

<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

额外提示

如果你想要实时更新当日步数,也可以结合Sensors API的累计步数:记录连接成功时的初始累计步数,之后每次onDataPoint回调时,用当前累计步数减去初始值,得到当日的实时步数。不过这种方法不如History API可靠,因为如果设备重启或者数据同步异常,初始值可能会不准确,所以更推荐用History API定期查询。

内容的提问来源于stack exchange,提问作者Joglidzee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 19:12:34