All Projects → VictorKachalov → HealthKitReporter

VictorKachalov / HealthKitReporter

Licence: MIT license
HealthKitReporter. A wrapper for HealthKit framework. Helps to write or read data from Apple Health via HealthKit framework.

Programming Languages

swift
15916 projects
ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to HealthKitReporter

health kit reporter
A Flutter wrapper for the HealthKitReporter library
Stars: ✭ 16 (-68%)
Mutual labels:  health, healthkit, apple-health
react-native-health
A React Native package to interact with Apple HealthKit
Stars: ✭ 348 (+596%)
Mutual labels:  health, healthkit
rn-fitness-tracker
React Native module to interact with Google Fit and Apple HealthKit.
Stars: ✭ 58 (+16%)
Mutual labels:  health, healthkit
ts4health
Time Series Data Analysis, Visualization and Forecasting with Python for Health and Self
Stars: ✭ 17 (-66%)
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 (-14%)
Mutual labels:  health, healthkit
Daily Dozen Android
Keep track of the foods that Dr. Greger recommends in his NYT's best-selling book, How Not to Die with this Android app
Stars: ✭ 200 (+300%)
Mutual labels:  health
hi-ml
HI-ML toolbox for deep learning for medical imaging and Azure integration
Stars: ✭ 150 (+200%)
Mutual labels:  health
Carekit
CareKit is an open source software framework for creating apps that help people better understand and manage their health.
Stars: ✭ 2,142 (+4184%)
Mutual labels:  health
Datasets For Good
List of datasets to apply stats/machine learning/technology to the world of social good.
Stars: ✭ 174 (+248%)
Mutual labels:  health
cht-conf
A command-line interface for configuring Community Health Toolkit applications
Stars: ✭ 20 (-60%)
Mutual labels:  health
DiseaseClassifier
Using a Naive Bayes Classifier gets possible diseases from symptoms
Stars: ✭ 23 (-54%)
Mutual labels:  health
21 Points
❤️ 21-Points Health is an app you can use to monitor your health.
Stars: ✭ 244 (+388%)
Mutual labels:  health
Home
🏡 👩‍💻 💡 home is where you can [learn to] build the future surrounded by like-minded creative, friendly and [intrinsically] motivated people focussed on health, fitness and making things people and the world need!
Stars: ✭ 209 (+318%)
Mutual labels:  health
EyesGuard
👀 Windows Application for protecting your eyes
Stars: ✭ 217 (+334%)
Mutual labels:  health
Fast Ide
🕺Fast Integrated Development Environment 😻
Stars: ✭ 181 (+262%)
Mutual labels:  health
bulario
Biblioteca para auxiliar nas pesquisas de bulas da ANVISA
Stars: ✭ 20 (-60%)
Mutual labels:  health
Calendula
An Android assistant for personal medication management
Stars: ✭ 174 (+248%)
Mutual labels:  health
Corona Tracker
An easy-to-use PWA to monitor the user's wellness and learn about COVID-19.
Stars: ✭ 240 (+380%)
Mutual labels:  health
healthi-app
Simple app to check your laptop's battery health.
Stars: ✭ 47 (-6%)
Mutual labels:  health
Projecteye
😎 一个基于20-20-20规则的用眼休息提醒Windows软件
Stars: ✭ 234 (+368%)
Mutual labels:  health

HealthKitReporter

About

A wrapper above HealthKit Apple's framework for data manipulations. The library supports manipulating with values from HealthKit repository and translating them to Codable models allowing to encode the result as a simple JSON payload. In addition you can write your own HealthKit objects using Codable wrappers which will be translated to HKObjectType objects inside HealthKit repository.

Start

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 create a HealthKitReporter instance surrounded by do catch block. If Apple Health is not supported by the device (i.e. iPad) the catch block will be called.

The reporter instance contains several properties:

  • reader
  • writer
  • manager
  • observer

Every property is responsible for an appropriate part of HealthKit framework. Based from the naming, reader will handle every manipulation regarding reading data and writer will handle everything related to writing data in HealthKit repository, observer will handle observations and will notify if anything was changes in HealthKit, manager is responsible for the authorization of read/write types and launching a WatchApp you make.

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 manager has authorization method with completion block 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.

In examples below every operation is hapenning iside authorization block. It is recommended to do so, because if new type will be added, there will be thrown a permission exception. If you are sure that no new types will appear, you can call operations outside authorization block in your app, only if the type's data reading/writing permissions were granted.

Reading Data

Create a HealthKitReporter instance.

Authorize deisred types to read, like step count.

If authorization was successfull (the authorization window was shown) call sample query with type step count to create a Query object.

Use reporter's manager's executeQuery to execute the query. (Or stopQuery to stop)

do {
    let reporter = try HealthKitReporter()
    let types = [QuantityType.stepCount]
    reporter.manager.requestAuthorization(
        toRead: types,
        toWrite: types
    ) { (success, error) in
        if success && error == nil {
            reporter.manager.preferredUnits(for: types) { (preferredUnits, error) in
                if error == nil {
                    for preferredUnit in preferredUnits {
                        do {
                            let query = try reporter.reader.quantityQuery(
                                type: try QuantityType.make(from: preferredUnit.identifier),
                                unit: preferredUnit.unit
                            ) { (results, error) in
                                if error == nil {
                                    for element in results {
                                        do {
                                            print(try element.encoded())
                                        } catch {
                                            print(error)
                                        }
                                    }
                                } else {
                                    print(error)
                                }
                            }
                            reporter.manager.executeQuery(query)
                        } catch {
                            print(error)
                        }
                    }
                } else {
                    print(error)
                }
            }
        } else {
            print(error)
        }
    }
} catch {
    print(error)
}

Here is a sample response for steps:

{
  "sourceRevision" : {
    "productType" : "iPhone8,1",
    "systemVersion" : "14.0.0",
    "source" : {
      "name" : "Guy’s iPhone",
      "bundleIdentifier" : "com.apple.health.47609E07-490D-4E5F-8E68-9D8904E9BA08"
    },
    "version" : "14.0"
  },
  "harmonized" : {
    "value" : 298,
    "unit" : "count"
  },
  "device" : {
    "softwareVersion" : "14.0",
    "manufacturer" : "Apple Inc.",
    "model" : "iPhone",
    "name" : "iPhone",
    "hardwareVersion" : "iPhone8,1"
  },
  "endTimestamp" : 1601066077.5886581,
  "identifier" : "HKQuantityTypeIdentifierStepCount",
  "startTimestamp" : 1601065755.8829093
}

Writing Data

Create a HealthKitReporter instance.

Authorize deisred types to write, like step count.

You may call manager's preferredUnits(for: ) function to pass units (for Quantity Types).

If authorization was successfull (the authorization window was shown) call save method with type step count.

do {
    let reporter = try HealthKitReporter()
    let types = [QuantityType.stepCount]
    reporter.manager.requestAuthorization(
        toRead: types,
        toWrite: types
    ) { (success, error) in
        if success && error == nil {
            reporter.manager.preferredUnits(for: types) { (preferredUnits, error) in
                for preferredUnit in preferredUnits {
                    //Do write steps
                    let identifier = preferredUnit.identifier
                    guard
                        identifier == QuantityType.stepCount.identifier
                    else {
                        return
                    }
                    let now = Date()
                    let quantity = Quantity(
                        identifier: identifier,
                        startTimestamp: now.addingTimeInterval(-60).timeIntervalSince1970,
                        endTimestamp: now.timeIntervalSince1970,
                        device: Device(
                            name: "Guy's iPhone",
                            manufacturer: "Guy",
                            model: "6.1.1",
                            hardwareVersion: "some_0",
                            firmwareVersion: "some_1",
                            softwareVersion: "some_2",
                            localIdentifier: "some_3",
                            udiDeviceIdentifier: "some_4"
                        ),
                        sourceRevision: SourceRevision(
                            source: Source(
                                name: "mySource",
                                bundleIdentifier: "com.kvs.hkreporter"
                            ),
                            version: "1.0.0",
                            productType: "CocoaPod",
                            systemVersion: "1.0.0.0",
                            operatingSystem: SourceRevision.OperatingSystem(
                                majorVersion: 1,
                                minorVersion: 1,
                                patchVersion: 1
                            )
                        ),
                        harmonized: Quantity.Harmonized(
                            value: 123.0,
                            unit: preferredUnit.unit,
                            metadata: nil
                        )
                    )
                    reporter.writer.save(sample: quantity) { (success, error) in
                        if success && error == nil {
                            print("success")
                        } else {
                            print(error)
                        }
                    }
                }
            }
        } else {
            print(error)
        }
    }
} catch {
    print(error)
}

Hint: if you have trouble with choosing unit for an object you want to save, you can call a manager's function preferredUnits which will return a dictionary with keys as identifiers of Quantitiy types and Units preferred for current localization.

reporter.manager.preferredUnits(for: [.stepCount]) { (dictionary, error) in
    for (identifier, unit) in dictionary {
        print("\(identifier) - \(unit)")
    }
}

Observing Data

Create a HealthKitReporter instance.

Authorize deisred types to read/write, like step count and sleep analysis.

You might create an App which will be called every time by HealthKit, and receive notifications, 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.

Call the observation query method inside your AppDelegate's method. This will let Apple Health to send events even if the app is in background or wake up your app, if it was previosly put into "Not Running" state and execute the code provided inside observerQuery update handler.

Warning: to run observerQuery when the app is killed by the system, provide an additional capability Background Mode and select Background fetch

Use reporter's manager's executeQuery to execute the query. (Or stopQuery to stop)

func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    do {
        let reporter = try HealthKitReporter()
        let types: [SampleType] = [
            QuantityType.stepCount,
            CategoryType.sleepAnalysis
        ]
        reporter.manager.requestAuthorization(
            toRead: types,
            toWrite: types
        ) { (success, error) in
            if success && error == nil {
                for type in types {
                    do {
                        let query = try reporter.observer.observerQuery(
                            type: type
                        ) { (query, identifier, error) in
                            if error == nil && identifier != nil {
                                print("updates for \(identifier!)")
                            }
                        }
                        reporter.observer.enableBackgroundDelivery(
                            type: type,
                            frequency: .daily
                        ) { (success, error) in
                            if error == nil {
                                print("enabled")
                            }
                        }
                        reporter.manager.executeQuery(query)
                    } catch {
                        print(error)
                    }
                }
            }
        }
    } catch {
        print(error)
    }
    return true
}

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

The library supports iOS 9 & above. Some features like HKHeartbeatSeries are available only starting with iOS 13.0 and like HKElectrocardiogramm starting with iOS 14.0

Installation

Cocoapods

HealthKitReporter is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'HealthKitReporter'

or

pod 'HealthKitReporter', '~> 2.0.0'

Swift Package Manager

To install it, simply add the following lines to your Package.swift file (or just use the Package Manager from within XCode and reference this repo):

dependencies: [
    .package(url: "https://github.com/VictorKachalov/HealthKitReporter.git", from: "2.0.0")
]

Carthage

Add the line in your cartfile

github "VictorKachalov/HealthKitReporter" "2.0.0"

Author

Victor Kachalov, [email protected]

License

HealthKitReporter is available under the MIT license. See the LICENSE file for more info.

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].