chipweinberger / flutter_blue_plus

Flutter plugin for connecting and communicationg with Bluetooth Low Energy devices, on Android, iOS, macOS
Other
788 stars 478 forks source link

[Help]: FlutterBluePlus.adapterState.listen never triggers an unauthorized state on Android #1031

Closed Quen71 closed 1 month ago

Quen71 commented 1 month ago

Requirements

Have you checked this problem on the example app?

No

FlutterBluePlus Version

1.33.5

Flutter Version

3.24.2

What OS?

Android

OS Version

Android 14, 15 at least

Bluetooth Module

.

What is your problem?

On an android device, when using FlutterBluePlus.adapterStateNow or listening to FlutterBluePlus.adapterState, the return state is "on" event if the BLE permissions are declined.

To put this in context, here is my test code :

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _hasAllBlePermissions = false;

  @override
  void initState() {
    AppLifecycleListener(
      onResume: () async {
        log(
          name: 'CYCLE',
          'onResume',
        );
        log(
          name: 'BLE_APP_STATE',
          'new state: ${FlutterBluePlus.adapterStateNow}',
        );
        await _checkBlePermissions();
      },
    );

    FlutterBluePlus.setLogLevel(LogLevel.verbose);

    FlutterBluePlus.adapterState.listen(
      (BluetoothAdapterState state) {
        log(
          name: 'BLE_APP_STATE',
          'new state: $state',
        );
      },
    );

    WidgetsBinding.instance.addPostFrameCallback(
      (_) async {
        await Permission.location.request();
        await Permission.bluetoothScan.request();
        await Permission.bluetoothConnect.request();

        await _checkBlePermissions();
      },
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            if (!_hasAllBlePermissions)
              const Text('No BLE permissions, accept Bluetooth permissions in your app settings'),
            if (_hasAllBlePermissions)
              ElevatedButton(
                onPressed: _onScanBleDevicesPressed,
                child: const Text('Scan BLE devices'),
              ),
          ],
        ),
      ),
    );
  }

  Future<void> _checkBlePermissions() async {
    final PermissionStatus locationStatus = await Permission.location.status;
    final PermissionStatus scanStatus = await Permission.bluetoothScan.status;
    final PermissionStatus connectStatus = await Permission.bluetoothConnect.status;

    if (locationStatus != PermissionStatus.granted ||
        scanStatus != PermissionStatus.granted ||
        connectStatus != PermissionStatus.granted) {
      setState(() {
        _hasAllBlePermissions = false;
      });
    } else {
      setState(() {
        _hasAllBlePermissions = true;
      });
    }
  }

  void _onScanBleDevicesPressed() async {
    log(
      name: 'BLE',
      'Stop scan',
    );
    await FlutterBluePlus.stopScan();
    log(
      name: 'BLE',
      'Start scan',
    );

    await FlutterBluePlus.startScan();

    FlutterBluePlus.scanResults.listen(
      (List<ScanResult> scanResult) {
        // log(
        //   name: 'SCAN',
        //   'Scanned devices: $scanResult',
        // );
      },
    );
  }
}

Logs

I/flutter (16181): [FBP] <setLogLevel> args: 5
D/[FBP-Android](16181): [FBP] onMethodCall: setLogLevel
D/[FBP-Android](16181): [FBP] initializing BluetoothAdapter
I/flutter (16181): [FBP] <setLogLevel> result: true
D/[FBP-Android](16181): [FBP] onMethodCall: flutterRestart
D/[FBP-Android](16181): [FBP] disconnectAllDevices(flutterRestart)
D/[FBP-Android](16181): [FBP] connectedPeripherals: 0
I/flutter (16181): [FBP] <getAdapterState> args: null
D/[FBP-Android](16181): [FBP] onMethodCall: getAdapterState
I/flutter (16181): [FBP] <getAdapterState> result: {adapter_state: 4}
chipweinberger commented 1 month ago

if it's a bug, please open a PR to fix it

chipweinberger commented 1 month ago

closing. please open a PR.