跳转至正文

Capacitor 中的 Google Fit 到 Health Connect 迁移

在 2026 年 Fit API 停用前,将 Capacitor 应用从 Google Fit 迁移到 Health Connect:数据类型映射、权限、查询及 Play 审核。

将 Capacitor 健身应用从 Google Fit 迁移到 Health Connect

从 Google Fit 迁移到 Health Connect 意味着在 Android 上用 Health Connect 替换 Capacitor 应用中所有的 Fit API 调用,如果也发布到 iOS,则用 HealthKit 替换。Google 已于 2024 年 5 月 1 日停止接受新的 Fit 注册,且仅支持 Fit API 至 2026 年底。本指南将 Fit 数据类型和调用映射到 Health Connect,并展示替换用的 code @capgo/capacitor-health,以及涉及健康权限的 Play Console 审核流程。

Google Fit 弃用时间表

日期 事情经过
2024 年 5 月 1 日 Google Fit API 不再接受新的开发者注册
2024 年至 2026 年 现有的 Fit 集成继续运行,Google 引导开发者转向 Health Connect
2026 Fit API(包括 REST API)已弃用
2026 年底 停止支持。Google 尚未公布确切的停用日期

Google 的迁移常见问题解答指出,没有与 Fit REST API 结构相同的替代方案:设备端应用将迁移到 Health Connect,云端集成将迁移到基于账户的 Google Health API。如果您在某处看到确切的停用日期,请在据此规划之前,先对照 Google 官方的常见问题解答进行核实。

迁移到 Health Connect 后有哪些变化

Google Fit Health Connect
数据存储位置 Google 账号,云端存储 设备本地
身份验证 包含健身权限的 OAuth 2.0,Google Sign-In 针对不同数据类型的 Android 运行时权限
配置 Cloud 项目,OAuth 客户端,SHA-1 指纹 Manifest 权限,隐私政策页面
可用性 任何支持 Play 服务的 Android 设备 Android 14+ 内置,旧版本需从 Google Play 安装应用
历史记录 完整账户历史记录 默认最近 30 天,更早数据需 READ_HEALTH_DATA_HISTORY
Web/服务器访问 REST API 无(云端请使用 Google Health API)
iOS 暂不支持 不支持,请使用 HealthKit
应用商店审核 敏感权限的 OAuth 验证 Play Console 中的 Health Connect 声明

最大的产品变化是以设备为中心的模式。一部手机上的 Health Connect 数据在另一部手机上不可见。如果你的应用需要跨设备显示历史记录,请将读数同步到你自己的后端。

将 Fit 数据类型映射到 Health Connect

Google Fit 数据类型 Health Connect 记录 @capgo/capacitor-health 类型
com.google.step_count.delta StepsRecord steps
com.google.distance.delta DistanceRecord distance
com.google.calories.expended TotalCaloriesBurnedRecord / ActiveCaloriesBurnedRecord totalCalories / calories
com.google.calories.bmr BasalMetabolicRateRecord basalCalories
com.google.heart_rate.bpm HeartRateRecord heartRate
com.google.weight WeightRecord weight
com.google.height HeightRecord height
com.google.body.fat.percentage BodyFatRecord bodyFat
com.google.sleep.segment SleepSessionRecord 包含阶段 sleep
com.google.oxygen_saturation OxygenSaturationRecord oxygenSaturation
com.google.blood_pressure BloodPressureRecord bloodPressure
com.google.blood_glucose BloodGlucoseRecord bloodGlucose
com.google.body.temperature BodyTemperatureRecord bodyTemperature
com.google.hydration HydrationRecord dietaryWater
com.google.nutrition NutritionRecord dietaryEnergyConsumed (仅限能量)
com.google.activity.segment 和 Sessions API ExerciseSessionRecord workouts (通过 queryWorkouts)

无直接对应类型的 Fit 数据

  • 心点 (com.google.heart_minutes) 以及 移动分钟数 (com.google.active_minutes)是 Google Fit 的评分。Health Connect 存储原始数据,而非这些评分。请基于心率和锻炼会话自行计算指标。
  • 活动样本 中按秒记录的活动类型,将由带片段的锻炼会话取代。
  • 位置采样 在锻炼中的位置数据变为 ExerciseRoute Health Connect 中的数据,这需要单独权限,且插件未暴露此功能。
  • 节奏、速度和功率 存在于 Health Connect 中(StepsCadenceRecord, SpeedRecord, PowerRecord),但插件的类型定义未涵盖。如果你依赖这些字段,编写一个小型自定义原生方法是最快的路径。

在编写 code 之前进行审计:列出所有 DataType 以及你调用的每个 API(History、Recording、Sessions、Sensors、Config、REST),并将每一项标记为已映射、已重算或已弃用。

步骤 1:移除 Google Fit

从你的 Android 项目和 JavaScript 中删除 Fit 集成:

  • 移除 com.google.android.gms:play-services-fitness 以及,如果仅用于 Fit, play-services-auth 来自 build.gradle.
  • 从 Google Cloud 中移除 Fit OAuth 客户端,并从你的同意屏幕中移除健身权限范围。
  • 卸载你之前使用的旧版社区 Google Fit Capacitor 插件,然后运行 bunx cap sync.

在新版本上线之前,请将 Fit code 保留在分支中,以便在用户要求时导出历史数据。

步骤 2:安装健康插件

bun add @capgo/capacitor-health
bunx cap sync

@capgo/capacitor-health 支持 Capacitor 8,在 Android 上使用 Health Connect,在 iOS 上使用 HealthKit,并且需要 Android minSdk 26.

Android 配置

该插件会将其支持类型的 Health Connect 读写权限合并到您的 manifest 中,此外还有 <queries> Health Connect 包的 entry 以及权限说明 activity。您需要:

  1. 提供隐私政策。 Health Connect 会从权限面板中打开它。请添加 android/app/src/main/assets/public/privacypolicy.html,或在 android/app/src/main/res/values/strings.xml:
<string name="health_connect_privacy_policy_url">https://example.com/privacy</string>
  1. 中设置 URL 精简权限。 tools:node="remove":
<uses-permission
    android:name="android.permission.health.WRITE_BLOOD_GLUCOSE"
    tools:node="remove" />
  1. 如需访问历史记录,请添加相应权限。 除非用户授权,否则 Health Connect 只能读取最近约 30 天的数据 READ_HEALTH_DATA_HISTORY:
<uses-permission android:name="android.permission.health.READ_HEALTH_DATA_HISTORY" />

iOS 配置

在 Xcode 中启用 HealthKit capability,并添加用途说明字符串到 Info.plist:

<key>NSHealthShareUsageDescription</key>
<string>Show your steps and workouts in the app.</string>
<key>NSHealthUpdateUsageDescription</key>
<string>Save the workouts you record in the app.</string>

步骤 3:检查可用性

Google Fit 在任何有 Play 服务的地方都能用。Health Connect 在 Android 13 及更早版本上可能没有,或者需要更新。

import { Health } from '@capgo/capacitor-health';

export async function ensureHealthAvailable() {
  const result = await Health.isAvailable();
  if (result.available) return true;

  // On Android, send the user to install or update Health Connect
  if (result.platform === 'android') {
    await Health.openHealthConnectSettings();
  }
  console.warn('Health store unavailable:', result.reason);
  return false;
}

在跳转前显示一个简短的说明页。从没听说过 Health Connect 的用户,看到 Play Store 突然打开会感到困惑。

步骤 4:用权限替换 OAuth

Fit 的流程是:Google 登录,请求健身 scope,然后调用 API。新流程只有一个权限弹窗:

const status = await Health.requestAuthorization({
  read: ['steps', 'distance', 'calories', 'heartRate', 'sleep', 'workouts'],
  write: ['weight'],
  requestHistoryAccess: true, // Android only
});

if (status.readDenied.length > 0) {
  // explain what will not work and offer openHealthConnectSettings()
}
if (status.historyAccessAvailable === false) {
  // provider too old: only the last 30 days are readable
}

权限按数据类型划分,用户可以只授予其中一部分。使用 checkAuthorization 在每次应用启动时用相同的选项调用,因为用户随时可以在 Health Connect 设置里撤销授权。在 iOS 上,HealthKit 出于隐私会隐藏读取被拒的情况,所以空结果可能表示“没有数据”,也可能表示“没有权限”。

步骤 5:替换 History API 读取

一个 Fit readData 获取原始样本的调用变为 readSamples:

const end = new Date();
const start = new Date(end.getTime() - 24 * 60 * 60 * 1000);

const { samples } = await Health.readSamples({
  dataType: 'heartRate',
  startDate: start.toISOString(),
  endDate: end.toISOString(),
  limit: 500,
  ascending: true,
});

for (const s of samples) {
  console.log(s.startDate, s.value, s.unit, s.sourceName, s.deviceType);
}

sourceName 而在 Android 上, deviceType (watch, phone, chestStrap等)替代 Fit 的数据源对象。当手表和手机同时存在数据时,使用它们优先选择手表数据。

第 6 步:替换分桶与聚合读取

Fit 的 bucketByTime 加 aggregate 会变为 queryAggregated:

const { samples: daily } = await Health.queryAggregated({
  dataType: 'steps',
  startDate: new Date(Date.now() - 7 * 86_400_000).toISOString(),
  endDate: new Date().toISOString(),
  bucket: 'day',          // 'hour' | 'day' | 'week' | 'month'
  aggregation: 'sum',
});

const { samples: hr } = await Health.queryAggregated({
  dataType: 'heartRate',
  bucket: 'hour',
  aggregation: ['min', 'average', 'max'],
  startDate: new Date(Date.now() - 86_400_000).toISOString(),
  endDate: new Date().toISOString(),
});
// hr[i].values.min, hr[i].values.average, hr[i].values.max

始终聚合步数,而不是对原始样本求和。Health Connect 在聚合过程中会去重来自多个应用的重复数据,而原始求和往往会在手表和手机同时记录步数时导致重复计算。

第 7 步:替换 Sessions API

Fit 会话映射到运动会话:

const { workouts, anchor } = await Health.queryWorkouts({
  workoutType: 'running',
  startDate: new Date(Date.now() - 30 * 86_400_000).toISOString(),
  endDate: new Date().toISOString(),
  limit: 50,
});

for (const w of workouts) {
  console.log(w.workoutType, w.duration, w.totalDistance, w.totalEnergyBurned);
}
// pass `anchor` back to fetch the next page

请求 workouts 中的 read 先处理权限。该插件会读取锻炼数据,但不会写入运动记录,所以如果你的应用要记录锻炼,请写入底层样本(距离、卡路里、心率),并把运动记录本身保存在后端,或添加一个原生方法用于 ExerciseSessionRecord.

第 8 步:替换插入操作

Fit 的 insertData 会变为 saveSample:

await Health.saveSample({
  dataType: 'weight',
  value: 72.4, // kilograms
  startDate: new Date().toISOString(),
});

await Health.saveSample({
  dataType: 'bloodPressure',
  value: 120,
  systolic: 120,
  diastolic: 80,
  startDate: new Date().toISOString(),
});

值必须使用每种类型的默认单位(千克、米、千卡、bpm)。 metadata 该选项会被 Health Connect 忽略。

第 9 步:通过 Google Play 审核

健康权限会触发额外审核:

  1. 在 Play Console 中,打开 应用内容 并完成 健康应用 声明以及 Health Connect 权限表单。请为请求的每一项权限提供正当理由。
  2. 确保 Play Console 中链接的隐私政策与 Health Connect 界面中显示的隐私政策均说明了健康数据的使用方式。
  3. 更新 数据安全 表单:健康与健身数据,是否收集,是否共享。
  4. 提交仅声明已提供正当理由的权限的构建版本。额外声明的权限是最常见的被拒原因。

预留比常规更新更长的审核时间。将迁移作为独立版本发布,不要与无关功能混合。

第 10 步:迁移用户预期

  • 告知用户其历史记录现在来自 Health Connect,且在授予历史访问权限之前,旧数据可能仅限于最近 30 天。
  • 如果您的应用使用 Fit 进行云端同步,请现在将该职责转移到您的后端。
  • 移除“连接 Google Fit”按钮,在 Android 上将其重命名为“连接 Health Connect”,在 iOS 上重命名为“连接 Apple Health”。

故障排除

isAvailable() 在 Android 13 上返回 false:Health Connect 未安装或版本过旧。请调用 openHealthConnectSettings().

权限弹窗从未出现:权限未在合并后的 manifest 中声明,或您已使用 tools:node="remove"的文件夹。请检查 android/app/build/intermediates/merged_manifests.

读取仅返回 30 天数据: 请求 requestHistoryAccess: true 并声明 READ_HEALTH_DATA_HISTORY.

步数总和高于 Google Fit:您累加了原始样本。请使用 queryAggregated.

iOS 上结果为空:要么没有数据,要么读取权限被拒绝。HealthKit 不会告诉你是哪种情况。

Play Console 拒绝该更新:移除未声明或无合理依据的 Health Connect 权限,并附上明确理由后重新提交。

分阶段发布迁移

原生部分(插件、manifest、HealthKit capability)需要发布商店版本。之后,查询、UI 和数据映射都是 JavaScript,你可以用 Live Updates 迭代。 Capgo 实时更新 同时让用户测试新流程。如果你还要读取实时传感器数据,请参阅我们的指南: 使用 Capacitor 构建心率监测仪,以及 健康插件文档 涵盖每种数据类型。

为 Capacitor 应用提供 Live Updates

当 Web 层出现线上 Bug 时,通过 Capgo 发布修复,而不用等 App Store 审核好几天。用户会在后台收到更新,原生变更则仍走正常审核流程。

博客最新动态

Capgo 为你提供打造真正专业的移动应用所需的最有价值的洞察。