健康
启用与 Apple Health 和 Google Fit 的健康数据读写。
该插件支持
- 通过
hasPermissions、requestAuthorization、revokePermissions方法处理健康数据访问权限。 - 通过
getHealthDataFromTypes方法读取健康数据。 - 通过
writeHealthData方法写入健康数据。 - 通过
writeWorkout方法在 iOS 上写入训练数据。 - 通过
writeAudiogram方法在 iOS 上写入听力图数据。 - 通过
getTotalStepsInInterval方法访问总步数。 - 通过
removeDuplicates方法清除重复数据点。
请注意,对于 Android,目标手机需要安装 Google Fit 并有互联网访问权限,否则该插件将无法正常工作。
数据类型
| 数据类型 | 单位 | iOS | Android | 注释 |
|---|---|---|---|---|
| ACTIVE_ENERGY_BURNED | 卡路里 | 是 | 是 | |
| BASAL_ENERGY_BURNED | 卡路里 | 是 | ||
| BLOOD_GLUCOSE | 毫克/分升 | 是 | 是 | |
| BLOOD_OXYGEN | 百分比 | 是 | 是 | |
| BLOOD_PRESSURE_DIASTOLIC | 毫米汞柱 | 是 | 是 | |
| BLOOD_PRESSURE_SYSTOLIC | 毫米汞柱 | 是 | 是 | |
| BODY_FAT_PERCENTAGE | 百分比 | 是 | 是 | |
| BODY_MASS_INDEX | 无单位 | 是 | 是 | |
| BODY_TEMPERATURE | 摄氏度 | 是 | 是 | |
| ELECTRODERMAL_ACTIVITY | 西门子 | 是 | ||
| HEART_RATE | 次/分钟 | 是 | 是 | |
| HEIGHT | 米 | 是 | 是 | |
| RESTING_HEART_RATE | 次/分钟 | 是 | ||
| STEPS | 计数 | 是 | 是 | |
| WAIST_CIRCUMFERENCE | 米 | 是 | ||
| WALKING_HEART_RATE | 次/分钟 | 是 | ||
| WEIGHT | 千克 | 是 | 是 | |
| DISTANCE_WALKING_RUNNING | 米 | 是 | ||
| FLIGHTS_CLIMBED | 计数 | 是 | ||
| MOVE_MINUTES | 分钟 | 是 | ||
| DISTANCE_DELTA | 米 | 是 | ||
| MINDFULNESS | 分钟 | 是 | ||
| SLEEP_IN_BED | 分钟 | 是 | 是 | |
| SLEEP_ASLEEP | 分钟 | 是 | 是 | |
| SLEEP_AWAKE | 分钟 | 是 | 是 | |
| WATER | 升 | 是 | 是 | 在 Android 上,饮水量需要注册第三方应用。 |
| EXERCISE_TIME | 分钟 | 是 | ||
| WORKOUT | 无单位 | 是 | 是 | |
| HIGH_HEART_RATE_EVENT | 无单位 | 是 | 需要 Apple Watch | |
| LOW_HEART_RATE_EVENT | 无单位 | 是 | 需要 Apple Watch | |
| IRREGULAR_HEART_RATE_EVENT | 无单位 | 是 | 需要 Apple Watch | |
| HEART_RATE_VARIABILITY_SDNN | 毫秒 | 是 | 需要 Apple Watch | |
| HEADACHE_NOT_PRESENT | 分钟 | 是 | ||
| HEADACHE_MILD | 分钟 | 是 | ||
| HEADACHE_MODERATE | 分钟 | 是 | ||
| HEADACHE_SEVERE | 分钟 | 是 | ||
| HEADACHE_UNSPECIFIED | 分钟 | 是 | ||
| AUDIOGRAM | DECIBEL_HEARING_LEVEL | 是 |
设置
Apple Health (iOS)
步骤 1:在 Info.plist 中添加以下 2 个条目
<key>NSHealthShareUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>
<key>NSHealthUpdateUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>
步骤 2:“Capabilities”选项卡中启用“HealthKit”。
Google Fit (Android)
请遵循 https://developers.google.com/fit/android/get-api-key 上的指南。
以下是遵循该指南的示例
将目录更改为您的密钥存储目录 (MacOS):cd ~/.android/
获取您的密钥存储 SHA1 指纹:keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
示例输出
Alias name: androiddebugkey
Creation date: Jan 01, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4aa9b300
Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033
Certificate fingerprints:
MD5: AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9
SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75
Signature algorithm name: SHA1withRSA
Version: 3
请遵循 https://developers.google.com/fit/android/get-api-key 上的说明,为 Google 项目设置 OAuth2 Client ID,并将 SHA1 指纹添加到该 OAuth2 凭据。
客户端 ID 将类似于 YOUR_CLIENT_ID.apps.googleusercontent.com。
Android 权限
从 API 级别 28 (Android 9.0) 开始,访问某些健身数据(例如步数)需要特殊权限。
要设置它,请将以下行添加到您的 AndroidManifest.xml 文件中。
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
此外,对于训练:如果请求了训练距离,则需要下面的位置权限。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
有一个 debug、main 和 profile 版本,它们根据您启动应用的方式而选择。通常,仅将权限添加到 main 版本就足够了。
由于这是一个标记为 dangerous 的保护级别,权限系统不会自动授予它,它需要用户的操作。您可以使用 permission_handler 插件提示用户。遵循插件设置说明,并在请求数据之前添加以下行
await Permission.activityRecognition.request();
Android X
将 android/gradle.properties 文件的内容替换为以下行
org.gradle.jvmargs=-Xmx1536M
android.enableJetifier=true
android.useAndroidX=true
用法
有关如何使用 Health API 的详细示例,请参阅示例应用。
Health 插件通过 HealthFactory 类使用,使用不同的方法来处理权限以及获取和添加数据到 Apple Health / Google Fit。以下是使用该插件的简化流程。
// create a HealthFactory for use in the app
HealthFactory health = HealthFactory();
// define the types to get
var types = [
HealthDataType.STEPS,
HealthDataType.BLOOD_GLUCOSE,
];
// requesting access to the data types before reading them
bool requested = await health.requestAuthorization(types);
var now = DateTime.now();
// fetch health data from the last 24 hours
List<HealthDataPoint> healthData = await health.getHealthDataFromTypes(
now.subtract(Duration(days: 1)), now, types);
// request permissions to write steps and blood glucose
types = [HealthDataType.STEPS, HealthDataType.BLOOD_GLUCOSE];
var permissions = [
HealthDataAccess.READ_WRITE,
HealthDataAccess.READ_WRITE
];
await health.requestAuthorization(types, permissions: permissions);
// write steps and blood glucose
bool success = await health.writeHealthData(10, HealthDataType.STEPS, now, now);
success = await health.writeHealthData(3.1, HealthDataType.BLOOD_GLUCOSE, now, now);
// get the number of steps for today
var midnight = DateTime(now.year, now.month, now.day);
int? steps = await health.getTotalStepsInInterval(midnight, now);
健康数据
HealthDataPoint 对象包含以下数据字段
HealthValue value; // NumericHealthValue, AudiogramHealthValue, WorkoutHealthValue
HealthDataType type;
HealthDataUnit unit;
DateTime dateFrom;
DateTime dateTo;
PlatformType platform;
String uuid, deviceId;
String sourceId;
String sourceName;
HealthData 对象可以使用 toJson() 方法序列化为 JSON。
获取健康数据
有关如何操作的展示,请参阅 pub.dev 上的示例。
注意:对于 iOS:请求健康数据之前必须解锁设备,否则将抛出错误。
flutter: Health Plugin Error:
flutter: PlatformException(FlutterHealth, Results are null, Optional(Error Domain=com.apple.healthkit Code=6 "Protected health data is inaccessible" UserInfo={NSLocalizedDescription=Protected health data is inaccessible}))
过滤重复项
如果多次请求相同数据并将其保存在同一个数组中,则会出现重复项。
单个数据点可以相互比较,使用 == 运算符,例如:
HealthDataPoint p1 = ...;
HealthDataPoint p2 = ...;
bool same = p1 == p2;
如果您有一个数据点列表,可以使用以下方法删除重复项:
List<HealthDataPoint> points = ...;
points = Health.removeDuplicates(points);
训练
从 4.0.0 开始,Health 支持向 iOS 和 Android 添加训练。
训练类型
| 训练类型 | iOS | Android | 注释 |
|---|---|---|---|
| ARCHERY | 是 | 是 | |
| BADMINTON | 是 | 是 | |
| BASEBALL | 是 | 是 | |
| BASKETBALL | 是 | 是 | |
| BIKING | 是 | 是 | 在 iOS 上是 CYCLING,但在此处更改了名称以匹配 Android。 |
| BOXING | 是 | 是 | |
| CRICKET | 是 | 是 | |
| CURLING | 是 | 是 | |
| ELLIPTICAL | 是 | 是 | |
| FENCING | 是 | 是 | |
| AMERICAN_FOOTBALL | 是 | 是 | |
| AUSTRALIAN_FOOTBALL | 是 | 是 | |
| SOCCER | 是 | 是 | |
| GOLF | 是 | 是 | |
| GYMNASTICS | 是 | 是 | |
| HANDBALL | 是 | 是 | |
| HIGH_INTENSITY_INTERVAL_TRAINING | 是 | 是 | |
| HIKING | 是 | 是 | |
| HOCKEY | 是 | 是 | |
| SKATING | 是 | 是 | 在 iOS 上是 skating_sports |
| JUMP_ROPE | 是 | 是 | |
| KICKBOXING | 是 | 是 | |
| MARTIAL_ARTS | 是 | 是 | |
| PILATES | 是 | 是 | |
| RACQUETBALL | 是 | 是 | |
| RUGBY | 是 | 是 | |
| RUNNING | 是 | 是 | |
| ROWING | 是 | 是 | |
| SAILING | 是 | 是 | |
| CROSS_COUNTRY_SKIING | 是 | 是 | |
| DOWNHILL_SKIING | 是 | 是 | |
| SNOWBOARDING | 是 | 是 | |
| SOFTBALL | 是 | 是 | |
| SQUASH | 是 | 是 | |
| STAIR_CLIMBING | 是 | 是 | |
| SWIMMING | 是 | 是 | |
| TABLE_TENNIS | 是 | 是 | |
| TENNIS | 是 | 是 | |
| VOLLEYBALL | 是 | 是 | |
| WALKING | 是 | 是 | |
| WATER_POLO | 是 | 是 | |
| YOGA | 是 | 是 | |
| BOWLING | 是 | ||
| CROSS_TRAINING | 是 | ||
| TRACK_AND_FIELD | 是 | ||
| DISC_SPORTS | 是 | ||
| LACROSSE | 是 | ||
| PREPARATION_AND_RECOVERY | 是 | ||
| FLEXIBILITY | 是 | ||
| COOLDOWN | 是 | ||
| WHEELCHAIR_WALK_PACE | 是 | ||
| WHEELCHAIR_RUN_PACE | 是 | ||
| HAND_CYCLING | 是 | ||
| CORE_TRAINING | 是 | ||
| FUNCTIONAL_STRENGTH_TRAINING | 是 | ||
| TRADITIONAL_STRENGTH_TRAINING | 是 | ||
| MIXED_CARDIO | 是 | ||
| STAIRS | 是 | ||
| STEP_TRAINING | 是 | ||
| FITNESS_GAMING | 是 | ||
| BARRE | 是 | ||
| CARDIO_DANCE | 是 | ||
| SOCIAL_DANCE | 是 | ||
| MIND_AND_BODY | 是 | ||
| PICKLEBALL | 是 | ||
| CLIMBING | 是 | ||
| EQUESTRIAN_SPORTS | 是 | ||
| FISHING | 是 | ||
| HUNTING | 是 | ||
| PLAY | 是 | ||
| SNOW_SPORTS | 是 | ||
| PADDLE_SPORTS | 是 | ||
| SURFING_SPORTS | 是 | ||
| WATER_FITNESS | 是 | ||
| WATER_SPORTS | 是 | ||
| TAI_CHI | 是 | ||
| WRESTLING | 是 | ||
| AEROBICS | 是 | ||
| BIATHLON | 是 | ||
| CALISTHENICS | 是 | ||
| CIRCUIT_TRAINING | 是 | ||
| CROSS_FIT | 是 | ||
| DANCING | 是 | ||
| DIVING | 是 | ||
| ELEVATOR | 是 | ||
| ERGOMETER | 是 | ||
| ESCALATOR | 是 | ||
| FRISBEE_DISC | 是 | ||
| GARDENING | 是 | ||
| GUIDED_BREATHING | 是 | ||
| HORSEBACK_RIDING | 是 | ||
| HOUSEWORK | 是 | ||
| INTERVAL_TRAINING | 是 | ||
| IN_VEHICLE | 是 | ||
| KAYAKING | 是 | ||
| KETTLEBELL_TRAINING | 是 | ||
| KICK_SCOOTER | 是 | ||
| KITE_SURFING | 是 | ||
| MEDITATION | 是 | ||
| MIXED_MARTIAL_ARTS | 是 | ||
| P90X | 是 | ||
| PARAGLIDING | 是 | ||
| POLO | 是 | ||
| ROCK_CLIMBING | (是) | 是 | 在 iOS 上将存储为 CLIMBING |
| RUNNING_JOGGING | (是) | 是 | 在 iOS 上将存储为 RUNNING |
| RUNNING_SAND | (是) | 是 | 在 iOS 上将存储为 RUNNING |
| RUNNING_TREADMILL | (是) | 是 | 在 iOS 上将存储为 RUNNING |
| SCUBA_DIVING | 是 | ||
| SKATING_CROSS | (是) | 是 | 在 iOS 上将存储为 SKATING |
| SKATING_INDOOR | (是) | 是 | 在 iOS 上将存储为 SKATING |
| SKATING_INLINE | (是) | 是 | 在 iOS 上将存储为 SKATING |
| SKIING_BACK_COUNTRY | 是 | ||
| SKIING_KITE | 是 | ||
| SKIING_ROLLER | 是 | ||
| SLEDDING | 是 | ||
| STAIR_CLIMBING_MACHINE | 是 | ||
| STANDUP_PADDLEBOARDING | 是 | ||
| STILL | 是 | ||
| STRENGTH_TRAINING | 是 | ||
| SURFING | 是 | ||
| SWIMMING_OPEN_WATER | 是 | ||
| SWIMMING_POOL | 是 | ||
| TEAM_SPORTS | 是 | ||
| TILTING | 是 | ||
| TREADMILL | 是 | ||
| VOLLEYBALL_BEACH | 是 | ||
| VOLLEYBALL_INDOOR | 是 | ||
| WAKEBOARDING | 是 | ||
| WALKING_FITNESS | 是 | ||
| WALKING_NORDIC | 是 | ||
| WALKING_STROLLER | 是 | ||
| WALKING_TREADMILL | 是 | ||
| WEIGHTLIFTING | 是 | ||
| WHEELCHAIR | 是 | ||
| WINDSURFING | 是 | ||
| ZUMBA | 是 | ||
| OTHER | 是 | 是 |