feat: check if bluetooth is enabled; ability to disconnect from ESense

This commit is contained in:
Orangerot 2025-01-13 20:00:27 +01:00
parent 4fb6af0135
commit 4c1d029216
5 changed files with 75 additions and 48 deletions

View file

@ -4,9 +4,7 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission <uses-permission android:name="android.permission.BLUETOOTH" />
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission <uses-permission
android:name="android.permission.BLUETOOTH_ADMIN" android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" /> android:maxSdkVersion="30" />

View file

@ -29,21 +29,30 @@ class ESenseInput {
_listenToESense(); _listenToESense();
} }
Future<void> _askForPermissions() async { Future<bool> _askForPermissions() async {
if (!Platform.isAndroid && !Platform.isIOS) return; if (!Platform.isAndroid && !Platform.isIOS) return false;
if (!await Permission.bluetooth.serviceStatus.isEnabled) {
deviceStatus.value = "Bluetooth is disabled!";
return false;
}
if (!(await Permission.bluetoothScan.request().isGranted && if (!(await Permission.bluetoothScan.request().isGranted &&
await Permission.bluetoothConnect.request().isGranted && await Permission.bluetoothConnect.request().isGranted &&
await Permission.bluetooth.request().isGranted)) { await Permission.bluetooth.request().isGranted)) {
print( print(
'WARNING - no permission to use Bluetooth granted. Cannot access eSense device.'); 'WARNING - no permission to use Bluetooth granted. Cannot access eSense device.');
deviceStatus.value = "Insufficiant Permissions";
return false;
} }
// for some strange reason, Android requires permission to location for Bluetooth to work.....? // for some strange reason, Android requires permission to location for Bluetooth to work.....?
if (Platform.isAndroid) { if (Platform.isAndroid) {
if (!(await Permission.locationWhenInUse.request().isGranted)) { if (!(await Permission.locationWhenInUse.request().isGranted)) {
print( print(
'WARNING - no permission to access location granted. Cannot access eSense device.'); 'WARNING - no permission to access location granted. Cannot access eSense device.');
deviceStatus.value = "Insufficiant Permissions";
return false;
} }
} }
return true;
} }
void _listenToESense() { void _listenToESense() {
@ -151,7 +160,8 @@ class ESenseInput {
Future<void> connectToESense(String deviceName) async { Future<void> connectToESense(String deviceName) async {
if (!connected) { if (!connected) {
await _askForPermissions(); bool permissionSuccessfull = await _askForPermissions();
if (!permissionSuccessfull) return;
print('Trying to connect to eSense device namend \'$deviceName\''); print('Trying to connect to eSense device namend \'$deviceName\'');
eSenseDeviceName = deviceName; eSenseDeviceName = deviceName;
eSenseManager.deviceName = deviceName; eSenseManager.deviceName = deviceName;

View file

@ -21,10 +21,14 @@ class ConnectionStatusButton extends StatelessWidget {
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return ESenseConnectDialog( return ESenseConnectDialog(
deviceStatus: ESenseInput.instance.deviceStatus, deviceStatus: ESenseInput.instance.deviceStatus,
connect: (String name) { connect: (String name) {
ESenseInput.instance.connectToESense(name); ESenseInput.instance.connectToESense(name);
}); },
disconnect: () {
ESenseInput.instance.eSenseManager.disconnect();
},
);
}, },
), ),
label: Text(deviceStatus), label: Text(deviceStatus),

View file

@ -1,10 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:sense_the_rhythm/utils/esense_input.dart';
class ESenseConnectDialog extends StatefulWidget { class ESenseConnectDialog extends StatefulWidget {
final void Function(String) connect; final void Function(String) connect;
final VoidCallback disconnect;
final ValueNotifier<String> deviceStatus; final ValueNotifier<String> deviceStatus;
const ESenseConnectDialog( const ESenseConnectDialog(
{super.key, required this.deviceStatus, required this.connect}); {super.key,
required this.deviceStatus,
required this.connect,
required this.disconnect});
@override @override
State<ESenseConnectDialog> createState() => _ESenseConnectDialogState(); State<ESenseConnectDialog> createState() => _ESenseConnectDialogState();
@ -15,38 +21,43 @@ class _ESenseConnectDialogState extends State<ESenseConnectDialog> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return ValueListenableBuilder(
title: const Text('Connect to ESense'), valueListenable: widget.deviceStatus,
content: Column(mainAxisSize: MainAxisSize.min, children: [ builder: (BuildContext context, String deviceStatus, Widget? child) {
TextField( return AlertDialog(
onChanged: (input) { title: const Text('Connect to ESense'),
setState(() { content: Column(mainAxisSize: MainAxisSize.min, children: [
eSenseDeviceName = input; TextField(
}); onChanged: (input) {
}, setState(() {
decoration: InputDecoration( eSenseDeviceName = input;
border: OutlineInputBorder(), });
hintText: 'eSense-xxxx', },
labelText: 'Device name', decoration: InputDecoration(
), border: OutlineInputBorder(),
), hintText: 'eSense-xxxx',
// Text(eSenseDeviceName), labelText: 'Device name',
ValueListenableBuilder( ),
valueListenable: widget.deviceStatus, ),
builder: (BuildContext context, String value, Widget? child) { // Text(eSenseDeviceName),
return Text(value); Text(deviceStatus)
}), ]),
]), actions: <Widget>[
actions: <Widget>[ TextButton(
TextButton( onPressed: () => Navigator.pop(context, 'Cancel'),
onPressed: () => Navigator.pop(context, 'Cancel'), child: const Text('Close'),
child: const Text('Close'), ),
), ESenseInput.instance.connected
TextButton( ? TextButton(
onPressed: () => widget.connect(eSenseDeviceName), onPressed: () => widget.disconnect(),
child: const Text('Connect'), child: const Text('Disconnect'),
), )
], : TextButton(
); onPressed: () => widget.connect(eSenseDeviceName),
child: const Text('Connect'),
),
],
);
});
} }
} }

View file

@ -25,10 +25,14 @@ class LevelListEntry extends StatelessWidget {
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return ESenseConnectDialog( return ESenseConnectDialog(
deviceStatus: ESenseInput.instance.deviceStatus, deviceStatus: ESenseInput.instance.deviceStatus,
connect: (String name) { connect: (String name) {
ESenseInput.instance.connectToESense(name); ESenseInput.instance.connectToESense(name);
}); },
disconnect: () {
ESenseInput.instance.eSenseManager.disconnect();
},
);
}, },
); );
} }