Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Help]: Should iOS automatically stop the scan when the bluetooth adapter is turned off? #586

Closed
decaf-dev opened this issue Sep 27, 2023 · 7 comments
Labels
help Questions, help, observations, or possible bugs

Comments

@decaf-dev
Copy link

decaf-dev commented Sep 27, 2023

FlutterBluePlus Version

1.15.8

Flutter Version

3.13.2

What OS?

iOS

OS Version

16.6

Bluetooth Module

Not sure

Ask your question

What should be the expected behavior when the bluetooth adapter is turned off on iOS. Right now it seems if a user had a scan running before the adapter was turned off, the scan is still running. However, it no longer produces scan results.

Steps to reproduce:

  1. Start a scan
  2. Turn off the bluetooth adapter
  3. Turn on the bluetooth adapter
  4. There's no exception but no scan results are coming in now

The logs are for when I don't try starting a new scan.

I am using the scanning extension from the migration file

  Stream<ScanResult> _scan({
    List<Guid> withServices = const [],
    Duration? timeout,
    bool androidUsesFineLocation = false,
  }) {
    if (FlutterBluePlus.isScanningNow) {
      throw Exception("Another scan is already in progress");
    }

    final controller = StreamController<ScanResult>();

    var subscription = FlutterBluePlus.scanResults.listen(
      (r) => controller.add(r.first),
      onError: (e, stackTrace) => controller.addError(e, stackTrace),
    );

    FlutterBluePlus.startScan(
      withServices: withServices,
      timeout: timeout,
      removeIfGone: null,
      oneByOne: true,
      androidUsesFineLocation: androidUsesFineLocation,
    );

    Future scanComplete =
        FlutterBluePlus.isScanning.where((e) => e == false).first;

    scanComplete.whenComplete(() {
      subscription.cancel();
      controller.close();
    });

    return controller.stream;
  }

If I try starting a scan, I get an error. This indicates that for sure, the scan is running
Steps to reproduce:

  1. Start a scan
  2. Turn off the bluetooth adapter
  3. Turn on the bluetooth adapter
  4. Try starting a new scan
  5. See exception

Logs

[FBP-iOS] centralManagerDidUpdateState CBManagerStatePoweredOff
[FBP-iOS] disconnectAllDevices
[FBP-iOS] calling disconnect: XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX
[CoreBluetooth] API MISUSE: <CBCentralManager: 0x2827fdae0> can only accept this command while in the powered on state
flutter: [app] BluetoothStackState.init.: adapterState: BluetoothAdapterState.off
[FBP-iOS] centralManagerDidUpdateState CBManagerStatePoweredOn
flutter: [oh_ble] BluetoothStackState.init.: adapterState: BluetoothAdapterState.on

Nothing happens even though it's still scanning
@decaf-dev decaf-dev added the help Questions, help, observations, or possible bugs label Sep 27, 2023
@decaf-dev decaf-dev changed the title [Help]: [Help]: Should iOS automatically stop the scan when the bluetooth adapter is turned off? Sep 27, 2023
@chipweinberger
Copy link
Owner

chipweinberger commented Sep 27, 2023

If I try starting a scan, I get an error.

What error do you get?

and yes, we should automatically stop the scan

@chipweinberger
Copy link
Owner

chipweinberger commented Sep 27, 2023

Also, feel free to try and fix this yourself, and open a PR.

For one, we should listen to OnAdapterStateChanged in _methodCallHandler

  static Future<dynamic> _methodCallHandler(MethodCall call) async {

    // keep track of adapter states
    if (call.method == "OnAdapterStateChanged") {
        BmBluetoothAdapterState r = BmBluetoothAdapterState.fromMap(call.arguments);
        if(isScanningNow && r.adapterState != BmAdapterStateEnum.on ) {
            _scanSubscription?.cancel();
            _scanTimeout?.cancel();
            _isScanning.add(false);
        }
    }

But I am not sure if there needs to be any changes to the iOS code. I'm curious what error you are getting.

@decaf-dev
Copy link
Author

decaf-dev commented Sep 27, 2023

Here is the error that I am getting. It is originating from the migration code. Once the bluetooth adapter stream changes to on, I call scan function from the migration guide. I have named it to _scan.

(I have modified the code a little bit to show case the behavior I'm getting. The overall stacktrace is irrelevant)

══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
The following _Exception was thrown while dispatching notifications for ValueNotifier<BTState>:
Exception: Another scan is already in progress

When the exception was thrown, this was the stack:
#0      BTDeviceScanner._scan (package:app/bt_device_scanner.dart:166:7)
#1      BTDeviceScanner.scanBTDevicesByMacAddress (package:app/bt_device_scanner.dart:133:14)
#2      BluetoothService.startScan (package:app/services/bluetooth_service.dart:137:49)
#3      BluetoothService._btStateListener (package:app/services/bluetooth_service.dart:70:9)
#4      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:403:24)
#5      ValueNotifier.value= (package:flutter/src/foundation/change_notifier.dart:530:5)
#6      BluetoothStackState.init.<anonymous closure> (package:app/bluetooth_stack_state.dart:67:23)
(elided 17 frames from dart:async)

The ValueNotifier<BTState> sending notification was:
  ValueNotifier<BTState>#9ab2c(BTState.on)
════════════════════════════════════════════════════════════════════════════════════════════════════
    btStateSubscription = FlutterBluePlus.adapterState.listen((state) async {
      if (state ==  BluetoothAdapterState.on){
         if (_isBTServiceOff){
            _isBTServiceOff = false;
           _scan();
     } else if ( state == BluetoothAdapterState.off){
        _isBTServiceOff = true;
      }
    });
image

Logs

[FBP-iOS] didUpdateValueForCharacteristic XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX
[FBP-iOS] centralManagerDidUpdateState CBManagerStatePoweredOff
[FBP-iOS] disconnectAllDevices
[FBP-iOS] calling disconnect: XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX
[FBP-iOS] centralManagerDidUpdateState CBManagerStatePoweredOn

@chipweinberger
Copy link
Owner

Another scan is already in progress

Oh ok, great. The code change I suggested above will fix this.

@decaf-dev
Copy link
Author

Just tested it. Yep! That fixes it.

@chipweinberger
Copy link
Owner

chipweinberger commented Sep 27, 2023

ok, I pushed a fix to master branch. please try it!

I will do a release tomorrow, if master branch works for you.

@chipweinberger
Copy link
Owner

fixed 1.15.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help Questions, help, observations, or possible bugs
Projects
None yet
Development

No branches or pull requests

2 participants