carp-dk / carp-dk/flutter-plugins
[Pedometer 4.0.1] stepCountStream can hang on iOS
- Dominant language
- Dart
- Stars
- 608
- Forks
- 735
- Avg merge
- 1m
- Merged PRs (30d)
- 3
Description
### Device / Emulator and OS
- Device: iPhone 13 Pro
- OS: iOS 16.4 or 17.0
### Describe the bug
When my app starts I need to query for the current pedometer reading. The only way to do this with the plugin API is grab the first value off the stream:
`final stepCount = await Pedometer.stepCountStream.first`
Normally this works fine but I've found that this call never returns in some edge cases. Leaving my app to hang on start.
### To Reproduce
1. Reboot the phone
2. Do not move it, leave it docked or laying on your desk
3. Call `await Pedometer.stepCountStream.first`
-- app hangs
4. pick up phone and walk around
5. API call returns a result and from now on you get instant results from this API call
### Expected behavior
- The api should always return a response
### Actual behavior
`stepCountStream` does not return any response until the device starts moving
### Flutter doctor
n/a
### Additional information
I stepped into the swift native code and determined that this is expected/undocumented behavior of CMPedometer after a reboot.
```
...
pedometer.startUpdates...
...
```
does not return on the callback but if I replace that code with this
```
pedometer.queryPedometerData(from: dateOfLastReboot, to: Date()) { pedometerData, error in
guard let pedometerData = pedometerData, error == nil else { return }
DispatchQueue.main.async {
self.handleEvent(count: pedometerData.numberOfSteps.intValue)
}
}
```
it works as you would expect. I get an immediate response on the callback regardless of reboot.
### Workaround
For those interested, I added a timeout to the Dart Future to get around this for now. This throws an exception which can be handled in a try/catch:
```
try {
final stepCount = await Pedometer.stepCountStream.first.timeout(const Duration(milliseconds: 100));
return Result.value(stepCount.steps);
} catch (e) {
return Result.error(e);
}
```
P.S. - after seeing how this timeout works on anything that returns a Dart Future I think it's quite elegant already. Maybe I should be doing this for any API calls? I'll leave this bug report here but my solution works for my purposes.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.