some cleanup and adding functions

This commit is contained in:
YamiDoesDev 2022-12-16 01:12:33 +01:00
parent 65a1ce14d1
commit 1d16f01cc3
8 changed files with 828 additions and 48 deletions

62
.gitignore vendored
View File

@ -42,3 +42,65 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
## custom
**/ios/**
**/macos/**
**/windows/**
**/linux/**
## https://github.com/flutter/flutter/blob/master/.gitignore
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/.last_build_id
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/ephemeral
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# macOS
**/Flutter/ephemeral/
**/Pods/
**/macos/Flutter/GeneratedPluginRegistrant.swift
**/macos/Flutter/ephemeral
**/xcuserdata/
# Windows
**/windows/flutter/generated_plugin_registrant.cc
**/windows/flutter/generated_plugin_registrant.h
# Linux
**/linux/flutter/generated_plugin_registrant.cc
**/linux/flutter/generated_plugin_registrant.h
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock

View File

@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>-->
<!-- Needed to communicate with already-paired Bluetooth devices. (Android 12 upwards)-->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<application

View File

@ -11,6 +11,32 @@ Future<Map<String, dynamic>> readJson() async {
return data_;
}
/*Future<void> checkNameAvailability(String input) async {
// await cloudServiceAPI.loadConfig();
List<dynamic> devices = await cloudServiceAPI.getDevices();
for (Map<String, dynamic> selected in devices) {
if (selected["id"] == input) {
await showNameAvailabilityStatus(true);
return;
}
}
await showNameAvailabilityStatus(false);
}
Future<void> showNameAvailabilityStatus(bool status) async {
String statusText = status
? "die eingegebene ID ist verfügbar"
: "die eingegebene ID ist nicht verfügbar";
Fluttertoast.showToast(
msg: statusText,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 2,
backgroundColor: Colors.grey[200],
textColor: Colors.black,
fontSize: 16.0);
}*/
class CloudServiceAPI {
static late final Map<String, dynamic> credentials;
static late Future loadJson;
@ -50,22 +76,22 @@ class CloudServiceAPI {
};
}
Future<List> getDevices() async {
var url = Uri.https(address, '/api/devices');
Uri url = Uri.https(address, '/api/devices');
Response r = await get(url, headers: headers);
return json.decode(r.body) as List<dynamic>;
}
Future<Map<String, dynamic>> getDeviceInfo(deviceID) async {
var url = Uri.https(address, '/api/devices/$deviceID');
Uri url = Uri.https(address, '/api/devices/$deviceID');
Response r = await get(url, headers: headers);
return json.decode(r.body) as Map<String, dynamic>;
}
Future<Map<String, dynamic>> getInformation() async {
var url = Uri.https(address, '/api/app');
Uri url = Uri.https(address, '/api/app');
Response r = await get(url, headers: headers);
return json.decode(r.body) as Map<String, dynamic>;
}
Future<bool> createDevice(id, primaryThumbprint, secondaryThumbprint) async{
var url = Uri.https(address, '/api/devices');
Uri url = Uri.https(address, '/api/devices');
Response r = await post(
url,
headers: headers,

View File

@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
class BluetoothDeviceListEntry extends ListTile {
BluetoothDeviceListEntry({super.key,
required BluetoothDevice device,
int? rssi,
GestureTapCallback? onTap,
GestureLongPressCallback? onLongPress,
bool enabled = true,
}) : super(
onTap: onTap,
onLongPress: onLongPress,
enabled: enabled,
leading: Icon(device.isConnected ? Icons.bluetooth_connected : Icons.bluetooth),
title: Text(device.name ?? "~ UNKNOWN_DEVICE ~"),
subtitle: Text(device.address.toString()),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
rssi != null
? Container(
margin: const EdgeInsets.all(8.0),
child: DefaultTextStyle(
style: _computeTextStyle(rssi),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(rssi.toString()),
const Text('dBm'),
],
),
),
)
: const SizedBox(width: 0, height: 0),
device.isBonded
? const Icon(Icons.link)
: const SizedBox(width: 0, height: 0),
IconButton(
onPressed: () {},
icon: const Icon(Icons.settings)
),
],
),
);
static TextStyle _computeTextStyle(int rssi) {
/**/ if (rssi >= -35) {
return TextStyle(color: Colors.greenAccent[700]);
} else if (rssi >= -45) {
return TextStyle(
color: Color.lerp(
Colors.greenAccent[700], Colors.lightGreen, -(rssi + 35) / 10));
} else if (rssi >= -55) {
return TextStyle(
color: Color.lerp(
Colors.lightGreen, Colors.lime[600], -(rssi + 45) / 10));
} else if (rssi >= -65) {
return TextStyle(
color: Color.lerp(Colors.lime[600], Colors.amber, -(rssi + 55) / 10));
} else if (rssi >= -75) {
return TextStyle(
color: Color.lerp(
Colors.amber, Colors.deepOrangeAccent, -(rssi + 65) / 10));
} else if (rssi >= -85) {
return TextStyle(
color: Color.lerp(
Colors.deepOrangeAccent, Colors.redAccent, -(rssi + 75) / 10));
} else {
return const TextStyle(color: Colors.redAccent);
}
}
}

View File

@ -1,37 +1,369 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter/material.dart';
import 'package:flutter_provisioning_for_iot/widgets/bluetooth_discovery.dart';
import 'package:flutter_provisioning_for_iot/objects/cloud_service_api.dart';
import 'package:flutter_provisioning_for_iot/widgets/switch_widget.dart';
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:flutter/material.dart';
import 'package:flutter_provisioning_for_iot/objects/cloud_service_api.dart';
import 'package:flutter_provisioning_for_iot/screens/bluetooth_device_list_entry.dart';
import 'package:app_settings/app_settings.dart';
import 'package:permission_handler/permission_handler.dart';
class BluetoothScreen extends StatefulWidget {
final bool start = true;
const BluetoothScreen({super.key});
@override
State<BluetoothScreen> createState() => _BluetoothScreen();
}
// debugPrint("r: ${r.device.name} ${r.device.address} ${r.rssi}");
class _BluetoothScreen extends State<BluetoothScreen> {
final textFieldValueHolder = TextEditingController();
CloudServiceAPI cloudServiceAPI = CloudServiceAPI();
List<BluetoothDiscoveryResult> results =
List<BluetoothDiscoveryResult>.empty(growable: true);
//BluetoothManager bluetoothManager = BluetoothManager();
late Stream<BluetoothDiscoveryResult> _stream;
late StreamSubscription<BluetoothDiscoveryResult> _streamSubscription;
late Stream<Uint8List> _connectionStream;
late StreamSubscription<Uint8List> _connectionStreamSubscription;
BluetoothDevice? _bluetoothDevice;
BluetoothConnection? _bluetoothConnection;
final List<BluetoothDiscoveryResult> _discoveryResults =
List<BluetoothDiscoveryResult>.empty(growable: true);
String _messageBuffer = "";
bool isDiscovering = false;
bool isConnecting = false;
bool isDisconnecting = false;
bool isConnected = false;
ButtonStyle buttonStyle = ElevatedButton.styleFrom(
foregroundColor: Colors.black,
backgroundColor: const Color(0xFFFDE100), // Text Color (Foreground color)
);
String inputName = "";
bool initScan = true;
bool scanState = false;
bool widgetScanState = false;
@override
void initState() {
super.initState();
isDiscovering = widget.start;
if (isDiscovering) {
_startDiscovery();
}
}
@override
void dispose() {
// Avoid memory leak (`setState` after dispose) and cancel discovery
_streamSubscription.cancel();
if (isConnected) {
isDisconnecting = true;
_bluetoothConnection?.dispose();
_bluetoothConnection = null;
}
super.dispose();
}
Future<void> _disconnectDevice(BluetoothDevice device) async {
if (_bluetoothConnection != null) {
await _bluetoothConnection!.finish();
_bluetoothConnection = null;
}
}
Future<void> _connectDevice(BluetoothDevice device) async {
String address = device.address;
if (_bluetoothConnection != null) {
await _bluetoothConnection!.finish();
_bluetoothConnection = null;
}
_bluetoothConnection = await BluetoothConnection.toAddress(address);
debugPrint("Connected to the device");
setState(() {
isConnecting = false;
isDisconnecting = false;
});
_connectionStream = _bluetoothConnection!.input!;
_connectionStreamSubscription = _connectionStream.listen(_connectionOnListen);
_connectionStreamSubscription.onDone(_connectionOnDone);
}
void _connectionOnDone() {
/*
// Example: Detect which side closed the connection
// There should be `isDisconnecting` flag to show are we are (locally)
// in middle of disconnecting process, should be set before calling
// `dispose`, `finish` or `close`, which all causes to disconnect.
// If we except the disconnection, `onDone` should be fired as result.
// If we didn't except this (no flag set), it means closing by remote.
*/
if (isDisconnecting) {
debugPrint("Disconnecting locally!");
} else {
debugPrint("Disconnected remotely!");
}
if (mounted) {
setState(() {});
}
}
void _connectionOnListen(Uint8List data) {
debugPrint("received: $data");
debugPrint("received decoded: ${const Utf8Decoder().convert(data)}");
// Allocate buffer for parsed data
int backspacesCounter = 0;
for (var byte in data) {
if (byte == 8 || byte == 127) {
backspacesCounter++;
}
}
Uint8List buffer = Uint8List(data.length - backspacesCounter);
int bufferIndex = buffer.length;
// Apply backspace control character
backspacesCounter = 0;
for (int i = data.length - 1; i >= 0; i--) {
if (data[i] == 8 || data[i] == 127) {
backspacesCounter++;
} else {
if (backspacesCounter > 0) {
backspacesCounter--;
} else {
buffer[--bufferIndex] = data[i];
}
}
}
// Create message if there is new line character
String dataString = String.fromCharCodes(buffer);
int index = buffer.indexOf(13);
if (~index != 0) {
setState(() {
_messageBuffer = dataString.substring(index);
});
} else {
_messageBuffer = (backspacesCounter > 0
? _messageBuffer.substring(
0, _messageBuffer.length - backspacesCounter)
: _messageBuffer + dataString);
}
}
Future<void> _startDiscovery() async {
_stream = FlutterBluetoothSerial.instance.startDiscovery();
_streamSubscription = _stream.listen(_discoveryOnListen);
_streamSubscription.onDone(_discoveryOnDone);
}
void _discoveryOnDone() {
setState(() {
isDiscovering = false;
//debugPrint(isDiscovering as String?);
});
}
void _discoveryOnListen(BluetoothDiscoveryResult event) {
setState(() {
final int existingIndex = _discoveryResults.indexWhere(
(element) => element.device.address == event.device.address);
if (existingIndex >= 0) {
_discoveryResults[existingIndex] = event;
} else {
_discoveryResults.add(event);
}
debugPrint("event: ${event.device.address} ${event.device.name}");
String deviceAddress = "64:BC:58:61:56:B0";
if (event.device.address == deviceAddress) {
_bluetoothDevice = event.device;
}
});
}
Future<void> _restartDiscovery() async {
setState(() {
_discoveryResults.clear();
isDiscovering = true;
});
_startDiscovery();
}
Future<void> _sendData() async {
String output = "0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ !§%&()=?#!?";
_bluetoothConnection!.output
.add(Uint8List.fromList(const Utf8Encoder().convert("$output \r\n")));
await _bluetoothConnection!.output.allSent;
debugPrint("sent: $output");
}
@override
Widget build(BuildContext context) {
//bool isDark = true;
return Theme(
data: ThemeData.dark(), //isDark ? ThemeData.dark() : ThemeData.light(),
child: Scaffold(
appBar: AppBar(
title: isDiscovering
? const Text('Bluetooth Devices (searching...)')
: const Text('Bluetooth Devices'),
actions: <Widget>[
isDiscovering
? FittedBox(
child: Container(
margin: const EdgeInsets.all(16.0),
child: const CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
)
: IconButton(
icon: const Icon(Icons.replay),
onPressed: _restartDiscovery,
)
],
),
body: // Center(
/*child:*/ SingleChildScrollView(
physics: const ScrollPhysics(),
child: Column(
children: <Widget>[
_SingleSection(
title: "Setup",
children: [
const _CustomListTile(
title: "Please Enable Bluetooth",
icon: Icons.info_outline_rounded,
),
_CustomListTile(
title: "Bluetooth Settings",
icon: Icons.bluetooth_connected,
onTap: () async {
await AppSettings.openBluetoothSettings();
},
),
],
),
const Divider(),
ElevatedButton(
onPressed: () async {
await Permission.bluetoothConnect.request();
await Permission.bluetoothScan.request();
if (await Permission.bluetoothScan.request().isGranted) {
// Either the permission was already granted before or the user just granted it.
debugPrint("Location Permission is granted");
} else {
debugPrint("Location Permission is denied.");
}
},
style: buttonStyle,
child: const Text("Request Permissions"),
),
ElevatedButton(
onPressed: () async {
_restartDiscovery();
},
style: buttonStyle,
child: const Text("Restart Scan"),
),
ElevatedButton(
onPressed: () async {
_sendData();
},
style: buttonStyle,
child: const Text("Send Data"),
),
const Divider(),
const _SingleSection(
title: "Bluetooth Devices",
children: [],
),
const Divider(),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: _discoveryResults.length,
itemBuilder: (BuildContext context, index) {
BluetoothDiscoveryResult result = _discoveryResults[index];
final device = result.device;
final address = device.address;
return BluetoothDeviceListEntry(
device: device,
rssi: result.rssi,
onTap: () {
debugPrint(_bluetoothConnection?.isConnected.toString());
if (_bluetoothConnection?.isConnected ?? false) {
_disconnectDevice(device);
} else {
_connectDevice(device);
}
//Navigator.of(context).pop(result.device);
},
onLongPress: () async {
try {
bool bonded = false;
if (device.isBonded) {
debugPrint('Unbonding from ${device.address}...');
await FlutterBluetoothSerial.instance
.removeDeviceBondWithAddress(address);
debugPrint(
'Unbonding from ${device.address} has succed');
} else {
debugPrint('Bonding with ${device.address}...');
bonded = (await FlutterBluetoothSerial.instance
.bondDeviceAtAddress(address))!;
debugPrint(
'Bonding with ${device.address} has ${bonded ? 'succed' : 'failed'}.');
}
setState(() {
_discoveryResults[_discoveryResults.indexOf(result)] =
BluetoothDiscoveryResult(
device: BluetoothDevice(
name: device.name ?? '',
address: address,
type: device.type,
bondState: bonded
? BluetoothBondState.bonded
: BluetoothBondState.none,
),
rssi: result.rssi);
});
} catch (ex) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Error occured while bonding'),
content: Text(ex.toString()),
actions: <Widget>[
TextButton(
child: const Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
},
);
},
),
],
),
),
//),
),
);
}
/*
@override
Widget build(BuildContext context) {
return Scaffold(
@ -60,6 +392,19 @@ class _BluetoothScreen extends State<BluetoothScreen> {
),
child: Column(
children: [
const Text(
"General",
textAlign: TextAlign.start,
),
Row(
children: [
_CustomListTile(
title: "Dark Mode",
icon: CupertinoIcons.moon,
trailing:
CupertinoSwitch(value: false, onChanged: (value) {})),
]
),
TextField(
controller: textFieldValueHolder,
decoration: const InputDecoration(
@ -81,6 +426,39 @@ class _BluetoothScreen extends State<BluetoothScreen> {
child: const Text("check name"),
),
),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
//_startDiscovery();
initScan();
},
style: buttonStyle,
child: const Text("discover devices"),
),
),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
//_startDiscovery();
_sendData();
},
style: buttonStyle,
child: const Text("send data"),
),
),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
//_startDiscovery();
dispose();
},
style: buttonStyle,
child: const Text("dispose"),
),
),
],
),
),
@ -92,7 +470,7 @@ class _BluetoothScreen extends State<BluetoothScreen> {
bottom: BorderSide(width: 1.5, color: Colors.grey),
),
),
child: Row(children: [
child: Row(children: [
const Text(
"Toggle Scan",
style: TextStyle(fontWeight: FontWeight.bold),
@ -106,7 +484,7 @@ class _BluetoothScreen extends State<BluetoothScreen> {
setState(() {
widgetScanState = toggleState;
});
})
})
]),
),
// BluetoothDiscovery(start: initScan, deviceID: inputName),
@ -114,37 +492,64 @@ class _BluetoothScreen extends State<BluetoothScreen> {
),
//),
),
),
);
}
}*/
}
Future<void> checkNameAvailability(String input) async {
// await cloudServiceAPI.loadConfig();
List<dynamic> devices = await cloudServiceAPI.getDevices();
for (Map<String, dynamic> selected in devices) {
if (selected["id"] == input) {
await showNameAvailabilityStatus(true);
return;
}
}
await showNameAvailabilityStatus(false);
}
class _CustomListTile extends StatelessWidget {
final String title;
final IconData icon;
final VoidCallback? onTap;
//final Widget? trailing;
Future<void> showNameAvailabilityStatus(bool status) async {
String statusText = status
? "die eingegebene ID ist verfügbar"
: "die eingegebene ID ist nicht verfügbar";
Fluttertoast.showToast(
msg: statusText,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 2,
backgroundColor: Colors.grey[200],
textColor: Colors.black,
fontSize: 16.0);
const _CustomListTile({
Key? key,
required this.title,
required this.icon,
this.onTap,
//this.trailing,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(title),
leading: Icon(icon),
onTap: onTap,
//trailing: trailing,
);
}
}
class BluetoothScan{
class _SingleSection extends StatelessWidget {
final String? title;
final List<Widget> children;
const _SingleSection({
Key? key,
this.title,
required this.children,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (title != null)
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
title!,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
Column(
children: children,
),
],
);
}
}

View File

@ -0,0 +1,163 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import './bluetooth_device_list_entry.dart';
class BluetoothScreen extends StatefulWidget {
/// If true, discovery starts on page start, otherwise user must press action button.
final bool start;
const BluetoothScreen({this.start = true});
@override
_BluetoothScreen createState() => new _BluetoothScreen();
}
class _BluetoothScreen extends State<BluetoothScreen> {
StreamSubscription<BluetoothDiscoveryResult>? _streamSubscription;
List<BluetoothDiscoveryResult> results =
List<BluetoothDiscoveryResult>.empty(growable: true);
bool isDiscovering = false;
_BluetoothScreen();
@override
void initState() {
super.initState();
isDiscovering = widget.start;
if (isDiscovering) {
_startDiscovery();
}
}
void _restartDiscovery() {
setState(() {
results.clear();
isDiscovering = true;
});
_startDiscovery();
}
void _startDiscovery() {
_streamSubscription =
FlutterBluetoothSerial.instance.startDiscovery().listen((r) {
setState(() {
final existingIndex = results.indexWhere(
(element) => element.device.address == r.device.address);
if (existingIndex >= 0)
results[existingIndex] = r;
else
results.add(r);
});
});
_streamSubscription!.onDone(() {
setState(() {
isDiscovering = false;
});
});
}
// @TODO . One day there should be `_pairDevice` on long tap on something... ;)
@override
void dispose() {
// Avoid memory leak (`setState` after dispose) and cancel discovery
_streamSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: isDiscovering
? Text('Discovering devices')
: Text('Discovered devices'),
actions: <Widget>[
isDiscovering
? FittedBox(
child: Container(
margin: new EdgeInsets.all(16.0),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
)
: IconButton(
icon: Icon(Icons.replay),
onPressed: _restartDiscovery,
)
],
),
body: ListView.builder(
itemCount: results.length,
itemBuilder: (BuildContext context, index) {
BluetoothDiscoveryResult result = results[index];
final device = result.device;
final address = device.address;
return BluetoothDeviceListEntry(
device: device,
rssi: result.rssi,
onTap: () {
Navigator.of(context).pop(result.device);
},
onLongPress: () async {
try {
bool bonded = false;
if (device.isBonded) {
print('Unbonding from ${device.address}...');
await FlutterBluetoothSerial.instance
.removeDeviceBondWithAddress(address);
print('Unbonding from ${device.address} has succed');
} else {
print('Bonding with ${device.address}...');
bonded = (await FlutterBluetoothSerial.instance
.bondDeviceAtAddress(address))!;
print(
'Bonding with ${device.address} has ${bonded ? 'succed' : 'failed'}.');
}
setState(() {
results[results.indexOf(result)] = BluetoothDiscoveryResult(
device: BluetoothDevice(
name: device.name ?? '',
address: address,
type: device.type,
bondState: bonded
? BluetoothBondState.bonded
: BluetoothBondState.none,
),
rssi: result.rssi);
});
} catch (ex) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Error occured while bonding'),
content: Text("${ex.toString()}"),
actions: <Widget>[
new TextButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
},
);
},
),
);
}
}

View File

@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
app_settings:
dependency: "direct main"
description:
name: app_settings
sha256: "7a5b880e2dd41dba8877108180380a1d28d874c231f7c0f9022127a4061b88e1"
url: "https://pub.dev"
source: hosted
version: "4.1.8"
async:
dependency: transitive
description:
@ -224,6 +232,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.3"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8"
url: "https://pub.dev"
source: hosted
version: "10.2.0"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2"
url: "https://pub.dev"
source: hosted
version: "10.2.0"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: "9c370ef6a18b1c4b2f7f35944d644a56aa23576f23abee654cf73968de93f163"
url: "https://pub.dev"
source: hosted
version: "9.0.7"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84"
url: "https://pub.dev"
source: hosted
version: "3.9.0"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b
url: "https://pub.dev"
source: hosted
version: "0.1.2"
platform:
dependency: transitive
description:
@ -415,4 +463,4 @@ packages:
version: "0.2.0+2"
sdks:
dart: ">=2.18.0 <4.0.0"
flutter: ">=3.0.0"
flutter: ">=3.0.1"

View File

@ -41,6 +41,8 @@ dependencies:
shared_preferences: ^2.0.13
http: ^0.13.5
fluttertoast: ^8.1.1
app_settings: ^4.1.8
permission_handler: ^10.2.0
dev_dependencies: