Flutter健康数据访问插件health_ios12的使用
Flutter健康数据访问插件health_ios12的使用
Health 插件简介
Health
插件允许从 Apple Health、Google Fit 和 Health Connect 读取和写入健康数据。
注意:Google Fitness API 正在被弃用,该插件将逐步过渡到 Health Connect API。
插件支持的功能:
- 权限管理:通过
hasPermissions
、requestAuthorization
和revokePermissions
方法处理权限。 - 读取健康数据:使用
getHealthDataFromTypes
方法读取健康数据。 - 写入健康数据:使用
writeHealthData
方法写入健康数据。 - 写入运动数据:使用
writeWorkout
方法写入运动数据。 - 写入音频图:在 iOS 上使用
writeAudiogram
方法写入音频图。 - 写入血压数据:使用
writeBloodPressure
方法写入血压数据。 - 获取总步数:使用
getTotalStepsInInterval
方法获取步数。 - 清理重复数据点:使用
removeDuplicates
方法清理重复数据。 - 删除指定类型的数据:使用
delete
方法删除指定时间段内的数据。 - 支持未来的 Android API Health Connect。
注意:对于 Android 用户,目标设备需要安装 Google Fit 或 Health Connect(目前处于测试阶段),并且需要互联网连接,否则该插件无法正常工作。
数据类型
以下为支持的数据类型及其单位:
数据类型 | 单位 | iOS | Android (Google Fit) | Android (Health Connect) | 备注 |
---|---|---|---|---|---|
ACTIVE_ENERGY_BURNED | CALORIES | 是 | 是 | 是 | |
BASAL_ENERGY_BURNED | CALORIES | 是 | 否 | 否 | |
BLOOD_GLUCOSE | MILLIGRAM_PER_DECILITER | 是 | 是 | 是 | |
BLOOD_OXYGEN | PERCENTAGE | 是 | 是 | 是 | |
BLOOD_PRESSURE_DIASTOLIC | MILLIMETER_OF_MERCURY | 是 | 是 | 是 | |
BLOOD_PRESSURE_SYSTOLIC | MILLIMETER_OF_MERCURY | 是 | 是 | 是 | |
BODY_FAT_PERCENTAGE | PERCENTAGE | 是 | 是 | 是 | |
BODY_MASS_INDEX | NO_UNIT | 是 | 是 | 是 | |
BODY_TEMPERATURE | DEGREE_CELSIUS | 是 | 是 | 是 |
…
安装与配置
Apple Health (iOS)
第一步:修改 Info.plist
添加以下两个条目以描述健康数据用途:
<key>NSHealthShareUsageDescription</key>
<string>我们需要同步您的数据到 Apple Health 应用以提供更好的洞察。</string>
<key>NSHealthUpdateUsageDescription</key>
<string>我们需要同步您的数据到 Apple Health 应用以提供更好的洞察。</string>
第二步:启用 HealthKit
在 Xcode 中打开项目,并在 Runner
的设置中启用 HealthKit 能力。
Google Fit (Android 选项 1)
按照以下步骤生成 OAuth2 客户端 ID 并添加 SHA1 指纹:
-
在终端进入密钥库目录:
cd ~/.android/
-
获取密钥库的 SHA1 指纹:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
-
将 SHA1 指纹添加到 OAuth2 凭据中,并生成客户端 ID,例如:
YOUR_CLIENT_ID.apps.googleusercontent.com
Health Connect (Android 选项 2)
在 AndroidManifest.xml
中添加以下内容:
<queries>
<package android:name="com.google.android.apps.healthdata" />
</queries>
Android 权限
从 Android 9.0 开始,访问某些健身数据(如步数)需要特殊权限。在 AndroidManifest.xml
中添加以下行:
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
对于 Health Connect,还需添加以下权限:
<uses-permission android:name="android.permission.health.READ_HEART_RATE"/>
<uses-permission android:name="android.permission.health.WRITE_HEART_RATE"/>
此外,如果请求运动距离,则需要位置权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
使用 permission_handler
插件提示用户授予这些权限:
await Permission.activityRecognition.request();
await Permission.location.request();
使用示例
以下是一个完整的示例代码,展示如何使用 health_ios12
插件访问健康数据。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:health_ios12/health.dart';
import 'package:health_example/util.dart';
import 'package:permission_handler/permission_handler.dart';
void main() => runApp(HealthApp());
class HealthApp extends StatefulWidget {
[@override](/user/override)
_HealthAppState createState() => _HealthAppState();
}
enum AppState {
DATA_NOT_FETCHED,
FETCHING_DATA,
DATA_READY,
NO_DATA,
AUTHORIZED,
AUTH_NOT_GRANTED,
DATA_ADDED,
DATA_DELETED,
DATA_NOT_ADDED,
DATA_NOT_DELETED,
STEPS_READY,
}
class _HealthAppState extends State<HealthApp> {
List<HealthDataPoint> _healthDataList = [];
AppState _state = AppState.DATA_NOT_FETCHED;
int _nofSteps = 0;
// 定义要获取的数据类型
static final types = dataTypesAndroid;
final permissions = types.map((e) => HealthDataAccess.READ_WRITE).toList();
HealthFactory health = HealthFactory(useHealthConnectIfAvailable: true);
Future authorize() async {
await Permission.activityRecognition.request();
await Permission.location.request();
bool authorized = false;
try {
authorized = await health.requestAuthorization(types, permissions: permissions);
} catch (error) {
print("授权异常: $error");
}
setState(() => _state = authorized ? AppState.AUTHORIZED : AppState.AUTH_NOT_GRANTED);
}
Future fetchData() async {
setState(() => _state = AppState.FETCHING_DATA);
final now = DateTime.now();
final yesterday = now.subtract(Duration(hours: 24));
_healthDataList.clear();
try {
List<HealthDataPoint> healthData = await health.getHealthDataFromTypes(yesterday, now, types);
_healthDataList.addAll(HealthFactory.removeDuplicates(healthData));
} catch (error) {
print("获取数据异常: $error");
}
setState(() {
_state = _healthDataList.isEmpty ? AppState.NO_DATA : AppState.DATA_READY;
});
}
Future addData() async {
bool success = true;
final now = DateTime.now();
final earlier = now.subtract(Duration(minutes: 20));
success &= await health.writeHealthData(10, HealthDataType.BODY_FAT_PERCENTAGE, earlier, now);
success &= await health.writeHealthData(1.925, HealthDataType.HEIGHT, earlier, now);
success &= await health.writeHealthData(90, HealthDataType.WEIGHT, earlier, now);
success &= await health.writeHealthData(90, HealthDataType.HEART_RATE, earlier, now);
success &= await health.writeHealthData(90, HealthDataType.STEPS, earlier, now);
success &= await health.writeHealthData(200, HealthDataType.ACTIVE_ENERGY_BURNED, earlier, now);
success &= await health.writeHealthData(70, HealthDataType.HEART_RATE, earlier, now);
success &= await health.writeHealthData(37, HealthDataType.BODY_TEMPERATURE, earlier, now);
success &= await health.writeBloodOxygen(98, earlier, now, flowRate: 1.0);
success &= await health.writeHealthData(105, HealthDataType.BLOOD_GLUCOSE, earlier, now);
success &= await health.writeHealthData(1.8, HealthDataType.WATER, earlier, now);
success &= await health.writeWorkoutData(
HealthWorkoutActivityType.AMERICAN_FOOTBALL, earlier, now,
totalDistance: 2430, totalEnergyBurned: 400);
success &= await health.writeBloodPressure(90, 80, earlier, now);
setState(() {
_state = success ? AppState.DATA_ADDED : AppState.DATA_NOT_ADDED;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Health Example')),
body: Column(
children: [
ElevatedButton(onPressed: authorize, child: Text('授权')),
ElevatedButton(onPressed: fetchData, child: Text('获取数据')),
ElevatedButton(onPressed: addData, child: Text('添加数据')),
Text('当前状态: $_state'),
],
),
),
);
}
}
更多关于Flutter健康数据访问插件health_ios12的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter健康数据访问插件health_ios12的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
health_ios12
是一个用于在 Flutter 应用中访问 iOS 设备上健康数据的插件。它主要用于读取和写入与健康相关的数据,如步数、心率、睡眠等。以下是如何使用 health_ios12
插件的基本步骤:
1. 添加依赖
首先,在 pubspec.yaml
文件中添加 health_ios12
插件的依赖:
dependencies:
flutter:
sdk: flutter
health_ios12: ^2.0.0 # 请使用最新版本
然后运行 flutter pub get
以获取依赖。
2. 配置 iOS 项目
在 iOS 项目中,你需要在 Info.plist
文件中添加健康数据访问的权限描述:
<key>NSHealthShareUsageDescription</key>
<string>我们需要访问您的健康数据以提供更好的服务。</string>
<key>NSHealthUpdateUsageDescription</key>
<string>我们需要更新您的健康数据以提供更好的服务。</string>
3. 初始化插件
在你的 Dart 代码中,首先导入 health_ios12
插件:
import 'package:health_ios12/health_ios12.dart';
然后创建一个 HealthFactory
实例:
HealthFactory health = HealthFactory();
4. 请求权限
在访问健康数据之前,你需要请求用户的权限。你可以使用 requestAuthorization
方法请求访问特定类型的健康数据:
List<HealthDataType> types = [
HealthDataType.STEPS,
HealthDataType.HEART_RATE,
HealthDataType.SLEEP_IN_BED,
];
bool requested = await health.requestAuthorization(types);
if (requested) {
print("权限请求成功");
} else {
print("权限请求失败");
}
5. 读取健康数据
你可以使用 getHealthDataFromTypes
方法读取特定时间范围内的健康数据:
DateTime now = DateTime.now();
DateTime startDate = DateTime(now.year, now.month, now.day - 7); // 一周前
DateTime endDate = now;
List<HealthDataPoint> healthData = await health.getHealthDataFromTypes(startDate, endDate, types);
for (var dataPoint in healthData) {
print("类型: ${dataPoint.type}, 值: ${dataPoint.value}, 时间: ${dataPoint.dateFrom}");
}
6. 写入健康数据
你也可以使用 writeHealthData
方法写入健康数据:
bool success = await health.writeHealthData(HealthDataType.STEPS, 1000, DateTime.now());
if (success) {
print("数据写入成功");
} else {
print("数据写入失败");
}
7. 处理错误
在实际应用中,你应该处理可能出现的错误,例如用户拒绝权限或设备不支持健康数据访问:
try {
List<HealthDataPoint> healthData = await health.getHealthDataFromTypes(startDate, endDate, types);
for (var dataPoint in healthData) {
print("类型: ${dataPoint.type}, 值: ${dataPoint.value}, 时间: ${dataPoint.dateFrom}");
}
} catch (e) {
print("获取健康数据时出错: $e");
}