Files
digital-pilates/docs/healthkit-implementation.md
2025-09-17 18:05:11 +08:00

229 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HealthKit Native Module 实现文档
本文档描述了为React Native应用添加HealthKit支持的完整实现包括授权和睡眠数据获取功能。
## 功能概述
这个native module提供了以下功能
1. **HealthKit授权** - 请求用户授权访问健康数据
2. **睡眠数据获取** - 从HealthKit读取用户的睡眠分析数据
## 文件结构
```
ios/digitalpilates/
├── HealthKitManager.swift # Swift native module实现
├── HealthKitManager.m # Objective-C桥接文件
├── digitalpilates.entitlements # HealthKit权限配置
└── Info.plist # 权限描述
utils/
├── healthKit.ts # TypeScript接口定义
├── healthKitExample.ts # 使用示例
└── health.ts # 现有健康相关工具
```
## 权限配置
### 1. Entitlements文件
`ios/digitalpilates/digitalpilates.entitlements` 已包含:
```xml
<key>com.apple.developer.healthkit</key>
<true/>
<key>com.apple.developer.healthkit.background-delivery</key>
<true/>
```
### 2. Info.plist权限描述
`ios/digitalpilates/Info.plist` 已包含:
```xml
<key>NSHealthShareUsageDescription</key>
<string>应用需要访问您的健康数据(步数、能量消耗、心率变异性等)以展示运动统计和压力分析。</string>
<key>NSHealthUpdateUsageDescription</key>
<string>应用需要更新您的健康数据(体重信息)以记录您的健身进度。</string>
```
## Swift实现详情
### HealthKitManager.swift
核心功能实现:
#### 授权方法
```swift
@objc func requestAuthorization(
_ resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock
)
```
请求的权限包括:
- 睡眠分析 (SleepAnalysis)
- 步数 (StepCount)
- 心率 (HeartRate)
- 静息心率 (RestingHeartRate)
- 心率变异性 (HeartRateVariabilitySDNN)
- 活动能量消耗 (ActiveEnergyBurned)
- 体重 (BodyMass) - 写入权限
#### 睡眠数据获取方法
```swift
@objc func getSleepData(
_ options: NSDictionary,
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock
)
```
支持的睡眠阶段:
- `inBed` - 在床上
- `asleep` - 睡眠(未分类)
- `awake` - 清醒
- `core` - 核心睡眠
- `deep` - 深度睡眠
- `rem` - REM睡眠
## TypeScript接口
### 主要接口
```typescript
interface HealthKitManagerInterface {
requestAuthorization(): Promise<HealthKitAuthorizationResult>;
getSleepData(options?: SleepDataOptions): Promise<SleepDataResult>;
}
```
### 数据类型
```typescript
interface SleepDataSample {
id: string;
startDate: string; // ISO8601格式
endDate: string; // ISO8601格式
value: number;
categoryType: 'inBed' | 'asleep' | 'awake' | 'core' | 'deep' | 'rem' | 'unknown';
duration: number; // 持续时间(秒)
source: SleepDataSource;
metadata: Record<string, any>;
}
```
## 使用示例
### 基本用法
```typescript
import HealthKitManager, { HealthKitUtils } from './utils/healthKit';
// 1. 检查可用性并请求授权
const initHealthKit = async () => {
if (!HealthKitUtils.isAvailable()) {
console.log('HealthKit不可用');
return false;
}
try {
const result = await HealthKitManager.requestAuthorization();
console.log('授权结果:', result);
return result.success;
} catch (error) {
console.error('授权失败:', error);
return false;
}
};
// 2. 获取睡眠数据
const getSleepData = async () => {
try {
const result = await HealthKitManager.getSleepData({
startDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), // 7天前
endDate: new Date().toISOString(), // 现在
limit: 100
});
console.log(`获取到 ${result.count} 条睡眠记录`);
return result.data;
} catch (error) {
console.error('获取睡眠数据失败:', error);
return [];
}
};
```
### 高级用法
使用提供的 `HealthKitService` 类:
```typescript
import { HealthKitService } from './utils/healthKitExample';
// 初始化并获取昨晚睡眠数据
const checkLastNightSleep = async () => {
const initialized = await HealthKitService.initializeHealthKit();
if (!initialized) return;
const sleepData = await HealthKitService.getLastNightSleep();
if (sleepData.hasData) {
console.log(`睡眠时间: ${sleepData.bedTime} - ${sleepData.wakeTime}`);
console.log(`睡眠时长: ${sleepData.totalDurationFormatted}`);
}
};
// 分析一周睡眠质量
const analyzeSleep = async () => {
const analysis = await HealthKitService.analyzeSleepQuality(7);
if (analysis.hasData) {
console.log(`平均睡眠: ${analysis.summary.averageSleepFormatted}`);
}
};
```
## 工具函数
`HealthKitUtils` 类提供了实用的工具方法:
- `formatDuration(seconds)` - 格式化时长显示
- `getTotalSleepDuration(samples, date)` - 计算特定日期的总睡眠时长
- `groupSamplesByDate(samples)` - 按日期分组睡眠数据
- `getSleepQualityMetrics(samples)` - 分析睡眠质量指标
- `isAvailable()` - 检查HealthKit是否可用
## 注意事项
1. **仅iOS支持** - HealthKit仅在iOS设备上可用Android设备会返回不可用状态
2. **用户权限** - 用户可以拒绝或部分授权,需要优雅处理权限被拒绝的情况
3. **数据可用性** - 并非所有用户都有睡眠数据特别是没有Apple Watch的用户
4. **隐私保护** - 严格遵循Apple的隐私指南只请求必要的权限
5. **后台更新** - 已配置后台HealthKit数据传输权限
## 错误处理
常见错误类型:
- `HEALTHKIT_NOT_AVAILABLE` - HealthKit不可用
- `AUTHORIZATION_ERROR` - 授权过程出错
- `AUTHORIZATION_DENIED` - 用户拒绝授权
- `NOT_AUTHORIZED` - 未授权访问特定数据类型
- `QUERY_ERROR` - 数据查询失败
## 扩展功能
如需添加更多HealthKit数据类型可以
1. 在Swift文件中的 `readTypes` 数组添加新的数据类型
2. 实现对应的查询方法
3. 在TypeScript接口中定义新的方法和数据类型
4. 更新Objective-C桥接文件暴露新方法
## 测试建议
1. 在真实iOS设备上测试模拟器不支持HealthKit
2. 使用不同的授权状态测试
3. 测试没有睡眠数据的情况
4. 验证数据格式和时区处理
5. 测试错误场景的处理
## 相关资源
- [Apple HealthKit文档](https://developer.apple.com/documentation/healthkit)
- [React Native Native Modules](https://reactnative.dev/docs/native-modules-ios)
- [iOS应用权限指南](https://developer.apple.com/documentation/bundleresources/information_property_list/protected_resources)