Post not yet marked as solved
https://developer.apple.com/documentation/healthkit/hkhealthstore/1614175-enablebackgrounddelivery, as Apple official described the technical documentation, We can read the health data in HealthStore when the application is not started or in the Kill state, when the data in the health App is updated. But it doesn't work for me, I don't know why, I hope I can get the answer here, thank you very much!
Here is my code:
typealias AccessRequestCallback = (_ success: Bool, _ error: Error?) -> Void
/// Helper for reading and writing to HealthKit.
class HealthKitManager: NSObject {
static let shared = HealthKitManager()
private override init() {}
private let healthStore = HKHealthStore()
/// Requests access to all the data types the app wishes to read/write from HealthKit.
/// On success, data is queried immediately and observer queries are set up for background
/// delivery. This is safe to call repeatedly and should be called at least once per launch.
func requestAccessWithCompletion(completion: @escaping AccessRequestCallback) {
guard HKHealthStore.isHealthDataAvailable() else {
debugPrint("Can't request access to HealthKit when it's not supported on the device.")
return
}
let writeDataTypes = dataTypesToWrite()
let readDataTypes = dataTypesToRead()
healthStore.requestAuthorization(toShare: writeDataTypes, read: readDataTypes) { [weak self] success, error in
guard let strongSelf = self else { return }
if success {
debugPrint("Access to HealthKit data has been granted")
strongSelf.readHealthKitData()
strongSelf.setUpBackgroundDeliveryForDataTypes(types: readDataTypes)
} else {
debugPrint("Error requesting HealthKit authorization: \(error?.localizedDescription ?? "")")
}
DispatchQueue.main.async {
completion(success,error)
}
}
}
}
// MARK: - Private
private extension HealthKitManager {
/// Initiates an `HKAnchoredObjectQuery` for each type of data that the app reads and stores
/// the result as well as the new anchor.
func readHealthKitData() {
debugPrint("===============readHealthKitData================")
// HealthKitManager.shared.addLocalPush(title: "readHealthKitData")
}
/// Sets up the observer queries for background health data delivery.
///
/// - parameter types: Set of `HKObjectType` to observe changes to.
private func setUpBackgroundDeliveryForDataTypes(types: Set<HKObjectType>) {
for type in types {
guard let sampleType = type as? HKSampleType else {
debugPrint("ERROR: \(type) is not an HKSampleType");
continue
}
var query: HKQuery!
query = HKObserverQuery(sampleType: sampleType, predicate: nil) { [weak self] query, completionHandler, error in
if error != nil {
debugPrint("observer query update handler called for type \(type), error: \(error?.localizedDescription ?? "")")
return
}
guard let strongSelf = self else { return }
strongSelf.queryForUpdates(type: type)
completionHandler()
}
healthStore.execute(query)
healthStore.enableBackgroundDelivery(for: type, frequency: .immediate) { success, error in
if error != nil {
debugPrint("enableBackgroundDeliveryForType handler called for \(type) - success: \(success), error: \(error?.localizedDescription ?? "")")
return
}
debugPrint("enableBackgroundDeliveryForType: \(type)")
}
}
}
/// Initiates HK queries for new data based on the given type
///
/// - parameter type: `HKObjectType` which has new data avilable.
private func queryForUpdates(type: HKObjectType) {
// self.addLocalPush(title: "queryForUpdates")
switch type {
case HKObjectType.quantityType(forIdentifier: .bodyMass):
debugPrint("HKQuantityTypeIdentifier-BodyMass")
case HKObjectType.quantityType(forIdentifier: .height):
debugPrint("HKQuantityTypeIdentifier-Height")
case HKObjectType.quantityType(forIdentifier: .stepCount):
debugPrint("HKQuantityTypeIdentifier-StepCount")
case is HKWorkoutType:
debugPrint("HKWorkoutType")
default: debugPrint("Unhandled HKObjectType: \(type)")
}
}
/// Types of data that this app wishes to read from HealthKit.
///
/// - returns: A set of HKObjectType.
private func dataTypesToRead() -> Set<HKObjectType> {
if #available(iOS 14.0, *) {
return Set(arrayLiteral:
HKObjectType.quantityType(forIdentifier: .bodyMass)!,
HKObjectType.quantityType(forIdentifier: .height)!,
HKObjectType.categoryType(forIdentifier: .handwashingEvent)!,
HKObjectType.quantityType(forIdentifier: .stepCount)!,
HKObjectType.quantityType(forIdentifier: .distanceCycling)!,
HKObjectType.workoutType())
} else {
return Set(arrayLiteral:
HKObjectType.quantityType(forIdentifier: .bodyMass)!,
HKObjectType.quantityType(forIdentifier: .height)!,
HKObjectType.quantityType(forIdentifier: .stepCount)!,
HKObjectType.quantityType(forIdentifier: .distanceCycling)!,
HKObjectType.workoutType())
}
}
/// Types of data that this app wishes to write to HealthKit.
///
/// - returns: A set of HKSampleType.
private func dataTypesToWrite() -> Set<HKSampleType> {
if #available(iOS 14.0, *) {
return Set(arrayLiteral:
HKObjectType.quantityType(forIdentifier: .bodyMass)!,
HKObjectType.quantityType(forIdentifier: .height)!,
HKObjectType.categoryType(forIdentifier: .handwashingEvent)!,
HKObjectType.quantityType(forIdentifier: .stepCount)!,
HKObjectType.quantityType(forIdentifier: .distanceCycling)!,
HKObjectType.workoutType())
} else {
return Set(arrayLiteral:
HKObjectType.quantityType(forIdentifier: .bodyMass)!,
HKObjectType.quantityType(forIdentifier: .height)!,
HKObjectType.quantityType(forIdentifier: .stepCount)!,
HKObjectType.quantityType(forIdentifier: .distanceCycling)!,
HKObjectType.workoutType())
}
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let vc: ViewController = .init()
window?.rootViewController = vc
window?.makeKeyAndVisible()
healthKitManager.requestAccessWithCompletion() { success, error in
if success { print("HealthKit access granted") }
else { print("Error requesting access to HealthKit: \(error?.localizedDescription ?? "")") }
}
return true
}
I am currently working on an app that compiles sensor data to a csv file for use in health applications. This data is collected in the background via HKWorkoutSession. I'm not using any data from the healthstore, however, it is needed to start the workout session. During background run time, the apple watch continuously runs the heartrate monitor (the green light on the back of the watch).
Is there any way to disable this light from turning on? This app must maintain a low battery usage profile so it may run continuously for 12+ hours, however, the heart rate sensor chews through battery life.
Post not yet marked as solved
Do I have to pay when I use healthKit in my app?
Would you tell me how does it cost or provide related documents?
I want to know really detailed information cause the app has many users
Post not yet marked as solved
I use the Fit! App on my iPhone for my workouts and all of a sudden it’s saying the token has expired. What can I do to fix it?
Post not yet marked as solved
I want to do an app for an apple watch using Heart rate and Electrodermal Activity from Healthkit, but i don't find the frecuency of the data, i mean how many times per second the library send me data?
Post not yet marked as solved
the specifics are pretty straight forward we just need to the code to get HRV in realtime and pasively like the zendo app in the app store
https://github.com/zendotools/zendo but that github doesnt compile. on the watch i can get the Heart rate to update but not hear rate variability. I need it in real time while the user is looking at his watch and passively throught out the day,.
Post not yet marked as solved
I'm trying to request access to read/write from HealthKit but am un able to figure out how to solve this error. When I attempt to put in "NSHealthUpdateUsageDescription" to my Info.plist file I get the Privacy - "Update Usage Description" equivalent, but still get this error.
I'm working with some code based on WWDC20 10664.
Post not yet marked as solved
I've successfully queried lots of HealthKit data, but I'm having trouble querying "appleStandHour" over some time range such as the last week. I'm sure the issue is that this data is a "category" instead of a "statistic". Can someone show me or give me a link that shows how to do this query?
Post not yet marked as solved
Hello!
Today I worked for the first time with Apple Health Kit and successfully saved a workout in Health with the basic informations (activityType, start and end).
My app is in basic function an interval timer where you can create your own workout. Now in the next step I want to add the calories burned in the workout. This information is stored in the attribute 'totalEnergyBurned'.
Do I need to calculate this value myself or can I query this value directly if the user is wearing an Apple Watch? Or maybe the value is even automatically added to the workout if there is the corresponding record? (So far I have only tested the app in the simulator, which is why I can't answer this possibility).
My current code:
func saveToHealthKit(entryID: String){
if HKHealthStore.isHealthDataAvailable() {
let healthStore = HKHealthStore()
if(healthStore.authorizationStatus(for: HKObjectType.workoutType()) == .sharingAuthorized && healthStore.authorizationStatus(for: HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.activeEnergyBurned)!) == .sharingAuthorized){
let newWorkout = HKWorkout(activityType: HKWorkoutActivityType.highIntensityIntervalTraining, start: entry.date!, end: Date())
healthStore.save(newWorkout) { success, error in
guard success else {
// Perform proper error handling here.
return
}
// Add detail samples here.
}
}
}
}
}
Thanks :)
Post not yet marked as solved
So in iOS15.4 the HealthKit authorization sheet which gives you permissions to select HealthKit options comes up in Portrait Only, and my App is in Landscape. Wondering if there is a way to tell the authorization sheet to display in Landscape?
Additionally in iOS15.4 this authorization sheet displays a high NavBar in Portrait by default instead of the compact NavBar, thus after the user accepts the HealthKit permissions and the authorization sheet is dismissed, the App switches back to Landscape, but is now stuck with the high NavBar instead of the compact NavBar, and there appears to be no way to switch it back to the compact NavBar after this. Calling the NavBar itself and programmatically setting compact doesn't work. So the only way to get the compact NavBar back is to restart the App. So my second question is there a way to get the HealthKit authorization sheet to come up with a compact NavBar instead of the high NavBar?
Post not yet marked as solved
I have a problem with Apple HealthKit authorization. Everything worked fine until update of Xcode to version 13.3. It seems that that request for authorization is not fired, even when I explicitly declared that I want to request authorization onAppear of ContentView. This is code for ContentView:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var firebaseManager: FirebaseManager
@EnvironmentObject var healthkitManager: HealthKitManager
var body: some View {
NavigationView {
if firebaseManager.signedIn {
HomePageView()
} else {
SignInView()
}
}
.onAppear {
healthkitManager.authorizeHealthKit()
firebaseManager.signedIn = firebaseManager.isSignedIn }
}
}
Function in HealthKitManager looks like this:
func authorizeHealthKit() {
//Check to see if HealthKit Is Available on this device
guard HKHealthStore.isHealthDataAvailable() else {
print("HealthKit data not available on this device")
return
}
// Set types to read and write in HealthStore
let typesToRead: Set = [
HKObjectType.characteristicType(forIdentifier: .dateOfBirth)!,
HKObjectType.quantityType(forIdentifier: .bloodGlucose)!,
HKObjectType.quantityType(forIdentifier: .insulinDelivery)!,
HKObjectType.quantityType(forIdentifier: .dietaryCarbohydrates)!,
HKObjectType.quantityType(forIdentifier: .stepCount)!,
HKObjectType.quantityType(forIdentifier: .heartRate)!,
HKObjectType.quantityType(forIdentifier: .appleExerciseTime)!,
]
let typesToWrite: Set = [
HKObjectType.quantityType(forIdentifier: .bloodGlucose)!,
HKObjectType.quantityType(forIdentifier: .insulinDelivery)!,
HKObjectType.quantityType(forIdentifier: .dietaryCarbohydrates)!,
]
// Request authorization for those quantity types.
healthStore.requestAuthorization(toShare: typesToWrite, read: typesToRead) { (success, error) in }
}
I've tried to add key Privacy - Health Update Usage Description and Privacy - Health Share Usage Description with some string values to Info tab in project file, but still nothing. When I build application, I get this in console:
[auth] FAILED prompting authorization request to share (
HKQuantityTypeIdentifierBloodGlucose,
HKQuantityTypeIdentifierDietaryCarbohydrates,
HKQuantityTypeIdentifierInsulinDelivery
), read (
HKCharacteristicTypeIdentifierDateOfBirth,
HKQuantityTypeIdentifierHeartRate,
HKQuantityTypeIdentifierBloodGlucose,
HKQuantityTypeIdentifierInsulinDelivery,
HKQuantityTypeIdentifierDietaryCarbohydrates,
HKQuantityTypeIdentifierAppleExerciseTime,
HKQuantityTypeIdentifierStepCount
)
I read some articles, tried multiple possible solutions, restarted my Mac, but everything without success. Should there be a problem because I have two environment object? I'll be thankful for any ideas...
Post not yet marked as solved
can you please guide can we add pause or sync button in our app for apple healthkit data synchronization, basically we are using long running queries for syncing new apple health data to our app and we want to give user option to pause syncing data any time.
Post not yet marked as solved
Can Apple Watch provide complete data on the heartbeat for thousands of seconds during the workout or when using the "Breathe" app?
When I exported data from Apple Health it shows the following data. The rows 195, 196 & 197 are measurements taken through the "Breathe" app.
Thank you for your answers,
Post not yet marked as solved
I am trying to display the steps of a user to a metrics view screen in an apple watch.
Here is how I try to get the steps:
KQuantityType.quantityType(forIdentifier: .stepCount):
let stepCount = HKUnit.meter()
self.stepCount = statistics.sumQuantity()?.doubleValue(for: stepCount) ?? 0
print("step count: \(self.stepCount ?? 0)")
Where stepCount is a published variable.
I then try to display the steps:
Text("\(workoutManager.stepCount!) steps")
I am not able to see the steps in a log when I try to print or through Text....any ideas on how to do this?
Post not yet marked as solved
Hi,
do you know if any data from AW Workout app are actually written to HealthKit only after the workout is over ?
I was wondering how I can read the data (route gps coordinates, specifically) while the workout session is still ongoing.
Thanks!
Post not yet marked as solved
I want to detect when the user has removed the watch from wrist in the middle of a work out. in iOS devices using the HealthKit framework. Been checking the docs, no luck so far.
HealthKit
I am making an app that collects information from Apple Health
(HealthKit). When the application is installed for the first time, the
apple screen appears with the permissions that will be used, but when it
is in Testflight that screen never appears, is there any extra
configuration that has to be done when it is released to production?
if the app is installed from xcode, it works correctly
Post not yet marked as solved
hi is or does anyone want to team up with a group of nurses and doctors to build apps
Post not yet marked as solved
Is there a way to get a human readable description of a HKQuantityTypeIdentifier, that also respects the systems language? So eg
HKQuantityTypeIdentifier.heartRate.humanReadable() = "Heart Rate" on an english phone, and
HKQuantityTypeIdentifier.heartRate.humanReadable() = "Puls" on a german phone etc?
Post not yet marked as solved
I I'm implementing six month sleep analysis data for graph. I have 2 entries as shown in below screenshot. I'm not able to understand logic used to display this data in Six month mode graph in HealthKit. How sleep start time 10:22 PM and sleep end time 7:24 AM is calculated?
Graph in Six Month Mode.