Flutter健康监测插件healthy_ios的使用
Flutter健康监测插件healthy_ios的使用
介绍
healthy_ios
是一个小型封装库,用于在 HealthKit 上进行样本和统计查询。它受到 CACHET 的 health
库的启发。
使用方法
- 在
pubspec.yaml
中添加healthy_ios
。 - 在
plist.info
文件中添加以下条目:
<key>NSHealthShareUsageDescription</key>
<string>请说明你需要这个权限的原因。</string>
<key>NSHealthUpdateUsageDescription</key>
<string>请说明你需要这个权限的原因。</string>
- 在 Xcode 中打开你的项目,并将 “HealthKit” 添加为功能。
设置完成后的操作
现在你可以实例化一个 HealthStore
对象:
final store = HealthStore();
在查询数据之前,请确保通过调用以下方法请求用户的权限:
final stepType = HKQuantityType.StepCount.identifier();
final permissionsGranted = await store.requestTypes([stepType]);
现在你可以查询样本。如果你查询的是数量类型,需要提供类型和单位的元组。这里有一个扩展函数可以使用:
final now = DateTime.now();
final samples = await store.getHealthSamplesForQuantityType(
start: now.subtract(Duration(days: 2)), // 查询过去两天的数据
end: now,
types: [
// 手动构造元组
HKQuantityTypeUnitTuple(HKQuantityType.StepCount, 'count'),
// 使用扩展函数
HKQuantityType.HeartRate.withUnit('count/min'),
]);
如果你查询的是类别类型,则不需要传递单位,因此结果值属性包含子类型的枚举值。
获取统计数据也很容易。你还需要传递一个间隔时间(用于累积统计数据)和一个锚定日期(用于确定间隔的起始点)。目前,StatisticsInterval
只能处理天、小时和分钟间隔。
final now = DateTime.now();
final start = DateTime(now.year, now.month, now.day, 0, 0);
final samples = await store.getHealthStatisticsForType(
start: start,
end: now,
interval: StatisticsInterval(hour: 1), // 每小时间隔
anchor: start,
types: [
HKQuantityType.StepCount.withUnit('count'),
]);
生成的统计数据对象有四个值字段(sum, avg, min, max)。如果 HKQuantityType
是累计类型,只有 sum 字段会有值。如果是离散类型,avg, min 和 max 字段都会有值。
额外信息
- 关于有效单位,请参阅相关文档。
支持的数据类型
定量类型:
- ActiveEnergyBurned
- BasalEnergyBurned
- BloodGlucose
- OxygenSaturation
- BloodPressureDiastolic
- BloodPressureSystolic
- BodyFatPercentage
- BodyMassIndex
- BodyTemperature
- HeartRate
- Height
- RestingHeartRate
- StepCount
- WaistCircumference
- WalkingHeartRateAverage
- BodyMass
- FlightsClimbed
- DistanceWalkingRunning
- DietaryWater
- HeartRateVariabilitySDNN
- EnvironmentalAudioExposure
- HeadphoneAudioExposure
类别类型:
- MindfulSession
- SleepAnalysis
完整示例 Demo
import 'package:flutter/material.dart';
import 'package:healthy_ios/healthy_ios.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var isLoading = false;
var _result = '';
final store = HealthStore();
[@override](/user/override)
void initState() {
super.initState();
}
// 获取分类样本
void _fetchCategoricalSamples() async {
final types = [HKCategoryType.SleepAnalysis, HKCategoryType.MindfulSession];
final granted = await store.requestTypes(types.map((e) => e.identifier));
setState(() {
isLoading = true;
});
try {
if (granted) {
final now = DateTime.now();
final samples = await store.getHealthSamplesForCategroyType(
start: now.subtract(Duration(days: 5)), end: now, types: types);
setState(() {
_result = samples.map((e) => e.toString()).join('\n');
});
}
} on HealthyException catch (e) {
setState(() {
_result = e.code;
});
} finally {
setState(() {
isLoading = false;
});
}
}
// 获取数量样本
void _fetchQuantitySamples() async {
final types = [HKQuantityType.StepCount, HKQuantityType.ActiveEnergyBurned]
.map((e) => e.identifier);
final granted = await store.requestTypes(types);
setState(() {
isLoading = true;
});
try {
if (granted) {
final now = DateTime.now();
final samples = await store.getHealthSamplesForQuantityType(
start: now.subtract(Duration(days: 2)),
end: now,
types: [
HKQuantityTypeUnitTuple(HKQuantityType.StepCount, 'count'),
]);
setState(() {
_result = samples.map((e) => e.toString()).join('\n');
});
}
} on HealthyException catch (e) {
setState(() {
_result = e.code;
});
} finally {
setState(() {
isLoading = false;
});
}
}
// 获取统计数据
void _fetchStatisticalData() async {
final types = [HKQuantityType.StepCount, HKQuantityType.HeartRate]
.map((e) => e.identifier);
final granted = await store.requestTypes(types);
setState(() {
isLoading = true;
});
try {
if (granted) {
final now = DateTime.now();
final start = DateTime(now.year, now.month, now.day, 0, 0);
final samples = await store.getHealthStatisticsForType(
start: start,
end: now,
interval: StatisticsInterval(hour: 1),
anchor: start,
types: [
HKQuantityType.StepCount.withUnit('count'),
HKQuantityType.HeartRate.withUnit('count/min'),
],
);
setState(() {
_result = samples.map((e) => e.toString()).join('\n');
});
}
} on HealthyException catch (e) {
setState(() {
_result = e.code;
});
} finally {
setState(() {
isLoading = false;
});
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('插件示例应用'),
),
body: isLoading
? const CircularProgressIndicator()
: Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: _fetchQuantitySamples,
child: Text('样本')),
ElevatedButton(
onPressed: _fetchCategoricalSamples,
child: Text('分类')),
ElevatedButton(
onPressed: _fetchStatisticalData,
child: Text('统计')),
],
),
Text(_result),
],
)),
),
),
);
}
}
更多关于Flutter健康监测插件healthy_ios的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter健康监测插件healthy_ios的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中集成并使用healthy_ios
插件来进行健康监测的一个基本示例。请注意,healthy_ios
是一个特定于iOS的插件,因此在Android上不可用。此外,由于我无法实时验证插件的API或安装过程,以下代码基于插件的一般使用方法和假设的API设计。
首先,确保你已经在pubspec.yaml
文件中添加了healthy_ios
依赖:
dependencies:
flutter:
sdk: flutter
healthy_ios: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目的iOS部分(通常是通过Xcode打开的Runner项目),你需要确保你的应用有权限访问健康数据。这需要在Info.plist
文件中添加相应的权限请求。例如:
<key>NSHealthShareUsageDescription</key>
<string>我们需要访问您的健康数据来提供更好的健康监测服务。</string>
<key>NSHealthUpdateUsageDescription</key>
<string>我们需要更新您的健康数据以提供最新的健康监测结果。</string>
现在,让我们编写一些Flutter代码来使用healthy_ios
插件。由于healthy_ios
可能是一个假设的插件名,我将提供一个基于类似插件可能提供的API的示例代码。请根据你实际使用的插件文档进行调整。
import 'package:flutter/material.dart';
import 'package:healthy_ios/healthy_ios.dart'; // 假设这是插件的导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String healthData = "No Data Yet";
@override
void initState() {
super.initState();
_requestHealthData();
}
Future<void> _requestHealthData() async {
// 检查平台是否为iOS,因为healthy_ios是iOS特定的
if (Platform.isIOS) {
HealthyIos healthyIos = HealthyIos();
try {
// 假设插件有一个方法来请求步数数据
var stepsData = await healthyIos.requestSteps();
setState(() {
healthData = "Steps: ${stepsData.stepsCount}";
});
} catch (e) {
print("Error requesting health data: $e");
setState(() {
healthData = "Error fetching health data";
});
}
} else {
setState(() {
healthData = "This feature is only available on iOS.";
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Healthy iOS Plugin Demo'),
),
body: Center(
child: Text(healthData),
),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,它尝试在iOS上请求健康数据(如步数)。请注意,HealthyIos
类和requestSteps
方法都是假设的,你需要根据你实际使用的插件的API进行调整。
由于healthy_ios
可能不是一个真实存在的Flutter插件,我强烈建议你查阅官方文档或GitHub仓库以获取准确的API信息和集成指南。如果你发现healthy_ios
确实存在但API与上述示例不同,请相应地调整代码。