flutter_blue
flutter_blue copied to clipboard
Enables background usage of flutter-blue
Changed this PR to come from rmawatson:background_feature
instead of rmawatson:master
Android: Swaps activity() calls for context() where only a context is required. The only place an activity is required is when requesting permissions. This patch will return an error when the plugin is used where permissions have not been granted, and there is no activity available to request permissions
iOS: To use bluetooth-central background role and continue to processes in the background it is required that a unique ID (CBCentralManagerOptionRestoreIdentifierKey) be set when the CBCentralManager is initialized. (https://developer.apple.com/documentation/corebluetooth/cbcentralmanageroptionrestoreidentifierkey?language=objc).
Delays instanciation of the cbcentralmanager to when it is first used, so allow setting of a unique id from dart.
When CBCentralManagerOptionRestoreIdentifierKey is set, the CBCentralManagerDelegate must implement centralManager:willRestoreState. The current implmentation is empty as it appears that setting a unique ID is sufficient to stop iOS killing the app once it has been backgrounded, if a bluetooth connection is active, or a scan is in progress.
This has a side effect of printing an API-MISUSE warning when CBCentralManagerOptionRestoreIdentifierKey is not used, because the method centralManager:willRestoreState is always implemented. The warning is harmless when not using CBCentralManagerOptionRestoreIdentifierKey.
Dart:
To support the setting of a unique Id, introduces setUniqueId(String). This should be called before any methods that will instanciate the native instance of the cbcentralmanager.
Additional Notes:
iOS:
Even when a unique ID is set, the app could still theoretically be killed for other reasons by iOS (although I have not experienced this).
If the app is killed by iOS at any point and bluetooth-tasks are ongoing, iOS will restart the app and willRestoreState method will be called on the CBCentralManagerDelegate. It allows about 10 seconds to handle the event, before the app is killed again. It may be nice to allow registering a handler in flutter that can be called to handle such events. This would be iOS only.
States that can be saved and restored:
https://developer.apple.com/documentation/corebluetooth/cbcentralmanagerdelegate/central_manager_state_restoration_options?language=objc
Additionally it would be good to be able to pass through the application restart reason. Currently flutter has no way of knowing why it was started and main() will run if it was started to handle something through willRestoreState. If it was started to handle this callback, the ideal would be run this in a standalone isolate, passing the various restored states to the handler, but allow the main to exit without attempting to run any code by checking the start reason.
@rmawatson Thank you for your work on this. There is no way to pass through the application restart reason. But it is possible to run flutter in headless mode an call it with a different entry point - as I read from geofencing service examples: Flutter's reference example for background processes [_headlessRunner runWithEntrypointAndLibraryUri:entrypoint libraryUri:uri];
, or here, Flutter Engine Reference
Probably (didn't check in detail) the headless runner would be a good candidate for your empty willRestoreState
method.
@treyerl Thanks for that info about the restart reason. I think it should be possible to make the restart reason available from iOS so in the flutter main() entry point you can just branch on the startup reason and gracefully exit when its handled the event.
Although I never actually got round to trying this with flutter blue (as I didn't need it) something like this https://github.com/rmawatson/flutter_startup for getting the startup type, then just providing a way to get the info passed into the startup reason callback should be enough... all gets a bit messy and platform specific though.
Is there any holdups in this? I'd really like to use it!
The same question - any update on when this fix is supposed to be released ?
Can we get this merged?
@pauldemarco is this on the roadmap to be merged? Lots of people needing this functionality.
@rmawatson I tried to merge your branch with the latest from master, but it seems this commit introduces a new issue.
My fork: https://github.com/MichealReed/flutter_blue/tree/background_feature
Commit with issue: https://github.com/pauldemarco/flutter_blue/commit/0879f5f26e1f2afced197bab22e0bcb615e7eed1#diff-2d2a8584d0b1a81f07c64ac07f23ee36
Trace:
Any suggestions?
Edit: I can remove the activity.runOnUiThread()
wrapper, but then it breaks @pauldemarco's example app. Seems to eliminate the crash for my purpose though.
Edit2: posted an issue update here (https://github.com/rmawatson/flutter_isolate/issues/19) if anyone can help solve this is the only thing outstanding for flutter_blue working in the background with an isolate.
Hi guys, I'm needing a background service that runs every 15 minutes periodically that connect with a nearby smartband, fetch its data and send this data to a server without any user interaction. Could someone help me about how should I build this?
Hi guys, any updates on this? This would be such a useful feature. Thank you for all your work! 👍
Hi guys, any updates on this? This would be such a useful feature. Thank you for all your work!
I stop waiting for this and started to use a new lib called by rx_ble, and for my needs, everything is working fine, here is the link
@edsonboldrini are you using this with an isolate in the background?
@edsonboldrini are you using this with an isolate in the background?
I'm using this with flutter_workmanager plugin, and it is working fine.
Note: I added your code together with other merge request.
flutter_blue: git: url: https://github.com/boskokg/flutter_blue.git ref: 0.7.1
@boskokg Shouldn't we close this PR then ?
@xurei I tested setting uniqueId in the production but I did not see any improvements described in this this PR (related to iOS). Other things are already on the latest release of this plugin, so I am not using my branch anymore...
Note: I added your code together with other merge request.
flutter_blue: git: url: https://github.com/boskokg/flutter_blue.git ref: 0.7.1
it is possible with this modification execute the plugin in a headless task?
Any update here or in #191? Maybe you could rebase it on top of latest master?
The iOS app is still getting killed when running in the background. How do you create Bluetooth object again on start up to reconnect to Bluetooth because scanning is not working in the background.
@edsonboldrini, the plugin that you using is it working on restoring BLE connection when the app is killed in iOS