main
 1import 'dart:async';
 2
 3import 'package:blood_pressure_app/features/bluetooth/backend/bluetooth_backend.dart';
 4import 'package:blood_pressure_app/logging.dart';
 5import 'package:flutter/foundation.dart';
 6import 'package:flutter_bloc/flutter_bloc.dart';
 7
 8part 'bluetooth_state.dart';
 9
10/// Availability of the devices bluetooth adapter.
11///
12/// The only state that allows using the adapter is [BluetoothStateReady].
13class BluetoothCubit extends Cubit<BluetoothState> with TypeLogger {
14  /// Create a cubit connecting to the bluetooth module for availability.
15  ///
16  /// [manager] manager to check availabilty of.
17  BluetoothCubit({ required this.manager }):
18        super(BluetoothState.fromAdapterState(manager.lastKnownAdapterState)) {
19    _adapterStateSubscription = manager.stateStream.listen(_onAdapterStateChanged);
20
21    _lastKnownState = manager.lastKnownAdapterState;
22    logger.finer('lastKnownState: $_lastKnownState');
23  }
24
25  /// Bluetooth manager
26  late final BluetoothManager manager;
27  late BluetoothAdapterState _lastKnownState;
28  late StreamSubscription<BluetoothAdapterState> _adapterStateSubscription;
29
30  @override
31  Future<void> close() async {
32    await _adapterStateSubscription.cancel();
33    await super.close();
34  }
35
36  void _onAdapterStateChanged(BluetoothAdapterState state) async {
37    if (state == BluetoothAdapterState.unauthorized) {
38      final success = await manager.enable();
39      if (success != true) {
40        logger.warning('Enabling bluetooth failed or not needed on this platform');
41      }
42    }
43
44    _lastKnownState = state;
45    logger.finer('_onAdapterStateChanged(state: $state)');
46    emit(BluetoothState.fromAdapterState(state));
47  }
48
49  /// Request to enable bluetooth on the device
50  Future<bool?> enableBluetooth() async {
51    assert(state is BluetoothStateDisabled, 'No need to enable bluetooth when '
52        'already enabled or not known to be disabled.');
53    try {
54      return manager.enable();
55    } on Exception {
56      return false;
57    }
58  }
59
60  /// Reevaluate the current state.
61  ///
62  /// When the user is in another app like the device settings, sometimes
63  /// the app won't get notified about permission changes and such. In those
64  /// instances the user should have the option to manually recheck the state to
65  /// avoid getting stuck on a unauthorized state.
66  void forceRefresh() => _onAdapterStateChanged(_lastKnownState);
67}