All Projects → VictorKachalov → health_kit_reporter

VictorKachalov / health_kit_reporter

Licence: MIT License
A Flutter wrapper for the HealthKitReporter library

Programming Languages

dart
5743 projects
swift
15916 projects
ruby
36898 projects - #4 most used programming language
objective c
16641 projects - #2 most used programming language

Projects that are alternatives of or similar to health kit reporter

HealthKitReporter
HealthKitReporter. A wrapper for HealthKit framework. Helps to write or read data from Apple Health via HealthKit framework.
Stars: ✭ 50 (+212.5%)
Mutual labels:  health, healthkit, apple-health
Heartcontrol
❤️ Continuous heart rate measurement during workouts with watchOS 3.
Stars: ✭ 170 (+962.5%)
Mutual labels:  apple, health
rn-fitness-tracker
React Native module to interact with Google Fit and Apple HealthKit.
Stars: ✭ 58 (+262.5%)
Mutual labels:  health, healthkit
ts4health
Time Series Data Analysis, Visualization and Forecasting with Python for Health and Self
Stars: ✭ 17 (+6.25%)
Mutual labels:  health, apple-health
Mining-Minds
Mining Minds is a collection of services, tools and techniques working collaboratively to investigate on human’s daily routines to provide a personalized well-being and health-care support
Stars: ✭ 43 (+168.75%)
Mutual labels:  health, healthkit
react-native-health
A React Native package to interact with Apple HealthKit
Stars: ✭ 348 (+2075%)
Mutual labels:  health, healthkit
health
A simple and flexible health check library for Go.
Stars: ✭ 494 (+2987.5%)
Mutual labels:  health
WacOS
A Linux distribution that mimics MacOS (modern and classic) iOS, and other Apple operating systems, but is open, customizable, and free to use on non-apple hardware.
Stars: ✭ 18 (+12.5%)
Mutual labels:  apple
decimation.github.io
Cydia repo
Stars: ✭ 18 (+12.5%)
Mutual labels:  apple
aceso
Python package to calculate 2SFCA and other measures of spatial accessibility
Stars: ✭ 20 (+25%)
Mutual labels:  health
sign-in-with-apple-js-node-example
Sign in with Apple using Apple JS and REST API
Stars: ✭ 48 (+200%)
Mutual labels:  apple
Thoughtless
An iOS app that lets user quickly jot down thoughts with Markdown support
Stars: ✭ 24 (+50%)
Mutual labels:  apple
homekit-qrcode
Generate a pairing HomeKit QR code label for your HomeKit accessory from the command line
Stars: ✭ 17 (+6.25%)
Mutual labels:  apple
Media
A beautiful and declarative cross-platform wrapper API for Apple's PhotoKit
Stars: ✭ 78 (+387.5%)
Mutual labels:  apple
react-native-imaged-carousel-card
Fully customizable & Lovely Imaged Carousel Card for React Native
Stars: ✭ 70 (+337.5%)
Mutual labels:  apple
Sensors
A macOS application displaying the thermal, voltage and current sensor values.
Stars: ✭ 70 (+337.5%)
Mutual labels:  apple
Clean-macOS
💻 A simple script to setup a clean environment on macOS
Stars: ✭ 155 (+868.75%)
Mutual labels:  apple
react-native-super-ellipse-mask
Apple flavored smooth corners for React Native
Stars: ✭ 55 (+243.75%)
Mutual labels:  apple
nestjs-redis
Redis(ioredis) module for NestJS framework
Stars: ✭ 112 (+600%)
Mutual labels:  health
aarogya seva
A beautiful 😍 covid-19 app with self - assessment and more.
Stars: ✭ 118 (+637.5%)
Mutual labels:  health

health_kit_reporter

Features

A Flutter wrapper for HealthKitReporter

  • iOS only usage, since AppleHealth is not available on Android devices.

  • The library supports reading, writing, observing values from HealthKit repository.

  • All methods from HealthKitReporter original library are wrapped in Method and Event channels provided by FlutterPlugin

Getting Started

  • Go inside pubspec.yaml file
  • Add this to your package's pubspec.yaml file:
dependencies:
     health_kit_reporter: ^1.5.2
  • Get dependencies
flutter pub get

How to use

Preparation

At first in your app's entitlements select HealthKit and in your app's info.plist file add permissions:

<key>NSHealthShareUsageDescription</key>
<string>WHY_YOU_NEED_TO_SHARE_DATA</string>
<key>NSHealthUpdateUsageDescription</key>
<string>WHY_YOU_NEED_TO_USE_DATA</string>

If you plan to use WorkoutRoute Series please provide additionally CoreLocation permissions:

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>WHY_YOU_NEED_TO_ALWAYS_SHARE_LOCATION</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>WHY_YOU_NEED_TO_SHARE_LOCATION</string>

Common usage

You simply call a HealthKitReporter methods surrounding by try catch blocks.

Warning: If Apple Health is not supported by the device (i.e. iPad) the error result will occur.

The reporter supports following operations with HealthKit:

  • accessing to permissions
  • reading data
  • writing data
  • observing data changes

If you want to read, write data or observe data changes, you always need to be sure that the data types are authorized to be read/written/observed. In that case call authorization method and await for the result telling about the presentation of the authorization window. Notice that Apple Health Kit will show this window only once during the whole time app is installed on the device, in this case if some types were denied to be read or written, user should manually allow this in Apple Health App.

Requesting permissions

As was mentioned above, you need to provide HealthKit entitlements and extend the info.plist file of your App with HealthKit permissions. (see Preparation)

Call the method: requestAuthorization

For this method you need to specify the strings identifiers of types you want to get access.

In the example, we want to read data for all QuantityTypes and write data for QuantityType.stepCount:

  void requestAuthorization() async {
    try {
      final readTypes = <String>[];
      readTypes.addAll(QuantityType.values.map((e) => e.identifier));
      final writeTypes = <String>[
        QuantityType.stepCount.identifier,
      ];
      final isRequested =
          await HealthKitReporter.requestAuthorization(readTypes, writeTypes);
      if (isRequested) {
        // read data/write data/observe data
      }
    } catch (e) {
      print(e);
    }
  }

Warning: Please keep in mind, Apple Health Kit does not let anyone to know if reading permissions were provided.

User can decline some of the reading permissions, but the result of the function will still be true. See Authorization status

Reading Data

After authorization, you can try to start reading data.

void read(bool isRequested) async {
    if (isRequested) {
      final preferredUnits =
      await HealthKitReporter.preferredUnits([QuantityType.stepCount]);
      preferredUnits.forEach((preferredUnit) async {
        print('preferredUnit: ${preferredUnit.identifier}');
        final type = QuantityTypeFactory.from(preferredUnit.identifier);
        final quantities = await HealthKitReporter.quantityQuery(
            type, preferredUnit, _predicate);
        print('quantity: ${quantities.map((e) => e.map).toList()}');
        final statistics = await HealthKitReporter.statisticsQuery(
            type, preferredUnit, _predicate);
        print('statistics: ${statistics.map}');
      });
      final characteristics = await HealthKitReporter.characteristicsQuery();
      print('characteristics: ${characteristics.map}');
      final categories = await HealthKitReporter.categoryQuery(
          CategoryType.sleepAnalysis, _predicate);
      print('categories: ${categories.map((e) => e.map).toList()}');
      final samples = await HealthKitReporter.sampleQuery(
          QuantityType.stepCount.identifier, _predicate);
      print('samples: ${samples.map((e) => e.map).toList()}');
      final sources = await HealthKitReporter.sourceQuery(
          QuantityType.stepCount.identifier, _predicate);
      print('sources: ${sources.map((e) => e.map).toList()}');
      final correlations = await HealthKitReporter.correlationQuery(
          CorrelationType.bloodPressure.identifier, _predicate);
      print('correlations: ${correlations.map((e) => e.map).toList()}');
    } else {
      print('error isRequested: $isRequested');
    }
  }

In the example above, there is a call of preferredUnits function. You can provide identifiers to get preferred units for them and eventually receive properly calculated values from queries. The units will be chosen automatically based on you current localization. This is only required for QuantityTypes. If you will try to provide invalid unit for a type, you will get an error.

The usage of sampleQuery for quantity types will return nearly the same result as quantityQuery, but the units for the values will be used according to SI, while quantityQuery together with preferredUnits will handle values units according to thee current localization.

Writing Data

Before writing data, you may need to check if writing is allowed by calling isAuthorizedToWrite.

If it is ok to write, you need to create a Sample object and call a save method.

final _device = Device(
    'FlutterTracker',
    'kvs',
    'T-800',
    '3',
    '3.0',
    '1.1.1',
    'kvs.sample.app',
    '444-888-555',
  );
final _source = Source(
    'myApp',
    'com.kvs.health_kit_reporter_example',
  );
final _operatingSystem = OperatingSystem(
    1,
    2,
    3,
  );

SourceRevision get _sourceRevision => SourceRevision(
    _source,
   '5',
   'fit',
   '4',
   _operatingSystem,
  );

void saveSteps() async {
  try {
    final canWrite = await HealthKitReporter.isAuthorizedToWrite(
        QuantityType.stepCount.identifier);
    if (canWrite) {
      final now = DateTime.now();
      final minuteAgo = now.add(Duration(minutes: -1));
      final harmonized = QuantityHarmonized(100, 'count', null);
      final steps = Quantity(
          'testStepsUUID',
          QuantityType.stepCount.identifier,
          minuteAgo.millisecondsSinceEpoch,
          now.millisecondsSinceEpoch,
          _device,
          _sourceRevision,
          harmonized);
      print('try to save: ${steps.map}');
      final saved = await HealthKitReporter.save(steps);
      print('stepsSaved: $saved');
    } else {
      print('error canWrite steps: $canWrite');
    }
  } catch (e) {
    print(e);
  }
}

Recommendation: As well as for reading, here will better as well to call preferredUnits first, to know what unit is valid for a type. Please see HKUnit.init

Warning: PLease be sure to provide valid values for the appropriate types. For example, HealthKit will not allow to save Quantity value for the QuantityType.stepCount if the value is 0

Observing Data

If you want to know, that something was changed in HealthKit, you can observe the repository.

Try simple observerQuery to get notifications if something is changed.

This call is a subscription for EventChannel of the plugin, so don't forget to cancel it as soon as you don't need it anymore.

  void observerQuery() async {
    final identifier = QuantityType.stepCount.identifier;
    final sub = HealthKitReporter.observerQuery(identifier, _predicate,
        onUpdate: (identifier) async {
      print('Updates for observerQuerySub');
      print(identifier);
    });
    print('observerQuerySub: $sub');
    final isSet = await HealthKitReporter.enableBackgroundDelivery(
        identifier, UpdateFrequency.immediate);
    print('enableBackgroundDelivery: $isSet');
  }

According to Observing Query and Background Delivery you might create an App which will be called every time by HealthKit, even if the app is in background, to notify, that some data was changed in HealthKit depending on frequency. But keep in mind that sometimes the desired frequency you set cannot be fulfilled by HealthKit.

To receive notifications when the app is killed by the system or in background:

  • provide an additional capability Background Mode and select Background fetch
  • with calling observerQuery, you need to call enableBackgroundDelivery function as well

As a recommendation set up the subscription inside initState or build methods of your widget or as more preferred in main function of your app.

If you want to stop observation, you need to:

  • remove the subscription for observerQuery
  • call disableBackgroundDelivery or disableAllBackgroundDelivery

Requirements

The library supports minimum iOS 9. Some features like HeartbeatSeries are available only starting with iOS 13.0 and like Electrocardiogramm starting with iOS 14.0.

License

Under MIT License

Sponsorhip

If you think that my repo helped you to solve the issues you struggle with, please don't be shy and sponsor :-)

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].