HealthKit

RSS for tag

Access and share health and fitness data while maintaining the user’s privacy and control using HealthKit.

Posts under HealthKit tag

101 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

The Watch App and iPhone App health care permissions are not synchronized.
I developed an iPhone/Watch app with the single target setting (new method) for Watch app projects, which will be available from Xcode14. This app uses HealthKit to retrieve information such as step count and heart rate from healthcare. The watch app is not independent and requires the iPhone app (companion app). Regarding the permission to access health care, i found some differences from the Old WatchApp Project (application project structure using WatchExtension when Xcode 13.4 or lower is used). This does not occur in the iPhone simulator or watch simulator, but only on the actual device. Both the iPhone app and watch app now display a dialog to allow access to health care In the Old WatchApp Project, if access was granted in either app, the granted access is synchronized. When checking the Health Care access status in the iPhone Settings App, permission settings for both the iPhone app and watch app are displayed independently. Because each permission setting is independent, you can choose to allow access to the iPhone app but not to allow it to the watch app. the Old WatchApp Project, permission settings for the iPhone app and watch app were synchronized, so it was not possible to have different settings for each. These behaviors are not described in the documentation. It would be understandable if the transition from watch "extension" to watch "app" is to split the app into two separate units. However, since there is no official documentation explaining this, i cannot determine whether this is the correct specification or not. Furthermore, since the companion app is required rather than a separate Watch app, having the Health Care permission settings out of sync with the companion app could cause unexpected problems and worsen the user experience. (It would be difficult and cumbersome for the user to know what settings they have made). Is there a solution to synchronize this behavior with the companion app like as the Old WatchApp Project? Do i have to go back to the project configuration (use of watchExtension) before Xcode13? I have prepared a sample project below that can test the above. https://github.com/HayakawaAKIRA/SingleTargetWatchOSApp-HealthKit reference: https://developer.apple.com/videos/play/wwdc2022/10133/ https://developer.apple.com/documentation/watchkit/wkapplication https://developer.apple.com/documentation/healthkit/setting_up_healthkit
6
0
1.9k
Nov ’23
Reset list of HealthKit written permissions in Setting after remove those from code
After some years our app has been writing some data to HealthKit we decided to remove this functionality from the app. Permissions were removed from requestAuthorization(toShare:read:completion:) method. For new users everything works fine, but for users who were already asked for writing permission in Settings toggles for permissions are still on. Is it any way to update toggles list in Settings for actual state of permissions? Thanks in advance.
0
0
404
Nov ’23
Provisioning profile doesn't support the HealthKit capability, doesn't include com.apple.developer.healthkit and com.apple.developer.healthkit.access entitlements. Your account does not have sufficient permissions to modify containers.
When I try to add HealthKit capabilities to my app, I get the following signing errors: Communication with Apple failed. Your account does not have sufficient permissions to modify containers. Provisioning profile "iOS Team Provisioning Profile: com.domain.app" doesn't support the HealthKit capability. Provisioning profile "iOS Team Provisioning Profile: com.domain.app" doesn't include the com.apple.developer.healthkit and com.apple.developer.healthkit.access entitlements. In my developer account, the HK capability is enabled. And the entitlements needed are automatically generated by Xcode when I add HK capability, if I try to add them, it says they're already there. I have automatically managed signing selected. Clinical health records are not enabled for Health Kit. Common solutions like cleaning, derived data, and restarts don't help. Does anybody know what this is?
2
1
1.7k
Nov ’23
how to check Healtkit's read permission
Even if you have granted read permission for specific health data items (such as walking, weight, etc.), calling the function below will return the permission as 'sharingDenied'. How can I obtain 'sharingAuthorized'? let stepType = HKObjectType.quantityType(forIdentifier: .stepCount)! let authorizationStatus = HKHealthStore().authorizationStatus(for: stepType) //authorizationStatus => sharingDenied
0
0
396
Nov ’23
Troubleshooting Session Start Errors on watchOS
https://idmsa.apple.com/IDMSWebAuth/signin?path=%2F%2Fforums%2Fpost%2Fquestion%3Flogin%3Dtrue&language=US-EN&instanceId=EN&appIdKey=25138a77e3499638936f018102a53961c923f72b517d4a4d6aee9f09529baca9&rv=4 I've built and tested the code obtained from this site, but although the session starts, pausing or stopping it doesn't seem to work properly. Does anyone know what might be causing this issue? I'm using the latest versions of iOS and watchOS, and my Xcode is version 15.0.1. The main code is as follows, and the session does not start properly in startWorkout. import Foundation import os import HealthKit @MainActor class WorkoutManager: NSObject, ObservableObject { struct SessionSateChange { let newState: HKWorkoutSessionState let date: Date } @Published var sessionState: HKWorkoutSessionState = .notStarted @Published var heartRate: Double = 0 @Published var activeEnergy: Double = 0 @Published var speed: Double = 0 @Published var power: Double = 0 @Published var cadence: Double = 0 @Published var distance: Double = 0 @Published var water: Double = 0 @Published var elapsedTimeInterval: TimeInterval = 0 @Published var workout: HKWorkout? let typesToShare: Set = [HKQuantityType.workoutType(), HKQuantityType(.dietaryWater)] let typesToRead: Set = [ HKQuantityType(.heartRate), HKQuantityType(.activeEnergyBurned), HKQuantityType(.distanceWalkingRunning), HKQuantityType(.cyclingSpeed), HKQuantityType(.cyclingPower), HKQuantityType(.cyclingCadence), HKQuantityType(.distanceCycling), HKQuantityType(.dietaryWater), HKQuantityType.workoutType(), HKObjectType.activitySummaryType() ] let healthStore = HKHealthStore() var session: HKWorkoutSession? #if os(watchOS) var builder: HKLiveWorkoutBuilder? #else var contextDate: Date? #endif let asynStreamTuple = AsyncStream.makeStream(of: SessionSateChange.self, bufferingPolicy: .bufferingNewest(1)) static let shared = WorkoutManager() private override init() { super.init() Task { for await value in asynStreamTuple.stream { await consumeSessionStateChange(value) } } } /** Consume the session state change from the async stream to update sessionState and finish the workout. */ private func consumeSessionStateChange(_ change: SessionSateChange) async { sessionState = change.newState /** Wait for the session to transition states before ending the builder. */ #if os(watchOS) /** Send the elapsed time to the iOS side. */ let elapsedTimeInterval = session?.associatedWorkoutBuilder().elapsedTime(at: change.date) ?? 0 let elapsedTime = WorkoutElapsedTime(timeInterval: elapsedTimeInterval, date: change.date) if let elapsedTimeData = try? JSONEncoder().encode(elapsedTime) { await sendData(elapsedTimeData) } guard change.newState == .stopped, let builder else { return } let finishedWorkout: HKWorkout? do { try await builder.endCollection(at: change.date) finishedWorkout = try await builder.finishWorkout() session?.end() } catch { Logger.shared.log("Failed to end workout: \(error))") return } workout = finishedWorkout #endif } } // MARK: - Workout session management // extension WorkoutManager { func resetWorkout() { #if os(watchOS) builder = nil #endif workout = nil session = nil activeEnergy = 0 heartRate = 0 distance = 0 water = 0 power = 0 cadence = 0 speed = 0 sessionState = .notStarted } func sendData(_ data: Data) async { do { try await session?.sendToRemoteWorkoutSession(data: data) } catch { Logger.shared.log("Failed to send data: \(error)") } } } extension WorkoutManager: HKWorkoutSessionDelegate { nonisolated func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) { Logger.shared.log("Session state changed from \(fromState.rawValue) to \(toState.rawValue)") let sessionSateChange = SessionSateChange(newState: toState, date: date) asynStreamTuple.continuation.yield(sessionSateChange) } nonisolated func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) { Logger.shared.log("\(#function): \(error)") } nonisolated func workoutSession(_ workoutSession: HKWorkoutSession, didDisconnectFromRemoteDeviceWithError error: Error?) { Logger.shared.log("\(#function): \(error)") } nonisolated func workoutSession(_ workoutSession: HKWorkoutSession, didReceiveDataFromRemoteWorkoutSession data: [Data]) { Logger.shared.log("\(#function): \(data.debugDescription)") Task { @MainActor in do { for anElement in data { try handleReceivedData(anElement) } } catch { Logger.shared.log("Failed to handle received data: \(error))") } } } } private func startWorkout() { Task { do { let configuration = HKWorkoutConfiguration() configuration.activityType = .cycling configuration.locationType = .outdoor try await workoutManager.startWorkout(workoutConfiguration: configuration) } catch { Logger.shared.log("Failed to start workout \(error))") } } }
0
0
446
Nov ’23
How to use `HKWorkoutBuilder` inside unit tests on iOS 17 and above
With iOS 17 creation of HKWorkout is deprecated via its init functions and the recommendation is to use HKWorkoutBuilder. If you try to init HKWorkout like you would pre iOS 17 you get this warning of deprecation: The problem is that I am creating this HKWorkout object inside unit tests in order to test a service that works with such objects. And HKWorkoutBuilder requires a HKHealthStore which itself requires to be authenticated to be able to create HKWorkoutActivity instances, like it would be when an app is running. But since the unit tests cannot accept the request on the HKHealthStore I am not sure if using HKWorkoutBuilder inside unit tests is possible. I've also tried to inherit HKHealthStore and override all of its methods, but still, store requires authorization. Any ideas on how to proceed with creating HKWorkout for unit test purposes?
0
1
410
Nov ’23
HealthKit on iPadOS 17 beta2 returns false with isHealthDataAvailable() method
I am running iPadOS 17 beta2 and experiencing an issue with the integration between a third-party app and the Health app. Specifically, I have noticed that the isHealthDataAvailable() method in HealthKit is returning false. Additional Information: ・Device: iPad (6th generation) running iPadOS 17 beta2. ・Xcode: ver14.2.0 Expected Outcome: ・I expect the isHealthDataAvailable() method in HealthKit to return true. This would allow the third-party app to integrate with the Health app. Additional Details: ・The third-party app successfully integrates with the Health app on iOS 17 beta2. ・The issue occurs regardless of whether the Health app is installed or uninstalled. I would greatly appreciate any advice or solutions regarding this issue. Thank you for your assistance.
2
2
1.1k
Nov ’23
Inconsistent Behaviour in HKWorkoutSessionDelegate Method on watchOS 10.0 and Higher
Hello developers, I hope you're all doing well. I've encountered an issue that I'm struggling to resolve, and I'd greatly appreciate any insights or assistance you can offer. Issue Summary: In my watchOS app, I'm utilizing the HKWorkoutSessionDelegate protocol and the workoutSession(_:didFailWithError:) method. While everything works smoothly on watchOS 9.*, I'm facing a problematic inconsistency on watchOS 10.0 and higher. Steps to Reproduce: Create a new watchOS project with a deployment target of watchOS 10.0 or higher. Implement the HKWorkoutSessionDelegate protocol and the workoutSession(_:didFailWithError:) method. Attempt to start a workout session. Expected Behavior: I expect the workout session to commence without any issues, and the delegate method to gracefully handle any errors, without displaying an error message. Actual Behavior: Unfortunately, on watchOS 10.0 and higher, my attempts to initiate a workout session result in an error message: "Cannot start workout session while process is in the background." Version/Build: Affected watchOS versions: 10.0 and higher Non-affected watchOS versions: 9.* Reproducibility: I've confirmed that this issue is reproducible across different projects and on different simulators running watchOS 10.0 and higher. Additional Information: This inconsistency seems to be specific to watchOS versions 10.0 and higher and doesn't occur on watchOS 9.*. It's causing confusion and hampering my development process, and the error message isn't as informative as I'd like. Workaround: I've been unable to identify a workaround for this issue so far. If any of you have insights, solutions, or suggestions, I'd be grateful for your input. Please feel free to share your experiences and thoughts on this matter. Your help is greatly appreciated! Thank you for your time and assistance. Best regards, Leonid
0
1
306
Nov ’23
How can I record a HKWorkoutSession primarily on the iPhone and mirror it on the Apple Watch
In the wwdc2023-10023 session, we go over how the Apple Watch can be used as a primary workout session manager and the iPhone as the mirrored one. How is it possible to create a workout session on the iPhone and optionally mirror it to the Apple Watch to collect heart rate data? In iOS 17, I still cannot instantiate a HKWorkoutSession, I'm assuming it says it's available because we can have an instance of it as a mirrored copy from the Apple Watch. I find it odd that the iPhone cannot manage the primary session. I hope I'm missing something.
2
1
511
Nov ’23
Cannot install app using HealthKit on iPad from TestFlight
iPadOS 17 brings HealthKit to the iPad. So I've updated my HealthKit-using app to also run on iPadOS. I can debug it from Xcode on iPad simulators and my iPad, but when I upload a build to AppStoreConnect from Xcode and try to install it on my iPad from TestFlight, the install-button is missing and instead there is a label saying "incompatible hardware". The app has no other required device capabilities besides healthkit. It was also updated to at least require iOS/iPadOS 17. I can install it on my iPhone but not on the iPad. I also noticed that in this list https://developer.apple.com/support/required-device-capabilities/#ipad-devices no iPad model has the healthkit device capability. Why? Is there some way to find out why exactly TestFlight thinks the iPad is incompatible hardware? Thanks in advance to anyone who can enlighten me here.
2
0
398
Nov ’23
iOS 17: How to use `HKWorkoutBuilder` inside unit tests
Hi, with iOS 17 creation of HKWorkout is deprecated via its init functions and the recommendation is to use HKWorkoutBuilder: The problem is that I am creating this HKWorkout object inside unit tests in order to test a service that works with such objects. And HKWorkoutBuilder requires a HKHealthStore which itself requires to be authenticated to be able to create HKWorkoutActivity instances, like it would be when an app is running. But since the unit tests cannot accept the request on the HKHealthStore I am not sure if using HKWorkoutBuilder inside unit tests is possible. Any ideas on how to proceed with creating HKWorkout for unit test purposes?
0
1
424
Oct ’23
Read sleep schedule
Hi Is there a way to read the sleep schedule i have set in either the health or clock apps? I found a few posts on here asking the same thing and the responce was always either no or just no responce but they are all from over 2 years ago so im not sure if something has changed since then. Up untill recently i was using a shortcuts automation to get the data but a recent update started excluding the sleep schedule alarm from the list that the shortcuts app can pull from the clock app. I dont want historical data, just when the alarm is set to go off next. I was using it to turn my lights on dim half an hour before the alarm goes off without having to set the schedule in 2 places. I have an annoyingly inconsistent morning schedule. Thanks
1
0
592
Oct ’23
Healthcare information may or may not be available through the app.
The app I distribute has a function that retrieves step count information from the "Healthcare" app and displays it on the app, but depending on the device, the step count may not be retrieved. When I checked the settings of the "Healthcare" app, I found that it was properly linked to the app, but for some reason I was unable to retrieve it. Is there any countermeasure in such a case? Is there anyone who has experienced a similar incident?*The same issue occurs even if the device is changed and the same Apple ID is used, so I think it is caused by the Apple ID.
0
0
452
Oct ’23
Cannot Upload HealthKitData in the Background
Hi, I am having some trouble with uploading HealthKit data to AWS S3 in the background. As of now, when I click on the button to beginBackgroundUpdates the data is uploaded as expected. When I go off the app and add data to HealthKit nothing happens. When I go back to the app, the new data is uploaded. I am not sure why this is not happening in the background. More specifically, I am not sure if this is allowed, and if so what I am doing wrong. ContentView: import SwiftUI import HealthKit struct ContentView: View { @StateObject var healthKitManager = HealthKitManager() var body: some View { VStack { Button("Enable Background Step Delivery") { healthKitManager.beginBackgroundUpdates() } } .padding() .onAppear { healthKitManager.requestAuthorization { success in print("Configured HealthKit with Return: \(success)") } } } } #Preview { ContentView() } BackgroundDeliveryApp: import SwiftUI import HealthKit import Amplify import AWSS3StoragePlugin import AWSCognitoAuthPlugin @main struct HKBackgruondDeliveryApp: App { private func configureAmplify() { do { try Amplify.add(plugin: AWSCognitoAuthPlugin()) try Amplify.add(plugin: AWSS3StoragePlugin()) try Amplify.configure() print("Succesfully configured Amplify with S3 Storage") } catch { print("Could not configure Amplify") } } init() { configureAmplify() } var body: some Scene { WindowGroup { ContentView() } } } HealthKitManager import Foundation import HealthKit import Amplify struct TestStep: Encodable, Decodable { let count: Double let startDate: Date let endDate: Date let device: String } class HealthKitManager: ObservableObject { var healthStore: HKHealthStore? let stepType = HKObjectType.quantityType(forIdentifier: .stepCount) let heartRateType = HKQuantityType(.heartRate) let sleepType = HKObjectType.categoryType(forIdentifier: .sleepAnalysis) init() { if HKHealthStore.isHealthDataAvailable() { healthStore = HKHealthStore() } else { print("There is no health data available") healthStore = nil } } func encodeStepList(stepList: [TestStep]) -> Data{ let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 do { return try encoder.encode(stepList) } catch { return Data() } } func uploadStepData(stepList: [TestStep]) async { let stepData = self.encodeStepList(stepList: stepList) let uploadTask = Amplify.Storage.uploadData( key: "ExampleKey", data: stepData ) Task { for await progress in await uploadTask.progress { print("Progress: \(progress)") } } do { let value = try await uploadTask.value print("Completed: \(value)") } catch { print("Could not upload step data") } } func requestAuthorization(completion: @escaping (Bool) -> Void) { guard let stepType = stepType, let sleepType = sleepType else { return completion(false) } guard let healthStore = self.healthStore else { return completion(false) } healthStore.requestAuthorization(toShare: [], read: [stepType, heartRateType, sleepType]) { success, error in if let error = error { print("Some error has occoured during authorization of healthKit") print(error) } return completion(success) } } func beginBackgroundUpdates() { guard let healthStore = healthStore, let stepType = stepType else { print("Cannot begin background updates because HealthStore is nil") return } healthStore.enableBackgroundDelivery(for: stepType, frequency: .immediate) { success, error in print("Background update of health data") if let error = error { print("Some error has occoured during the set up of the background observer query for steps") print(error) return } guard let query = self.createObserverQuery() else { print("Could not create a query for steps") return } healthStore.execute(query) } } func stepCountDeviceRecordsQuery(stepCountObjects: @escaping ([TestStep]) -> Void) { guard let stepType = stepType else { print("Nil step type") return } let stepCountUnit = HKUnit.count() let endDate = Date() let startDate = Calendar.current.date(byAdding: .day, value: -7, to: endDate) let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate) let sortDescriptors = [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)] let stepCountQuery = HKSampleQuery(sampleType: stepType, predicate: predicate, limit: 10000, sortDescriptors: sortDescriptors) { query, results, error in if let error = error { print("Error in getStepCount") print(error) return } guard let results = results else { print("Empty results in getStepCount") return } var stepCounts: [TestStep] = [] for (_, record) in results.enumerated() { guard let record: HKQuantitySample = record as? HKQuantitySample else {return} let step = TestStep(count: record.quantity.doubleValue(for: stepCountUnit), startDate: record.startDate, endDate: record.endDate, device: record.device?.model ?? "") stepCounts.append(step) } print("\(stepCounts.count) records at \(Date())") print(stepCounts[stepCounts.count - 1]) stepCountObjects(stepCounts) } healthStore?.execute(stepCountQuery) } private func createObserverQuery() -> HKQuery? { guard let stepType = stepType else { return nil } let query = HKObserverQuery(sampleType: stepType, predicate: nil) { query, completionHandler, error in self.stepCountDeviceRecordsQuery { stepList in Task { await self.uploadStepData(stepList: stepList) } } completionHandler() } return query } }
1
1
441
Oct ’23
Simulator Xcode - Import Swim Workout
Hi guys, I'm delveloping an app that use HealthData. I use this data: HKWorkoutType.workoutType(), HKObjectType.quantityType(forIdentifier: .heartRate)!, HKObjectType.quantityType(forIdentifier: .distanceSwimming)! I would like use Simulator to test app, but there aren't data. How can I import data? Now to test my app use only my iPhone, but in this way I don't test multiple device to test my app. Could you help me? Thank you. Filippo
0
0
446
Oct ’23
Querying HealthKit for Manually-Entered Medication
I'm trying to query HealthKit for all of users medications, including prescribed medications and user-entered medications. Using a HKSampleQuery with type HKClinicalTypeIdentifierMedicationRecord, I'm able to fetch medications that have been prescribed by a healthcare provider (eg medications associated with clinical FHIR records): let type = HKClinicalType(.medicationRecord) let predicate = HKQuery.predicateForClinicalRecords(withFHIRResourceType: .medicationStatement) let query = HKSampleQuery(sampleType: type, predicate: predicate, limit: kRecordLimit, sortDescriptors: nil) { q, samples, error in // this returns only -clinical- records // it doesnt include manually entered meds } However, medications which I have manually entered into the Health app with a user-defined schedule and dosing do NOT appear in the results of this query. is it possible to fetch medications which have been manually entered by the user?
3
1
944
Oct ’23