Hard Crash when addQuantity is used.
Mravuri96 opened this issue · 1 comments
Mravuri96 commented
Describe the bug
Using the await HealthKitReporter.addQuantity
function causes the app to hard crash.
To Reproduce
final preferredUnits = await HealthKitReporter.preferredUnits(
[
QuantityType.activeEnergyBurned,
QuantityType.stepCount,
QuantityType.distanceCycling
],
);
final calorieUnit = preferredUnits.first;
final distanceUnit = preferredUnits.last;
final workoutHarmonized = WorkoutHarmonized(
WorkoutActivityType.cycling,
200,
calorieUnit.unit,
1,
distanceUnit.unit,
null,
'',
null,
'',
null,
);
final workout = Workout(
'',
'',
DateTime.now()
.subtract(const Duration(seconds: 60))
.millisecondsSinceEpoch,
DateTime.now().millisecondsSinceEpoch,
null,
sourceRevision,
workoutHarmonized,
workout.duration,
[],
);
await HealthKitReporter.save(workout);
final energySample = Quantity(
'',
QuantityType.activeEnergyBurned.identifier,
DateTime.now()
.subtract(const Duration(seconds: 30))
.millisecondsSinceEpoch,
DateTime.now().millisecondsSinceEpoch,
null,
sourceRevision,
QuantityHarmonized(
100,
calorieUnit.unit,
null,
),
);
await HealthKitReporter.save(energySample); //Works, but does not fill the rings if an Apple Watch is paired.
// Need this to fill the workout rings
await HealthKitReporter.addQuantity([energySample], workout); // Crashes the app
Error
*** Terminating app due to uncaught exception '_HKObjectValidationFailureException', reason: 'Type HKSample can not have endDate of NSDate.distantFuture'
*** First throw call stack:
(0x1d124ce38 0x1ca3e78d8 0x1d133cc28 0x1e6b5f6ec 0x1e6b5f4b8 0x1e6b5f3a8 0x1e6b61d7c 0x1016f8f04 0x1016f8b94 0x1016db2c8 0x1cb0348dc 0x1016db0a4 0x101926e98 0x10191d114 0x101927c98 0x105244b14 0x104d2fa8c 0x1d8863460 0x1d8864f88 0x1d88737f4 0x1d8873444 0x1d12dd6c8 0x1d12bf02c 0x1d12c3eb0 0x20b4b9368 0x1d37b9668 0x1d37b92cc 0x100d5e25c 0x1efbbc960)
libc++abi: terminating with uncaught exception of type NSException
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x000000020ed67674 libsystem_kernel.dylib`__pthread_kill + 8
libsystem_kernel.dylib`:
-> 0x20ed67674 <+8>: b.lo 0x20ed67694 ; <+40>
0x20ed67678 <+12>: pacibsp
0x20ed6767c <+16>: stp x29, x30, [sp, #-0x10]!
0x20ed67680 <+20>: mov x29, sp
Target 0: (Runner) stopped.
Lost connection to device.
Swift Equivalent
private let healthStore = HKHealthStore()
let workout = HKWorkout(
activityType: .cycling,
start: Date.now,
end: Date().withAddedMinutes(minutes: 1),
workoutEvents: [],
totalEnergyBurned: HKQuantity(unit: .largeCalorie(), doubleValue: 200),
totalDistance: HKQuantity(unit: .mile(), doubleValue: 1),
metadata: nil
)
healthStore.save(workout) ... //Works
let energySample = HKQuantitySample(
type: HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
quantity: HKQuantity(unit: .largeCalorie(), doubleValue: 100),
start: Date.now,
end: Date.now.withAddedMinutes(minutes: 0.5))
)
healthStore.add([energySample], to: workout) // Works even with future end date.
Mravuri96 commented
@kvs-coder I was able to fix this in this repo. But since Workout.make
always overwrites the uuid, the quantities can never be added to an already existing workout. I am also assuming addCategory
is also broken.
health_kit_reporter/ios/Classes/Extensions+SwiftHealthKitReporterPlugin.swift
Lines 1299 to 1335 in 5954841
Fix
private func addQuantity(
reporter: HealthKitReporter,
arguments: [String: Any],
result: @escaping FlutterResult
) {
guard
let quantity = arguments["quantities"] as? [[String: Any]],
let workout = arguments["workout"] as? [String: Any]
else {
throwParsingArgumentsError(result: result, arguments: arguments)
return
}
let device = arguments["device"] as? [String: Any]
do {
let w = try Workout.make(from: workout)
reporter.writer.addQuantitiy(
try quantity.map {
let q = try Quantity.make(from: $0)
return q.copyWith(
startTimestamp: q.startTimestamp.secondsSince1970,
endTimestamp: q.endTimestamp.secondsSince1970
)
},
from: device != nil
? try Device.make(from: device!)
: nil,
to: w.copyWith(
startTimestamp: w.startTimestamp.secondsSince1970,
endTimestamp: w.endTimestamp.secondsSince1970,
workoutEvents: w.workoutEvents.map { event in
event.copyWith(
startTimestamp: event.startTimestamp.secondsSince1970,
endTimestamp: event.endTimestamp.secondsSince1970
)
}
)
) { (success, error) in
guard error == nil else {
result(
FlutterError(
code: "AddQuantity",
message: "Error in addQuantity",
details: error.debugDescription
)
)
return
}
result(success)
}
} catch {
throwPlatformError(result: result, error: error)
}
}