Google Fit:订阅本地设备DataSource后如何读取数据?
好的,既然你已经成功订阅了TYPE_STEP_COUNT_DELTA的数据源,接下来要读取步数和行走距离可以分实时监听更新和查询历史数据两种场景来处理,我给你详细拆解实现步骤:
一、实时监听步数增量更新
订阅RecordingClient的作用是让系统在后台自动收集步数数据,如果你想实时获取新增的步数,可以通过SensorsClient注册一个数据监听器,当有新的数据点产生时触发回调:
- 首先定义一个数据点监听器,用于处理新的步数数据:
val stepDataListener = OnDataPointListener { dataPoint -> // 遍历数据点中的所有字段 for (field in dataPoint.dataType.fields) { val value = dataPoint.getValue(field) // 匹配步数字段(TYPE_STEP_COUNT_DELTA对应的字段名是"steps") if (field.name == "steps") { val newSteps = value.asInt() Log.d("GoogleFit", "新增步数: $newSteps") // 如果你需要累计总步数,可以维护一个全局变量来累加这个增量值 } } }
- 注册监听器到SensorsClient:
// 用你之前创建的dataSource来构建传感器请求 val sensorRequest = SensorRequest.Builder() .setDataSource(dataSource) .setSamplingRate(1, TimeUnit.MINUTES) // 按需调整采样频率,比如每分钟获取一次 .build() Fitness.getSensorsClient(this, GoogleSignIn.getLastSignedInAccount(this)) .add(sensorRequest, stepDataListener) .addOnSuccessListener { Log.d("GoogleFit", "步数监听已成功注册") } .addOnFailureListener { e -> Log.e("GoogleFit", "注册步数监听失败: ${e.message}") }
- 记得在不需要监听时移除(比如页面销毁),避免内存泄漏:
Fitness.getSensorsClient(this, GoogleSignIn.getLastSignedInAccount(this)) .remove(stepDataListener) .addOnSuccessListener { Log.d("GoogleFit", "步数监听已移除") }
二、查询历史累计步数和行走距离
如果需要获取某段时间内的累计步数和距离,使用HistoryClient来执行聚合查询会更高效,同时可以一次性获取步数和距离数据:
- 构建数据查询请求:
// 设置查询的时间范围,这里示例为过去24小时 val endTime = System.currentTimeMillis() val startTime = endTime - 24 * 60 * 60 * 1000 // 构建请求,同时聚合步数和距离的累计数据 val readRequest = DataReadRequest.Builder() // 聚合步数:从增量数据转为累计总数 .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA) // 聚合距离:从增量数据转为累计总数(单位是米) .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA) .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS) .bucketByTime(1, TimeUnit.DAYS) // 按天聚合数据,也可以改为小时/分钟 .build()
- 执行查询并处理结果:
Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this)) .readData(readRequest) .addOnSuccessListener { response -> // 遍历返回的数据桶 for (bucket in response.buckets) { for (dataSet in bucket.dataSets) { processAggregatedData(dataSet) } } } .addOnFailureListener { e -> Log.e("GoogleFit", "查询历史数据失败: ${e.message}") } // 处理聚合数据的辅助函数 private fun processAggregatedData(dataSet: DataSet) { for (dataPoint in dataSet.dataPoints) { for (field in dataPoint.dataType.fields) { val value = dataPoint.getValue(field) when (field.name) { "steps" -> { val totalSteps = value.asInt() Log.d("GoogleFit", "累计步数: $totalSteps") } "distance" -> { val totalDistance = value.asFloat() Log.d("GoogleFit", "累计距离: ${totalDistance}米") } } } } }
关键注意事项
- 权限检查:确保你的应用已经获取了
ACTIVITY_RECOGNITION权限,并且在Google SignIn的FitnessOptions中添加了步数和距离的读取权限,比如:val fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ) .addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ) .build() - 数据类型区分:
TYPE_STEP_COUNT_DELTA是增量数据(每次新增的步数),而AGGREGATE_STEP_COUNT_DELTA是时间段内的累计总数,查询时注意使用正确的聚合类型。 - 账户有效性:确保
GoogleSignIn.getLastSignedInAccount(this)返回的账户是已授权的有效账户,否则会导致请求失败。
内容的提问来源于stack exchange,提问作者Srijith
相关产品推荐
相关产品推荐

