Sunday, 5 February 2023

Apple Health Kit

How to access and share health and fitness data while maintaining the user’s privacy and control.


Overview

HealthKit provides a central repository for health and fitness data on iPhone and Apple Watch. With the user’s permission, apps communicate with the HealthKit store to access and share this data.

Creating a complete, personalised health and fitness experience includes a variety of tasks:

  • Collecting and storing health and fitness data

  • Analysing and visualising the data

  • Enabling social interactions


HealthKit apps take a collaborative approach to building this experience. Your app doesn’t need to provide all of these features. Instead, you can focus just on the subset of tasks that most interest you.

For example, users can select their favourite weight-tracking, step-counting, and health challenge app, each calibrated to their personal needs. Because HealthKit apps freely exchange data (with user permission), the combined suite provides a more customised experience than any single app on its own


Note

Because health data may contain sensitive, personal information, apps must receive permission from the user to read data from or write data to the HealthKit store. They must also take steps to protect that data at all times. For more information, see Protecting User Privacy.



About the HealthKit Framework


Overview

The HealthKit framework is designed to share data between apps in a meaningful way. The framework constrains the types of data and units to a predefined list, ensuring that all apps understand what the data means and how it can be used. Developers cannot create custom data types or units. Instead, HealthKit provides a wide variety of data types and units.

HealthKit Data

HealthKit saves a variety of data types in the HealthKit Store:

  • Characteristic data. These records represent items that typically do not change, such as the user’s birthdate, blood type, biological sex, and skin type. You can read this data directly from the HealthKit store. Your application cannot save characteristic data. The user must enter or modify this data using the Health app.

  • Sample data. Most of the user’s health data is stored in samples that represent data at a particular point in time. 

  • Workout data. Information about fitness and exercise activities are stored as HKWorkout

  • Source data. Each sample stores information about its source. The HKSourceRevisionobject contains information about the app or device that saved the sample. The HKDeviceobject contains information about the hardware device that generated the data.

  • Deleted objects. An HKDeletedObject instance is used to temporarily store the UUID of an item that has been deleted from the HealthKit store. You can use deleted objects to respond when an object is deleted by the user or another app. For more information, see HKAnchoredObjectQuery and HKDeletedObject.


Properties of Objects and Samples

The HKObject class is the superclass of all HealthKit sample types. All HKObject subclasses are immutable. Each object has the following properties:

  • UUID. A unique identifier for that particular entry.

  • Metadata. A dictionary containing additional information about the entry. The metadata can contain both predefined and custom keys. The predefined keys facilitate the sharing of data between apps. Custom keys help extend a given HealthKit object type, adding app-specific data to the entry.

  • Source Revision. The source of the sample. The source can be a device that directly saves data into HealthKit, or an app. HealthKit automatically records each object’s source and version when the object is saved to the HealthKit store. This property is available only on objects retrieved from the store.

  • Device. The hardware device that generated the data stored in this sample.

  • Type. The sample type, such as a sleep analysis sample, a height sample, or a step count sample.

  • Start date. The sample’s start time.

  • End date. The sample’s end time. If the sample represents a single point in time, the end time should equal the start time. If the sample represents data collected over a time interval, the end time should occur after the start time.

Threading

The HealthKit store is thread-safe, and most HealthKit objects are immutable. In general, you can use HealthKit safely in a multithreaded environment.

All the HealthKit API’s completion handlers execute on private background queues. You will typically want to dispatch this data back to the main queue before updating your user interface or modifying any other resources that should be touched only by the main thread

Syncing Data Between Devices

iPhone and Apple Watch each have their own HealthKit store, and data is automatically synced between the phone and watch. To save space, old data is periodically purged from the Apple Watch. Use earliestPermittedSampleDate() to determine the oldest samples available on Apple Watch.



Setting Up HealthKit

Before using HealthKit, you must perform the following steps:

  1. Enable HealthKit in your app.

  2. Ensure that HealthKit is available on the current device.

  3. Create your app’s HealthKit store.

  4. Request permission to read and share data.


More Info Authorizing Access to Health Data

Enable HealthKit


Before you can use HealthKit, you must enable the HealthKit capabilities for your app. In Xcode, select the project and add the HealthKit capability.



Only select the Clinical Health Records checkbox if your app needs to access the user’s clinical records. App Review may reject apps that enable the Clinical Health Records capability if the app doesn’t actually use the health record data



For a detailed discussion about enabling capabilities, see Configure HealthKit in Xcode Help.



When you enable the HealthKit capabilities on an iOS app, Xcode adds HealthKit to the list of required device capabilities, which prevents users from purchasing or installing the app on devices that don’t support HealthKit.

Ensure HealthKit’s Availability


if HKHealthStore.isHealthDataAvailable() {

   // Add code to use HealthKit here.

}

Create the HealthKit Store


let healthStore = HKHealthStore()


We need only a single HealthKit store per app. These are long-lived objects; you create the store once and keep a reference for later use.


HealthKit Entitlement


A Boolean value that indicates whether the app may request user authorization to access health and activity data that appears in the Health app.


Details

Key 

com.apple.developer.healthkit

Type 

Boolean



HealthKit Capabilities Entitlement


Details

Key 

com.apple.developer.healthkit.access 

Type 

Array of strings



The HealthKit Entitlement provides access to most HealthKit data types. However, because of their highly sensitive nature, some data types require additional entitlements. The HealthKit Capabilities Entitlement provides access to these data types.


To add this entitlement to your app, first enable the HealthKit capability in Xcode, and then check any values that you want to add to the HealthKit Capabilities Entitlement.


Protecting User Privacy

Because health data can be sensitive, HealthKit provides users with fine-grained control over the information that apps can share. The user must explicitly grant each app permission to read and write data to the HealthKit store. Users can grant or deny permission separately for each type of data. 

For example, a user could let your app read step count data, but prevent it from reading blood glucose levels. To prevent possible information leaks, an app isn’t aware when the user denies permission to read data. From the app’s point of view, no data of that type exists.

Important :

Apps must include usage descriptions, or they will crash when you request authorization to access HealthKit data. Include the NSHealthShareUsageDescription key to read, and NSHealthUpdateUsageDescription key to writing data to Healthkit. For projects created using Xcode 13 or later, set these keys in the Target Properties list on the app’s Info tab. For projects created with Xcode 12 or earlier, set these keys in the app's Info.plist file. For more information, see Information Property List.



HKHealthStore


class HKHealthStore : NSObject


Use a HKHealthStore object to request permission to share or read HealthKit data. Once permission is granted, you can use the HealthKit store to save new samples to the store, or to manage the samples that your app has saved.


Coding part:


Authorise HealthKit Access


@IBAction func authoriseHealthKitAccess(_ sender: Any) {

        let healthKitTypes: Set = [

            // access step count

            HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!

        ]

        healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (_, _) in

            print("authrised???")

        }

        healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (bool, error) in

            if let e = error {

                print("oops something went wrong during authorisation \(e.localizedDescription)")

            } else {

                print("User has completed the authorization flow")

            }

        }

    }


Get Today's Steps


func getTodaysSteps(completion: @escaping (Double) -> Void) {

        let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!

        let now = Date()

        let startOfDay = Calendar.current.startOfDay(for: now)

        let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: now, options: .strictStartDate)

        let query = HKStatisticsQuery(quantityType: stepsQuantityType, quantitySamplePredicate: predicate, options: .cumulativeSum) { (_, result, error) in

            var resultCount = 0.0

            guard let result = result else {

                print("Failed to fetch steps rate")

                completion(resultCount)

                return

            }

            if let sum = result.sumQuantity() {

                resultCount = sum.doubleValue(for: HKUnit.count())

            }

            DispatchQueue.main.async {

                completion(resultCount)

            }

        }

        healthStore.execute(query)

    }



  • In the getTodaysSteps we are creating a HKquery by which we will be able to access the HealthKit Data.

  • HKStatisticsQuery will perform statistical calculations for the given data and return matching samples, it can calculate minimum, maximum and average values for the quantities. This is perfect for our need as it will return the sumQuantity for the total number of steps.

    • It also requires a time between which it should run its calculations, we've set it so that we get stats for the number of steps from the start of the day.


Steps sum 

func getTotalSteps(_ sender: Any) {

        getTodaysSteps { (result) in

            print("\(result)")

            DispatchQueue.main.async {

                self.totalSteps.text = "\(result)"

            }

        }

    }


We are running a function on click on the getTotalSteps button, which in turn runs the function that will return the total number of steps.


This is done on a background thread so in order for us to view the total number of steps we will have to push it onto the main thread.



No comments:

Post a Comment