This question is a follow-up of https://developer.apple.com/forums/thread/695853
I need to save a workout with a route from a locked iPhone. I've tried many different ways of saving it since more than one year but I still struggle to find a code which works when the phone is locked.
My current code is :
let healthStore = HKHealthStore()
let workoutConfiguration = HKWorkoutConfiguration()
workoutConfiguration.activityType = .running
let builder = HKWorkoutBuilder(healthStore: healthStore,
configuration: workoutConfiguration,
device: .local())
try await builder.beginCollection(at: workout.start)
guard let quantityType = HKQuantityType.quantityType(forIdentifier: .activeEnergyBurned) else { ... }
let totalEnergyBurnedSample = HKCumulativeQuantitySample(type: quantityType, quantity: HKQuantity(unit: HKUnit.kilocalorie(), doubleValue: totalEnergyBurned), start: workout.start, end: workout.end)
try await builder.addSamples([totalEnergyBurnedSample])
if let route = builder.seriesBuilder(for: .workoutRoute()) as? HKWorkoutRouteBuilder {
try await route.insertRouteData(locations)
} else {
Logger.health.error("Error creating the route builder! Skipping location addition to HealthKit workout.")
}
try await builder.endCollection(at: workout.end)
let hkFinishedWorkout = try await builder.finishWorkout()
Logger.health.info("Workout saved successfully.")
} catch {
Logger.health.error("Failed to save workout: \(String(describing: error))")
}
I naively though that by getting the HKWorkoutRouteBuilder from the HKWorkoutBuilder, the finishWorkout() method would link both of them, but this code never reports an error and the route is associated with the workout only when the iPhone is unlocked when saving. If this code is executed on a locked iPhone, the workout is created, the route is created (both can be seen in the Health application) but the route is not associated with the workout. I can't call finishRoute(with: hkworkout, metadata: nil) on the HKWorkoutRouteBuilder as it requires the HKWorkout which the HKWorkoutBuilder does not return when the phone is locked ;-(
Is there a way to create a workout with an associated route on a locked iPhone ?
Post
Replies
Boosts
Views
Activity
I use the following code :
do {
...
Logger.health.info(c: .saveWorkout, "Ending collection.")
try await builder.endCollection(at: workout.end)
Logger.health.info(c: .saveWorkout, "Finishing workout.")
let hkFinishedWorkout = try await builder.finishWorkout()
guard let hkworkout = hkFinishedWorkout else {
Logger.health.error(c: .saveWorkout, "Error finishing workout. Returned workout is nil!")
return false
}
...
} catch {
Logger.health.error(c: .saveWorkout, "Failed to save workout: \(String(describing: error))")
return false
}
This code sometimes behave correctly, but it also happen to log "Error finishing workout. Returned workout is nil!" which indicates that the builder.finishWorkout() returned nil without throwing an error.
Notes:
There is a workout session running in parallel on the AppleWatch.
The workout is correctly saved, but all the location information is missing as the route builder needs the workout to be saved.
My question is when do finishWorkout()returns nil without throwing an error ?
I need to start an HKObserverQuery on heart rate data when the phone is locked, and then read this data when notified still with the phone is locked. The trigger to start the HKObserverQuery would be an apple watch message which will wake-up the iPhone counterpart app on the lock phone.
Is it possible?