Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Health and Fitness Apps for Apple Watch

Jeff Kelley
February 18, 2016

Health and Fitness Apps for Apple Watch

Jeff Kelley

February 18, 2016
Tweet

More Decks by Jeff Kelley

Other Decks in Programming

Transcript

  1. HEALTH AND FITNESS APPS FOR APPLE
    WATCH
    MOTOR CITY COCOAHEADS

    View full-size slide

  2. HEALTH AND FITNESS APPS FOR APPLE WATCH
    WHY BRING A FITNESS APP TO APPLE WATCH?
    ▸ Heart Rate Monitor
    ▸ Automatically track heart rate during workouts, even in the background
    ▸ Activity Rings Integration
    ▸ Third-party apps contribute to users’ daily activity, making your app part of someone’s
    routine
    ▸ Independent from the Phone
    ▸ Works where phones can’t (like in a pool)
    ▸ Doesn’t need to be carried through a gym

    View full-size slide

  3. HEALTH AND FITNESS APPS FOR APPLE WATCH
    WHY STORE HEALTH DATA IN HEALTHKIT?
    ▸ Separates concerns for health data: storing, processing, and using
    ▸ Automatically share data between your users’ apps
    ▸ You don’t have to implement your own data security for your users’ health data
    ▸ …or make sure their data is backed up
    ▸ Attract new users who are already invested in using HealthKit

    View full-size slide

  4. WITH HEALTH CARE, THERE IS A WIDE-OPEN FIELD TO MAKE SOME REALLY PROFOUND
    CONTRIBUTIONS… SO THIS IS YET ANOTHER WAY TO BEGIN TO BUILD A COMPREHENSIVE
    VIEW OF YOUR LIFE, WHICH SHOULD EMPOWER YOU TO TAKE CARE OF YOURSELF OVER TIME,
    AND WHEN YOU NEED HELP, IT EMPOWERS YOU TO TAKE CERTAIN DATA TO YOUR DOCTOR TO
    GET HELP FROM THEM. ALL WHILE GUARDING YOUR PRIVACY, SO THAT NOBODY’S GETTING
    THE DATA IF YOU DON’T WANT THEM TO HAVE THE DATA. NOBODY’S SHARING THE DATA IF YOU
    DON’T WANT THEM TO SHARE THE DATA. AND, NO, WE’RE NOT KEEPING IT.
    Tim Cook
    HEALTH AND FITNESS APPS FOR APPLE WATCH

    View full-size slide

  5. HEALTH AND FITNESS APPS FOR APPLE WATCH
    WORKING OUT WITH HEALTHKIT
    ▸ Centered around the HKWorkout and HKWorkoutSession classes
    ▸ HKWorkoutSession
    ▸ Beginning one starts the heart rate monitor
    ▸ Use the delegate to get a callback when monitoring begins
    ▸ HKWorkout
    ▸ Created after the workout is complete, saved with samples of all data
    ▸ Not only heart rates, but also data your app knows (e.g. running distance)

    View full-size slide

  6. HEALTH AND FITNESS APPS FOR APPLE WATCH
    CREATING AN HKWORKOUTSESSION
    let session = HKWorkoutSession(activityType: .Running,
    locationType: .Indoor)
    session.delegate = self
    HKHealthStore().startWorkoutSession(session)

    View full-size slide

  7. HEALTH AND FITNESS APPS FOR APPLE WATCH
    WORKOUT TYPES (HKWORKOUTACTIVITYTYPE)
    ▸ AmericanFootball, Archery, AustralianFootball, Badminton, Baseball,
    Basketball, Bowling, Boxing, Climbing, Cricket, CrossTraining, Curling, Cycling,
    Dance, DanceInspiredTraining, Elliptical, EquestrianSports, Fencing, Fishing,
    FunctionalStrengthTraining, Golf, Gymnastics, Handball, Hiking, Hockey,
    Hunting, Lacrosse, MartialArts, MindAndBody, MixedMetabolicCardioTraining,
    PaddleSports, Play, PreparationAndRecovery, Racquetball, Rowing, Rugby,
    Running, Sailing, SkatingSports, SnowSports, Soccer, Softball, Squash,
    StairClimbing, SurfingSports, Swimming, TableTennis, Tennis, TrackAndField,
    TraditionalStrengthTraining, Volleyball, Walking, WaterFitness, WaterPolo,
    WaterSports, Wrestling, Yoga, Other

    View full-size slide

  8. HEALTH AND FITNESS APPS FOR APPLE WATCH
    HKWORKOUTSESSIONDELEGATE
    func workoutSession(workoutSession: HKWorkoutSession,
    didChangeToState toState: HKWorkoutSessionState,
    fromState: HKWorkoutSessionState,
    date: NSDate) {
    switch toState {
    case .NotStarted:
    case .Running:
    case .Ended:
    }
    }
    func workoutSession(workoutSession: HKWorkoutSession,
    didFailWithError error: NSError) {
    print("Workout session error: \(error.localizedDescription)")
    }

    View full-size slide

  9. HEALTH AND FITNESS APPS FOR APPLE WATCH
    WHAT HAPPENS DURING A WORKOUT SESSION?
    ▸ The heart rate sensor activates,
    continuously getting heart rate data while
    the session is running
    ▸ watchOS keeps your app’s workout
    session running, even if the user returns to
    the watch face or launches another app
    ▸ (Optional) The user’s calories burned are
    automatically calculated and delivered to
    your app

    View full-size slide

  10. HEALTH AND FITNESS APPS FOR APPLE WATCH
    READING CALORIE BURN DATA
    ▸ HealthKit data is represented by discrete samples that we’ll add to our workout
    ▸ First, we’ll get a quantity type to represent active energy burned
    ▸ Then, we’ll create a query to ask HealthKit for samples, and we’ll give it an
    update handler to process new samples as they arrive
    ▸ Finally, we’ll execute the query on the health store
    ▸ When the workout session is complete, we’ll add the samples to the workout

    View full-size slide

  11. HEALTH AND FITNESS APPS FOR APPLE WATCH
    READING CALORIE BURN DATA
    guard let calorieType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned) else { return }
    let datePredicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: nil, options: .None)
    let processCalorieSamplesFromQuery = { (query: HKAnchoredObjectQuery,
    samples: [HKSample]?,
    deletedObjects: [HKDeletedObject]?,
    anchor: HKQueryAnchor?,
    error: NSError?) -> Void in
    NSOperationQueue.mainQueue().addOperationWithBlock { [weak self]
    guard let initialCaloriesBurned = self?.currentCaloriesBurned.doubleValueForUnit(.kilocalorieUnit()) else { return }
    let newCaloriesBurned = samples.reduce(initialCaloriesBurned) {
    $0 + $1.quantity.doubleValueForUnit(calorieUnit)
    }
    self?.currentCaloriesBurned = HKQuantity(unit: calorieUnit, doubleValue: newCaloriesBurned)
    self?.calorieSamples += newSamples
    }
    }
    let query = HKAnchoredObjectQuery(type: calorieType,
    predicate: datePredicate,
    anchor: nil,
    limit: Int(HKObjectQueryNoLimit),
    resultsHandler: processCalorieSamplesFromQuery)
    query.updateHandler = processCalorieSamplesFromQuery
    healthStore.executeQuery(query)

    View full-size slide

  12. HEALTH AND FITNESS APPS FOR APPLE WATCH
    CREATING SAMPLE DATA
    ▸ For health data that the app can calculate, you can create your own samples
    and associate them with the workout
    ▸ HKQuantityTypeIdentifierDistanceWalkingRunning,
    HKQuantityTypeIdentifierDistanceCycling, and
    HKQuantityTypeIdentifierFlightsClimbed are obvious candidates
    ▸ Create an HKQuantitySample and add it to the workout

    View full-size slide

  13. HEALTH AND FITNESS APPS FOR APPLE WATCH
    CREATING SAMPLE DATA
    guard let distanceRunType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)
    else { return }
    let lapDistanceQuantity = HKQuantity(unit: HKUnit.meterUnit(), doubleValue: lapDistance)
    var lapStartDate = startDate
    var samples: [HKSample] = []
    for i in lapTimes.startIndex ..< lapTimes.endIndex {
    let lapTime = lapTimes[i]
    let lapEndDate = lapStartDate.dateByAddingTimeInterval(lapTime)
    let sample = HKQuantitySample(type: distanceRunType,
    quantity: lapDistanceQuantity,
    startDate: lapStartDate,
    endDate: lapEndDate,
    device: HKDevice.localDevice(),
    metadata: nil)
    samples.append(sample)
    lapStartDate = lapEndDate
    }

    View full-size slide

  14. HEALTH AND FITNESS APPS FOR APPLE WATCH
    FINISHING A WORKOUT SESSION
    ▸ When your user is done with her workout, call endWorkoutSession() on the
    health store with the workout session as a parameter
    ▸ In the delegate callback, stop any active queries and create an HKWorkout
    object to contain all of the data
    ▸ Save the workout object, then if it succeeded, add samples to the saved
    workout

    View full-size slide

  15. HEALTH AND FITNESS APPS FOR APPLE WATCH
    SAVING A WORKOUT AND ADDING SAMPLES
    let distanceRun = HKQuantity(unit: HKUnit.meterUnit(), doubleValue: lapDistance * Double(lapTimes.count))
    let workout = HKWorkout(activityType: HKWorkoutActivityType.Running,
    startDate: startDate,
    endDate: endDate,
    duration: endDate.timeIntervalSinceDate(startDate),
    totalEnergyBurned: currentCaloriesBurned,
    totalDistance: distanceRun,
    metadata: nil)
    healthStore.saveObject(workout) { [weak self] success, error in
    guard success else { return }
    guard let calorieSamples = self?.calorieSamples where !calorieSamples.isEmpty else { return }
    self?.healthStore.addSamples(calorieSamples, toWorkout: workout) { success, error in
    if let error = error where !success {
    print("Failed to add calorie samples to the workout:" + error.localizedDescription)
    }
    }
    }

    View full-size slide

  16. HEALTH AND FITNESS APPS FOR APPLE WATCH
    BASK IN THE GLOW OF A JOB WELL DONE
    ▸ If you saved active calories burned to your
    workout, you’ll contribute to the activity rings in
    the user’s Activity app
    ▸ On iPhone, when the user looks at their Activity
    app, your app will appear as a contributor
    ▸ You should still save your data outside of
    HealthKit in case the user has it disabled or you
    need to access it in the future on the watch

    View full-size slide

  17. HEALTH AND FITNESS APPS FOR APPLE WATCH
    GETTING DATA OUT OF HEALTHKIT
    ▸ Not only is workout information stored in
    HealthKit, but nutrition, sleep, vital health data,
    and personal measurements
    ▸ Users can enter data manually inside of the
    Health app or using third-party apps (e.g. using
    a food tracker to input nutrition information)
    ▸ Third-party apps can query HealthKit to get
    information out
    ▸ HealthKit may only be read on an unlocked
    iPhone

    View full-size slide

  18. HEALTH AND FITNESS APPS FOR APPLE WATCH
    USING HEALTHKIT DATA ON APPLE WATCH
    ▸ Because the Apple Watch cannot read HealthKit data directly, getting it onto the
    watch is tricky
    ▸ Using WatchConnectivity, you can send data from the phone to the watch
    whenever you have it, then process it on the watch when the user launches the app
    ▸ On the iPhone, you can execute a background query to receive new data in the
    background as users enter it
    ▸ The Health database is locked when the phone is locked, but you can still write new
    data, which is cached until the database is available

    View full-size slide

  19. HEALTH AND FITNESS APPS FOR APPLE WATCH
    A STRATEGY FOR HEALTH COMPLICATIONS
    ▸ On iPhone, use background queries to
    get new data from other apps
    ▸ Whenever new data comes in, use
    WatchConnectivity to sync with the watch
    ▸ On the watch, send all new data to the
    phone, but also update locally
    ▸ Use a local notification if the user needs
    to launch the iPhone app

    View full-size slide

  20. HEALTH AND FITNESS APPS FOR APPLE WATCH
    ASKING FOR PERMISSION
    ▸ Before you can do anything with any Health data,
    you must have the user’s permission
    ▸ Set up a Health entitlement on the developer
    portal and include it in your app
    ▸ Request authorization from the health store to
    read/write specific types
    ▸ The user can enable/disable specific permissions,
    so look at them individually instead of as a whole
    ▸ The user may allow you to write calorie burn
    data, but not to read weight data

    View full-size slide

  21. HEALTH AND FITNESS APPS FOR APPLE WATCH
    ASKING FOR PERMISSION
    let shareTypes = Set([HKObjectType.workoutType(), caloriesBurnedType,
    distanceRunType])
    let readTypes = Set([caloriesBurnedType])
    healthStore.requestAuthorizationToShareTypes(shareTypes,
    readTypes: readTypes,
    completion: { (success: Bool, error: NSError?) in
    if let error = error where !success {
    print("Error authorizing HealthKit: " +
    error.localizedDescription)
    }
    else if !success {
    print("You didn’t authorize HealthKit.")
    }
    })

    View full-size slide

  22. HEALTH AND FITNESS APPS FOR APPLE WATCH
    ASKING FOR PERMISSION
    ▸ Use the authorizationStatusForType() method on the health store to
    determine authorization status
    ▸ If you’re asking for permission on Apple Watch, the user must approve the
    permissions on their iPhone
    ▸ For that, use the handleAuthorizationForExtensionWithCompletion()
    method on the health store

    View full-size slide

  23. HEALTH AND FITNESS APPS FOR APPLE WATCH
    ASKING FOR PERMISSION
    func applicationShouldRequestHealthAuthorization(application: UIApplication) {
    HKHealthStore().handleAuthorizationForExtensionWithCompletion { success, error in
    if let error = error where !success {
    print("HealthKit authorization failed. Error: "
    + error.localizedDescription)
    }
    }
    }

    View full-size slide

  24. HEALTH AND FITNESS APPS FOR APPLE WATCH
    SUGGESTED READING
    ▸ HealthKit Framework Reference
    ▸ iOS Human Interface Guidelines: HealthKit
    ▸ Apple Watch Human Interface Guidelines: Health and Fitness
    ▸ App Store Review Guidelines: HealthKit
    ▸ “Apps using the HealthKit framework must indicate integration with the Health app in their
    marketing text and must clearly identify the HealthKit functionality in the app’s user
    interface”
    ▸ “Apps using the HealthKit framework or conducting human subject research must provide a
    privacy policy or they will be rejected”

    View full-size slide