关于 terra-mobile-sdk
指导在 iOS、Android、React Native 和 Flutter 中集成 Terra API 移动 SDK 的技能,重点覆盖没有 Web API 的设备健康数据源,并说明认证流程、平台配置、权限和运行边缘情况。
主要功能
- 01涵盖四种移动开发平台
- 02说明由后端生成并绑定用户的认证令牌
- 03指导 SDK 初始化与连接检查
- 04详述平台权限和后台数据传送
- 05记录重新连接与设备更换情况
适用场景
- 01将应用连接到 Apple Health 或 HealthKit
- 02集成 Samsung Health 或 Health Connect
- 03实现移动用户的后端令牌生成
- 04排查权限、重新连接或设备更换问题
MCP 相关
说明 Terra API admin MCP 服务可供聊天助手使用的账户管理工具,并区分其与仅限 CLI 的命令。技能指出,生成 data token 需要用户在控制面板批准,且默认 MCP 登录不具备所需访问级别。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tryterra/ agent-skills --skill terra-mobile-sdk安装后在 Claude Code 中输入/terra-mobile-sdk确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonREADME.mdreferences/android.mdflutter.mdios.mdreact-native.md详细介绍
Terra API 移动 SDK
本指南介绍如何在 iOS、Android、React Native 和 Flutter 中集成 Terra API 移动 SDK。工作流以及所有跨平台注意事项都记录在 SKILL.md 中;各平台的设置详情(功能、清单条目、安装坐标、代码片段、平台特有问题)记录在 references/ 中。
账户工具:CLI 或 MCP
对于移动端集成,账户工具会提供后端持有的凭据,并确认设备是否确实已注册。
一次性设置。 用于生成每位用户令牌的后端需要自己的凭据:
terra environments list --select dev_id,name # the dev-id the app is built against
terra data-tokens create --env <dev-id> --name mobile --scopes auth:write
按需检查工作情况。 这些操作是只读的,不会打印任何凭据材料:
terra data-tokens list --env <dev-id> --select token_id,name,scopes,expires_at,last_used_at,revoked_at
terra users list --env <dev-id> --provider APPLE --select user_id,reference_id,active
data-tokens list 只显示元数据,因此是合适的检查方式:它会说明是否存在可用令牌及其作用范围,但不会再次显示任何 bearer 令牌。如需再次显示令牌,则要单独使用受 keys:read 权限控制的 terra data-tokens retrieve-secret。
手动测试令牌生成流程。 这不是读取操作:它会生成 initConnection() 所需的短期令牌,并将其打印出来。
terra data-api /auth/tokens -X POST -q reference_id=<your id>
这里的 reference_id 是一个查询参数,因此要用 -q。用 -d 传入会将它放进端点不会读取的 JSON 请求体中;调用仍会成功,但返回的令牌会悄悄变成未绑定状态。这很重要,因为绑定可以防止令牌将设备关联到错误的用户。绑定后,令牌会与该标识符关联,兑换时会忽略 SDK 发送的任何内容。(/auth/generateWidgetSession 确实会接收请求体,因此在那里使用 -d 才正确。请用 terra admin-api list --data-api <path> --format json 核实,而不要想当然。)
这适合在后端尚未搭建时端到端检查流程,但它仍会将凭据输出到 stdout,因此不要让它进入 CI 日志。
参考文件和随附的 SDK 版本使用 POST /auth/generateAuthToken。这是该端点已弃用的旧名称,与当前名称完全相同,参数和响应也一致;由于已发布的 SDK 会调用该路径,因此会一直保留。两种名称都可用;新代码应使用 /auth/tokens。
只有在确实需要环境 API 密钥时,才使用 terra environments retrieve-api-key。移动端流程中的任何操作都不需要它,而且该命令会同时打印 webhook 签名密钥。
绝不要在应用中打包管理员令牌或环境 API 密钥。 SDK 使用按用户生成的短期身份验证令牌;terra data-tokens create --scopes auth:write 则是为生成这些令牌的后端提供的、作用范围明确且可撤销的凭据:每个环境可以同时存在多个令牌,因此轮换时只需生成新令牌再撤销旧令牌,无需切换。通过 MCP 生成数据令牌需要用户在仪表板中批准,而且访问级别必须高于默认 MCP 登录所授予的级别,因此这一步用 CLI 会更简单。
设备连接后,terra users list --reference-id <ref> 可以说明记录是否已写入并保持活跃,从而区分是 SDK 问题还是权限问题。
在编码 Agent(Claude Code、Codex、Cursor 等,无论运行在用户设备还是云端)中,请使用 CLI;如果尚未安装,可提供安装方式:在 macOS 和 Linux 上运行 curl -fsSL https://cli.tryterra.co/install.sh | sh,在 Windows PowerShell 中运行 irm "https://cli.tryterra.co/install.ps1" | iex,或者使用用户已经在用的 Homebrew 或 npm。在聊天助手(claude.ai、Claude Desktop、ChatGPT)中,请使用 Terra API 管理 MCP 服务,即使它可以运行代码也是如此:它的沙盒无法安装 CLI 或登录。每条管理命令都是一个工具,其名称和 method 都能体现命令内容(terra users list 对应 users_read,method: "list")。只有 CLI 提供 terra data-api、terra admin-api 和 terra examples,而且 --select 和 --jq 没有对应的 MCP 功能。terra-cli 和 terra-mcp 技能包含防护措施(确认更改、避免在对话记录中泄露凭据)、错误说明,以及按任务编写的操作指南。它们用于管理集成,不会替代本文档说明的 API 调用。
何时适合使用移动 SDK
移动 SDK 的用途只有一个:连接没有 Web API 的健康数据源。只有三种集成需要使用它:
- Apple Health / HealthKit(iOS)
- Samsung Health(Android)
- Health Connect(Android)
所有其他提供商(Garmin、Fitbit、Oura、Whoop、Strava、Dexcom 等 500 多种)都通过 Unified API 连接,而不是通过 SDK。Google Fit 可以通过 Health Connect 使用 SDK 读取,但 Web API 是首选且更可靠的方式。如果你需要的提供商有 Web API,请使用 Web API。
SDK 捕获的数据会流向与 Web API 数据相同的数据目标(Webhook),连接也使用相同的身份验证模型进行管理。如果你正在构建接收 Webhook 或存储健康数据的功能,那属于 terra-unified-api 技能的范围;本技能涵盖设备端连接。来自 BLE 或 ANT+ 可穿戴设备的实时、逐秒数据属于独立的 Real-Time SDK,由 terra-streaming 涵盖。
六步工作流
每个平台的流程都相同。平台差异请参阅 references/ 文件。
- 安装 SDK 并授予原生功能权限。 添加软件包,声明 HealthKit/后台功能(iOS),或清单权限及 minSDK 28(Android)。请参阅对应平台的参考文档。
- 每次应用启动及每次进入前台时都初始化 SDK。 创建
TerraManager(iOS/Android),或调用initTerra(RN/Flutter)。此调用是异步的,必须在任何其他 SDK 调用之前完成。初始化是使用所有其他功能的前提,因此每次打开应用时都要执行,而不只是安装后执行一次。 - 从你的后端获取一次性身份验证令牌。 调用
POST https://api.tryterra.co/v2/auth/tokens(已弃用的/auth/generateAuthToken是相同的端点),并将用户标识符作为reference_id查询参数,以便令牌绑定到该用户。使用上文“Account tools”中的auth:write数据令牌进行身份验证,通过Authorization: Bearer terra_dt_...发送;令牌绑定到单个环境,因此无需dev-id标头。参考文件中展示的dev-id和x-api-key组合仍然有效,但它是环境的主密钥。令牌只能使用一次,且会在 3 分钟后过期(响应中包含expires_in),因此应在用户发起连接时即时获取,而不是在应用启动时获取。通过你自己的渠道将令牌交给客户端。无论在开发还是生产环境中,都不要从应用调用此端点:任何能够获取令牌的凭据都必须保留在你的服务器上。 - 使用
initConnection打开连接。 传入连接类型、令牌和权限集。这会触发操作系统的权限弹窗。请参阅下文“权限弹窗行为”——这是集成中阻力最大的环节。 - 每次重新初始化时,都使用
getUserId验证。getUserId是同步的;如果连接正常,它会返回user_id,否则返回nil/null。每次初始化后立即调用;如果返回nil,则再次调用initConnection以重新连接。已连接的用户重新连接时不会触发弹窗,也不会打断用户。 - 仅限 iOS:启用后台数据推送。 在
AppDelegate的didFinishLaunchingWithOptions中调用Terra.setUpBackgroundDelivery()。如果不启用,Apple Health 数据就不会自动推送。
取消用户身份验证使用与 Web 集成相同的端点:从你的后端调用 DELETE /auth/deauthenticateUser。请参阅 Web API 身份验证参考文档。
权限弹窗行为(发布前请阅读)
- 弹窗只会显示一次。 在 Apple Health 和 Health Connect 上,操作系统只会在首次显示权限界面。再次调用
initConnection不会触发弹窗。只有在以下情况下才会重新触发:(a)调用initConnection时使用了扩展后的customPermissions集合;(b)删除并重新安装应用;(c)仅限 Health Connect——请求 Google 尚未批准在你的应用正式发布版本中使用的权限。 - HealthKit 弹窗是一个 WebView。 如果你的应用本身基于 WebView,你必须中断 WebView,调用
initConnection,并在完成后重新打开 WebView。否则弹窗无法显示。 getUserId返回nil表示需要重新连接,而不是重新弹出权限界面。 重新连接仍然已获授权的用户时,不会显示提示。
后台数据传送(iOS)
Terra.setUpBackgroundDelivery() 可启用 Apple Health 自动推送,但数据传送受到以下限制:
- 应用被终止时,触发频率会低得多。
- 仅在手机已解锁时触发。
- 仅在有网络连接时触发。
- 仅传送 Terra API 控制面板中启用的数据类型。
terra unified-api data scopes list --env <dev-id>可读取该集合。如需更改,请使用terra unified-api data scopes replace,并提供完整集合:未列出的每种类型都会被取消选择,因此请先读取列表,再将其连同新增项一起提交。 - 如果使用
customPermissions,后台数据传送需要启用特定类别的权限:Daily 需要STEPS;Sleep 需要SLEEP_ANALYSIS;Body 需要BMI和HEART_RATE;Activity 需要WORKOUT_TYPE;Nutrition 需要NUTRITION_CALORIES。
schedulerOn 对 iOS 没有影响——后台数据传送完全由 setUpBackgroundDelivery() 控制。在 Android 上,schedulerOn = true 会启用 Terra API,使其在应用处于前台时发送计划请求。
跨平台注意事项
- Samsung Health 需要获得批准的合作伙伴资格。 Terra API 拥有 Samsung 的特权合作伙伴资格,可绕过 Health Connect,但你必须申请访问权限。等待期间,请基于 Health Connect 进行开发;之后切换到 Samsung 直连只需升级版本,无需更改代码。发布版本需要 ProGuard 规则
-keep class com.samsung.android.** { *; }(否则 R8 会移除 Samsung 类并导致运行时崩溃),测试设备还需要在 Samsung Health 中启用开发者模式。 - Health Connect 需要配置清单并获得 Google 批准。 你的清单需要一个隐私政策
<activity>,并配置ACTION_SHOW_PERMISSIONS_RATIONALE和VIEW_PERMISSION_USAGEintent-filter。正式上线前,你必须向 Google 申请 Health Connect 数据类型访问权限,并为每项不使用的权限添加tools:node="remove"<uses-permission>行。请参阅references/android.md。 setIgnoredSources仅适用于 iOS,且不会持久保存。 它会过滤 HealthKit 中特定来源应用的数据(当用户同时拥有云端 Terra API 连接和该提供方的配套应用,并将数据同步到 Apple Health 时,这很有用,因为这种情况会产生重复数据)。应用每次重启后该设置都会重置,因此每次初始化后都要调用它。在 Android 上它不执行任何操作。- 新设备或重新安装会替换现有连接——请处理
user_reauth。 当 SDK 身份验证使用与现有连接相同的(dev-id, reference_id, provider),但设备标识符不同(第二台设备,或重置了供应商 ID 的重新安装)时,Terra API 会发放新的user_id、删除该元组的所有旧连接,并发送携带old_user和new_user的user_reauthwebhook。收到此事件后,请将存储的old_user.user_id迁移到new_user.user_id;每个(dev-id, reference_id, provider)始终只有一个有效连接。只有在提供reference_id时才会触发这种替换——如果reference_id为空,旧连接会不断累积,这也是始终设置reference_id的另一个理由。 postActivity需要device_data,且要求 iOS 14+。 如果负载中没有device_data,写入已完成的活动会失败。
由你决定的事项
这些由你决定;文档不作规定。请审慎决策:
- 要申请哪些数据类型/权限。
customPermissions为空时默认包含所有可用项;缩小范围可以减少权限覆盖面,但必须保持启用上述后台传输类别。 - 立即还是延后弹出 HealthKit 权限请求。 在
Terra.instance中设置requestPermissions: false,可以静默识别回访用户,并让你在用户明确操作时再显示弹窗。请参阅references/ios.md。 - 设备切换处理方式。 第二台设备或重新安装会替换现有连接并触发
user_reauth(见上文),因此请决定是允许任意设备连接(并在user_reauth时迁移user_id),还是将initConnection限制为单台主设备。 - 选择 Samsung 直连还是 Health Connect 作为 Android 接入方式(以及是否在 Samsung 合作伙伴资格审批期间先使用 Health Connect)。
- 回填方案。
getDaily/getSleep/等 getter 接受toWebhook: true(推送到你的目标位置)或toWebhook: false(通过客户端回调返回负载)。 - 后端如何将身份验证令牌传给客户端,以及你的
reference_id方案(它是每个 webhook 中的关联键)。
平台参考
阅读与你所构建的平台对应的文件:
references/ios.md– 在原生集成 TerraiOS(Swift)时阅读:功能、info.plist 键、Terra.instance、延迟提示、setUpBackgroundDelivery、setIgnoredSources、写入数据、计划锻炼的 WorkoutKit 同步。references/android.md– 在原生集成 TerraAndroid(Kotlin)时阅读:build.gradle坐标、最低 SDK 28、Samsung 与 Health Connect 的设置、ProGuard、manifest intent-filters、startIntent(已弃用,始终为 null)。references/react-native.md– 在集成 terra-react 时阅读:安装、iOS + Android 原生设置、initTerra/initConnection、AppDelegate 后台传递修改、postActivity(仅限 Apple Health)。references/flutter.md– 在集成 terra_flutter_bridge 时阅读:flutter pub、原生设置、TerraFlutterAPI、AppDelegate 后台传递、getter。
完整文档:docs.tryterra.co。如果此处未展示某个签名或枚举,请参阅 仅限移动平台的来源中链接的 SDK 参考。获取文档页面前,请先询问 terra docs ask(或通过 MCP 使用 docs_ask):它会根据文档作答并注明来源。给任何文档 URL 追加 .md 即可获取 Markdown。