dwyl / learn-apple-watch-development

:green_book: Learn how to build Native Apple Watch (+iPhone) apps from scratch!
55 stars 5 forks source link

Tutorial on how to access Healthkit Data. #43

Open sohilpandya opened 6 years ago

sohilpandya commented 6 years ago

How does a 3rd party app access Healthkit Data such as a user's steps or heart rate.

We'll take the user through a simple tutorial where they'll be able to:

It's a simple starting app which will familiarise the user to the healthkit framework.

Related to #35

sohilpandya commented 6 years ago

Today we'll be building a simple app that will let us access users HealthKit data. We'll be starting out with a trying to find out the total number of steps taken over a given period of time by the user.

What is HealthKit?

HealthKit is a framework built by Apple that will allow us to access health and fitness information from a user's device, whether it be an iPhone or an Apple Watch. The data is stored securely in a HealthKit Data Store, we'll be requiring access to this data store and then querying it to give us specific samples. i.e. the number of steps taken by the user.

Setup

Let's start out by creating a new project. I've called it healthkit-steps screen shot 2017-07-12 at 12 00 04

Next in order for us to be able to access healthkit data we need to take the following two steps:

  1. turn on the capability to access healthkit framework screen shot 2017-07-12 at 12 01 37

  2. Very Important After iOS10 we will have to add description keys to our info.plist file to access or update HealthKit Data. The app will crash if we do not have these descriptions keys in place. screen shot 2017-07-12 at 12 12 10

    • Add Privacy - Health Update Usage Description if you would like to update Healthkit data
    • Add Privacy - Health Share Usage Description if you would like to obtain HealthKit data
    • The description you provide will be shown to the user when they are asked for permission to authorise the app.

Asking for permission to use HealthKit

In order to access a user's HealthKit data we need to ask for permission from the user, we can do this by adding a button on the storyboard and linking it to a function that will ask for user permissions. screen shot 2017-07-12 at 12 38 46


import HealthKit // import this at the top of the file

class ViewController: UIViewController {
    let healthStore = HKHealthStore()

// Rest of your code 

    @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")
            }
        }
    }

// Rest of your code

}

Here is what is happening in the above block of code:

If we run the app in the simulator and select the button, we'll be taken to the authorization screen. screen shot 2017-07-12 at 12 55 52

You can also see that the description we provided in the info.plist is used as the description when asking for permission.

Turn on the access for our app and select Allow, we now have access to read and write to the step count data provided by HealthKit! 🎉

Fetching steps count from HealthKit store

Now that we can access the user's data, let's try to get the number of steps the user may have taken over a given period of time. For this, we need to add a button and a label so that we can ask and then display the data in the app. screen shot 2017-07-12 at 13 18 09

    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)
    }

    @IBOutlet weak var totalSteps: UILabel!
    @IBAction func getTotalSteps(_ sender: Any) {
        getTodaysSteps { (result) in
            print("\(result)")
            DispatchQueue.main.async {
                self.totalSteps.text = "\(result)"
            }
        }
    }

Here is what is happening in the above block of code:

If we build and run this code on the simulator we'll notice that the total number of steps is unfortunately equal to 0.0, this is because the simulator does not have any data. If we try to run the app on our iPhone and see the total number of steps, it should show a real number. 🎉 (don't forget to authorise the app before pressing the get count button)

anb2018 commented 5 years ago

Great. Thanks a ton

ghost commented 5 years ago

Is the method to read entire workouts similar? As in, I would like my app to retrieve all the data associated with a users workouts i.e. Heart rate, speed, longitude, latitude.

danielweatrowski commented 5 years ago

Is it possible to save the steps value to a global variable to use elsewhere in the project?

kanyaneepromma commented 5 years ago

Thank you so much

beherasusanta commented 5 years ago

I followed your code but not getting any value for result.sumQuantity().

sohilpandya commented 5 years ago

@beherasusanta it would be great if you could share the code so I could read through it. :)

I've looked at it https://developer.apple.com/documentation/healthkit/hkstatistics/1615680-sumquantity and the method hasn't changed :)

hohaidang commented 4 years ago

Thanks you so much, Hope you do more <3