feat: 支持 healthkit
This commit is contained in:
229
docs/healthkit-implementation.md
Normal file
229
docs/healthkit-implementation.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user