如何通过Google Fit API将WearOS设备心率数据同步至安卓手机
我之前做过类似的WearOS与手机通过Google Fit同步心率数据的项目,结合你的华为Watch 2 + 三星S7的场景,整理了一套可行的落地方案,你可以跟着一步步来验证:
一、先确认前提条件
这些是后续实现的基础,务必先排查:
- 确保华为Watch 2的WearOS系统是最新版本,且已经和三星S7完成蓝牙配对、WearOS官方应用绑定
- 手机和手表端都登录了同一个Google账号,且Google Fit服务在两端都正常启用(可以打开Google Fit App确认状态)
- 你的手机应用和手表应用都已经在Google Cloud Console配置好Google Fit API权限,包括对应两端包名和签名的OAuth 2.0客户端ID
二、核心实现步骤
1. 手表端:获取心率数据并写入Google Fit
WearOS上可以直接通过Google Fit的传感器API读取心率,再将数据写入Fit的数据源中,这样手机端就能同步获取到。
Kotlin代码示例:
// 初始化Google Fit客户端,申请写入心率数据的权限 private val fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_WRITE) .build() private fun initHeartRateListener(context: Context, activity: Activity) { val account = GoogleSignIn.getAccountForExtension(context, fitnessOptions) // 检查权限,无权限则发起请求 if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) { GoogleSignIn.requestPermissions( activity, REQUEST_OAUTH_PERMISSIONS, account, fitnessOptions ) } else { startHeartRateMonitoring(context, account) } } private fun startHeartRateMonitoring(context: Context, account: GoogleSignInAccount) { // 监听实时心率数据 Fitness.getSensorsClient(context, account) .add( SensorRequest.Builder() .setDataType(DataType.TYPE_HEART_RATE_BPM) .setSamplingRate(1, TimeUnit.SECONDS) // 每秒采样一次 .build(), object : OnDataPointListener { override fun onDataPoint(dataPoint: DataPoint) { for (field in dataPoint.dataType.fields) { val heartRate = dataPoint.getValue(field).asFloat() // 将读取到的心率写入Google Fit insertHeartRateToFit(context, account, heartRate, dataPoint.timestamp) } } } ) } // 插入心率数据到Google Fit数据源 private fun insertHeartRateToFit(context: Context, account: GoogleSignInAccount, heartRate: Float, timestamp: Long) { val dataSource = DataSource.Builder() .setAppPackageName(context.packageName) .setDataType(DataType.TYPE_HEART_RATE_BPM) .setType(DataSource.TYPE_RAW) .setStreamName("HuaweiWatch2_HeartRate_Stream") // 自定义唯一流名称,避免冲突 .build() val dataPoint = DataPoint.builder(dataSource) .setTimestamp(timestamp, TimeUnit.MILLISECONDS) .setField(Field.FIELD_BPM, heartRate) .build() Fitness.getHistoryClient(context, account) .insertData(DataSet.builder(dataSource).add(dataPoint).build()) .addOnSuccessListener { /* 数据写入成功,可添加日志或回调 */ } .addOnFailureListener { e -> /* 处理写入失败,比如打印Logcat */ } } // 定义权限请求码 private const val REQUEST_OAUTH_PERMISSIONS = 1001
2. 手机端:从Google Fit读取同步的心率数据
手机端需要配置读取心率数据的权限,然后通过Google Fit API监听或读取手表端写入的数据。
Kotlin代码示例:
// 初始化Google Fit客户端,申请读取心率数据的权限 private val fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ) .build() private fun initFitDataReader(context: Context, activity: Activity) { val account = GoogleSignIn.getAccountForExtension(context, fitnessOptions) if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) { GoogleSignIn.requestPermissions( activity, REQUEST_OAUTH_PERMISSIONS, account, fitnessOptions ) } else { startRealTimeHeartRateListener(context, account) } } // 实时监听心率数据更新 private fun startRealTimeHeartRateListener(context: Context, account: GoogleSignInAccount) { Fitness.getSensorsClient(context, account) .add( SensorRequest.Builder() .setDataType(DataType.TYPE_HEART_RATE_BPM) .setSamplingRate(1, TimeUnit.SECONDS) .build(), object : OnDataPointListener { override fun onDataPoint(dataPoint: DataPoint) { for (field in dataPoint.dataType.fields) { val heartRate = dataPoint.getValue(field).asFloat() // 在这里处理心率数据,比如更新App UI、存储到本地等 updateHeartRateUI(heartRate) } } } ) } // 可选:读取历史心率数据(比如最近5分钟) private fun readHistoryHeartRate(context: Context, account: GoogleSignInAccount) { val readRequest = DataReadRequest.Builder() .read(DataType.TYPE_HEART_RATE_BPM) .setTimeRange(System.currentTimeMillis() - 300000, System.currentTimeMillis(), TimeUnit.MILLISECONDS) .build() Fitness.getHistoryClient(context, account) .readData(readRequest) .addOnSuccessListener { response -> for (dataSet in response.dataSets) { processHeartRateDataSet(dataSet) } } } private fun processHeartRateDataSet(dataSet: DataSet) { for (dataPoint in dataSet.dataPoints) { for (field in dataPoint.dataType.fields) { val heartRate = dataPoint.getValue(field).asFloat() // 处理历史数据 } } } private const val REQUEST_OAUTH_PERMISSIONS = 1002
三、关键注意事项
- 权限配置要精准:手机和手表的OAuth客户端ID必须分别配置,包名和签名指纹要和Google Cloud Console中的记录完全一致(包括debug和release签名),否则会出现权限拒绝的问题
- 数据源唯一性:手表端设置的
setStreamName要保证唯一,避免和其他应用的数据源冲突,导致数据读取混乱 - 后台运行稳定性:在三星S7的电池优化设置中,把你的目标应用和WearOS官方应用设置为“不优化”,防止系统杀死后台同步进程
- 实时性优化:如果需要高实时性,优先使用传感器监听(
getSensorsClient)而不是历史数据读取,这样能最快获取到手表端的心率数据
四、排查问题的小技巧
如果之前的代码没生效,可以按以下步骤排查:
- 检查两端Google账号是否一致,Google Fit App是否能正常显示心率数据
- 查看Logcat中的错误日志,重点关注权限、API调用失败、数据源不存在等关键词
- 在手表端的心率回调中打印日志,确认是否真的读取到了有效的心率值
- 验证Google Cloud Console中的Google Fit API是否已启用,客户端ID的签名指纹是否正确
内容的提问来源于stack exchange,提问作者genie137




