main
1import 'dart:async';
2import 'dart:io';
3
4import 'package:blood_pressure_app/features/old_bluetooth/logic/flutter_blue_plus_mockable.dart';
5import 'package:flutter/foundation.dart';
6import 'package:flutter_bloc/flutter_bloc.dart';
7import 'package:flutter_blue_plus/flutter_blue_plus.dart';
8
9part 'bluetooth_state.dart';
10
11/// Availability of the devices bluetooth adapter.
12///
13/// The only state that allows using the adapter is [BluetoothReady].
14class BluetoothCubit extends Cubit<BluetoothState> {
15 /// Create a cubit connecting to the bluetooth module for availability.
16 ///
17 /// [flutterBluePlus] may be provided for testing purposes.
18 BluetoothCubit({
19 FlutterBluePlusMockable? flutterBluePlus
20 }): _flutterBluePlus = flutterBluePlus ?? FlutterBluePlusMockable(),
21 super(BluetoothInitial()) {
22 _adapterStateStateSubscription = _flutterBluePlus.adapterState.listen(_onAdapterStateChanged);
23 }
24
25 final FlutterBluePlusMockable _flutterBluePlus;
26
27 BluetoothAdapterState _adapterState = BluetoothAdapterState.unknown;
28
29 late StreamSubscription<BluetoothAdapterState> _adapterStateStateSubscription;
30
31 @override
32 Future<void> close() async {
33 await _adapterStateStateSubscription.cancel();
34 await super.close();
35 }
36
37 void _onAdapterStateChanged(BluetoothAdapterState state) async {
38 _adapterState = state;
39 switch (_adapterState) {
40 case BluetoothAdapterState.unavailable:
41 emit(BluetoothUnfeasible());
42 case BluetoothAdapterState.unauthorized:
43 // Bluetooth permissions should always be granted on normal android
44 // devices. Users on non-standard android devices will know how to
45 // enable them. If this is not the case there will be bug reports.
46 emit(BluetoothUnauthorized());
47 case BluetoothAdapterState.on:
48 emit(BluetoothReady());
49 case BluetoothAdapterState.off:
50 case BluetoothAdapterState.turningOff:
51 case BluetoothAdapterState.turningOn:
52 emit(BluetoothDisabled());
53 case BluetoothAdapterState.unknown:
54 emit(BluetoothInitial());
55 }
56 }
57
58 /// Request to enable bluetooth on the device
59 Future<bool> enableBluetooth() async {
60 assert(state is BluetoothDisabled, 'No need to enable bluetooth when '
61 'already enabled or not known to be disabled.');
62 try {
63 if (!Platform.isAndroid) return false;
64 await _flutterBluePlus.turnOn();
65 return true;
66 } on FlutterBluePlusException {
67 return false;
68 }
69 }
70
71 /// Reevaluate the current state.
72 ///
73 /// When the user is in another app like the device settings, sometimes
74 /// the app won't get notified about permission changes and such. In those
75 /// instances the user should have the option to manually recheck the state to
76 /// avoid getting stuck on a unauthorized state.
77 Future<void> forceRefresh() async {
78 _onAdapterStateChanged(_flutterBluePlus.adapterStateNow);
79 }
80}