Google Fit REST API授权失败求助&健康历史数据写入需求
解决Google Fit OAuth授权错误及数据写入指导
一、OAuth授权错误(错误400: invalid_request)修复方案
1. 修正OAuth客户端配置
- 确保在Google Cloud控制台创建的是桌面应用类型的OAuth客户端ID。本地脚本属于桌面应用场景,若之前创建的是Web/移动应用类型,需重新创建桌面客户端,系统会自动生成适配的重定向URI(如
urn:ietf:wg:oauth:2.0:oob或http://localhost)。 - 脚本中
redirect_uri需使用单个URI字符串,而非列表。修改代码:# 原代码:redirect_uri = redirect_uris redirect_uri = redirect_uris[0] # 取列表第一个元素
2. 缩小权限范围
替换宽泛的https://www.googleapis.com/auth/fitness范围,根据实际需求使用具体权限:
- 写入活动数据(如步数):
https://www.googleapis.com/auth/fitness.activity.write - 写入心率数据:
https://www.googleapis.com/auth/fitness.heart_rate.write - 其他数据类型对应权限可参考Google Fit官方权限说明
3. 添加测试用户(未验证应用)
未通过Google OAuth验证的应用只能对测试用户开放授权:
- 进入Google Cloud控制台 → API和服务 → OAuth同意屏幕
- 在“测试用户”板块添加你自己的Google账号
- 使用该测试账号进行授权操作
4. 修正API请求URL
脚本中最后两个GET请求存在路径错误,修正为:
# 获取步数衍生数据源详情 r = google.get('https://www.googleapis.com/fitness/v1/users/me/dataSources/derived:com.google.step_count.delta:com.google.android.gms:merge_step_deltas') # 获取当前用户所有数据源 r = google.get('https://www.googleapis.com/fitness/v1/users/me/dataSources')
二、Google Fit REST API写入数据步骤
1. 匹配数据类型与数据源
首先确认Apple Health数据对应的Google Fit数据类型,比如:
- 步数:
com.google.step_count.delta - 体重:
com.google.weight - 心率:
com.google.heart_rate.bpm
对于常见数据类型,可直接使用Google提供的衍生数据源(如步数的derived:com.google.step_count.delta:com.google.android.gms:merge_step_deltas),无需自定义数据源。
2. 构造符合要求的请求体
Google Fit写入数据使用users/me/dataset:patch接口,请求体需包含:
dataSourceId:目标数据源IDpoint:数据点数组,每个数据点需包含:startTimeNanos:数据起始时间(纳秒级字符串)endTimeNanos:数据结束时间(纳秒级字符串)value:数据值(根据类型选择intVal/floatVal/stringVal等)
3. pandas DataFrame转Google Fit数据示例
假设你的DataFrame包含date(日期)和step_count(当日步数)两列,转换并写入的代码示例:
import pandas as pd # 示例DataFrame df = pd.DataFrame({ 'date': ['2024-01-01', '2024-01-02'], 'step_count': [8500, 9200] }) # 配置参数 data_source_id = "derived:com.google.step_count.delta:com.google.android.gms:merge_step_deltas" # 构造数据点 data_points = [] for _, row in df.iterrows(): # 转换日期为纳秒时间戳 start_ts = pd.Timestamp(row['date']).timestamp() * 1e9 end_ts = start_ts + 86400 * 1e9 # 当日结束时间(+1天的秒数转纳秒) data_points.append({ "startTimeNanos": str(int(start_ts)), "endTimeNanos": str(int(end_ts)), "value": [{"intVal": int(row['step_count'])}] }) # 构造数据集ID(格式:起始纳秒-结束纳秒) start_nanos = str(int(pd.Timestamp(df['date'].min()).timestamp() * 1e9)) end_nanos = str(int(pd.Timestamp(df['date'].max()).timestamp() * 1e9 + 86400 * 1e9)) dataset_id = f"{start_nanos}-{end_nanos}" # 发送写入请求 response = google.patch( url=f"https://www.googleapis.com/fitness/v1/users/me/datasets/{dataset_id}", json={"dataSourceId": data_source_id, "point": data_points} ) # 检查响应 if response.status_code == 200: print("数据写入成功") else: print(f"写入失败:{response.json()}")
4. 注意事项
- 拆分数据写入:避免一次性写入过大时间范围的数据,建议按天或按周拆分请求,避免触发API限流。
- 去重处理:若数据已存在于Google Fit,重复写入会覆盖原有数据,建议先查询已有数据再决定是否写入。
- 配额限制:Google Fit API有每日请求配额,若数据量较大,需添加请求间隔(如
time.sleep(1))。
内容的提问来源于stack exchange,提问作者SiSchi
相关产品推荐
相关产品推荐

