carp-dk / carp-dk/flutter-plugins

[Pedometer 4.0.1] stepCountStream can hang on iOS

Open
#825 0 comments 0 reactions 0 assignees View on GitHub
bugfix pedometer
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.