From 79ecebf86a008b71e131e067ee87525927f0bd48 Mon Sep 17 00:00:00 2001 From: Thomas Atkins Date: Sat, 10 Apr 2021 21:52:37 -0500 Subject: [PATCH] expetion error --- loc_chain_app/lib/main.dart | 13 +- loc_chain_app/lib/pages/bluetooth.dart | 30 +++-- loc_chain_app/lib/pages/home.dart | 79 +++++++---- loc_chain_app/lib/util/bluetooth.dart | 179 ++++++++++++++----------- loc_chain_app/pubspec.lock | 16 ++- loc_chain_app/pubspec.yaml | 1 + 6 files changed, 192 insertions(+), 126 deletions(-) diff --git a/loc_chain_app/lib/main.dart b/loc_chain_app/lib/main.dart index 5cc6355..b3dbc08 100644 --- a/loc_chain_app/lib/main.dart +++ b/loc_chain_app/lib/main.dart @@ -1,21 +1,22 @@ import 'package:flutter/material.dart'; +import 'package:loc_chain_app/util/bluetooth.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:loc_chain_app/widgets/navbar.dart'; -import 'dart:math'; +import 'package:flutter_udid/flutter_udid.dart'; void main() async { runApp(App()); - final prefs = await SharedPreferences.getInstance(); - final userName = prefs.getString('userName') ?? '0'; - if (userName == '0') { - prefs.setString('id', Random().nextInt(10000).toString()); - } + (await SharedPreferences.getInstance()) + .setString('userName', await FlutterUdid.consistentUdid); } class App extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { + Connect.stop(); + Connect.start(); + return MaterialApp( title: 'Flutter Demo', theme: ThemeData( diff --git a/loc_chain_app/lib/pages/bluetooth.dart b/loc_chain_app/lib/pages/bluetooth.dart index cbf1c76..624067e 100644 --- a/loc_chain_app/lib/pages/bluetooth.dart +++ b/loc_chain_app/lib/pages/bluetooth.dart @@ -4,6 +4,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:nearby_connections/nearby_connections.dart'; +import 'package:flutter_udid/flutter_udid.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -16,7 +17,7 @@ class BluetoothPage extends StatefulWidget { } class _BluetoothPageState extends State { - // final String id = getId(); + final Future _id = FlutterUdid.consistentUdid; // String getId() => // SharedPreferences.getInstance().then((s) => s.getString('id') ?? '0'); @@ -26,18 +27,21 @@ class _BluetoothPageState extends State { appBar: AppBar( title: Text(widget.title), ), - body: Center( - child: ElevatedButton( - child: Text("GetID"), - onPressed: () async { - final prefs = await SharedPreferences.getInstance(); - final userName = prefs.getString('userName'); - - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text("Id is $userName"))); - }, - ), - ), + body: FutureBuilder( + future: _id, // a previously-obtained Future or null + builder: (BuildContext context, AsyncSnapshot snapshot) { + String content = "Loading id..."; + if (snapshot.hasData) { + content = "ID: ${snapshot.data!}"; + } + return ListView( + children: [ + Container( + child: Text(content), + ), + ], + ); + }), ); } diff --git a/loc_chain_app/lib/pages/home.dart b/loc_chain_app/lib/pages/home.dart index 6db1e1d..61e76b4 100644 --- a/loc_chain_app/lib/pages/home.dart +++ b/loc_chain_app/lib/pages/home.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_udid/flutter_udid.dart'; +import 'package:loc_chain_app/util/bluetooth.dart'; +import 'package:loc_chain_app/util/transaction_manager.dart'; class HomePage extends StatefulWidget { HomePage({Key? key, required this.title}) : super(key: key); @@ -9,16 +12,16 @@ class HomePage extends StatefulWidget { } class _HomePageState extends State { - int _counter = 0; + final Future _id = FlutterUdid.consistentUdid; + Connect connector = Connect(); + Map transactionMap = Map(); + // String getId() => + // SharedPreferences.getInstance().then((s) => s.getString('id') ?? '0'); - void _incrementCounter() { + void refreshTransactions() { setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; + transactionMap = Connect.transactionMap; + Connect.context = context; }); } @@ -28,25 +31,51 @@ class _HomePageState extends State { appBar: AppBar( title: Text(widget.title), ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ], - ), - ), + body: FutureBuilder( + future: _id, // a previously-obtained Future or null + builder: (BuildContext context, AsyncSnapshot snapshot) { + String content = "Loading id..."; + if (snapshot.hasData) { + content = "ID: ${snapshot.data!}"; + } + List transactions = List.generate( + transactionMap.length, + (index) { + Transaction t = transactionMap.values.elementAt(index); + return Card( + child: Row( + children: [Text(t.hash), Text(t.pubKey)], + ), + ); + }, + ); + return ListView( + children: [ + Container( + child: Text(content), + ), + ] + + transactions, + ); + }), floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), + onPressed: () { + refreshTransactions(); + try { + Connect.stop(); + Connect.start(); + } catch (e) { + print(e); + } + }, + child: Icon(Icons.refresh_sharp), ), ); } + + void showSnackbar(dynamic a) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(a.toString()), + )); + } } diff --git a/loc_chain_app/lib/util/bluetooth.dart b/loc_chain_app/lib/util/bluetooth.dart index d16fb82..0affa97 100644 --- a/loc_chain_app/lib/util/bluetooth.dart +++ b/loc_chain_app/lib/util/bluetooth.dart @@ -1,8 +1,7 @@ -import 'dart:io'; -import 'dart:math'; import 'dart:typed_data'; import 'package:flutter/material.dart'; +import 'package:flutter_udid/flutter_udid.dart'; import 'package:nearby_connections/nearby_connections.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -11,20 +10,15 @@ import 'package:loc_chain_app/util/keyfile_manager.dart'; import 'package:loc_chain_app/util/transaction_manager.dart'; class Connect { - final serviceId = "com.yourdomain.appname"; - final Strategy strategy = Strategy.P2P_STAR; - late final _userName; - final BuildContext? context; + static final serviceId = "com.yourdomain.appname"; + static final Strategy strategy = Strategy.P2P_STAR; + static String _userName = ""; + static BuildContext? context; - Map endpointMap = Map(); - Map transactionMap = Map(); + static Map endpointMap = Map(); + static Map transactionMap = Map(); - Connect({this.context}) { - SharedPreferences.getInstance() - .then((s) => _userName = s.getString('userName') ?? '0'); - } - - void showSnackbar(dynamic a) { + static void showSnackbar(dynamic a) { if (context == null) { return; } @@ -33,78 +27,100 @@ class Connect { )); } - void startConnect() async { + static void stop() { + Nearby().stopAdvertising(); + Nearby().stopDiscovery(); + Nearby().stopAllEndpoints(); + } + + static void start() async { + _userName = await FlutterUdid.consistentUdid; // final prefs = await SharedPreferences.getInstance(); // final userName = prefs.getString('userName') ?? " "; - try { - bool advertise = await Nearby().startAdvertising( - _userName, - strategy, - onConnectionInitiated: onConnectionInit, - onConnectionResult: (String id, Status status) async { - // Called when connection is accepted/rejected - // if connection is accepted send the transaction - if (status != Status.CONNECTED) { - return; - } - // Connected to other device, send combined hash and pub key - String str = await Transaction.generateHash(id); - Nearby().sendBytesPayload(id, Uint8List.fromList(str.codeUnits)); - }, - onDisconnected: (String id) { - // Callled whenever a discoverer disconnects from advertiser - // delete connection info - endpointMap.remove(id); - // delete transaction info - transactionMap.remove(id); - }, - serviceId: serviceId, // uniquely identifies your app - ); - - bool discovery = await Nearby().startDiscovery( - _userName, - strategy, - onEndpointFound: (String id, String userName, String serviceId) { - // called when an advertiser is found - Nearby().requestConnection( - userName, - id, - onConnectionInitiated: onConnectionInit, - onConnectionResult: (String id, Status status) async { - // Called when connection is accepted/rejected - // if connection is accepted send the transaction - if (status != Status.CONNECTED) { - return; - } - // Connected to other device, send combined hash and pub key - String str = await Transaction.generateHash(id); - Nearby().sendBytesPayload(id, Uint8List.fromList(str.codeUnits)); - }, - onDisconnected: (id) { - endpointMap.remove(id); - showSnackbar( - "Disconnected from: ${endpointMap[id]!.endpointName}, id $id"); - }, - ); - }, - onEndpointLost: (String? id) { - //called when an advertiser is lost (only if we weren't connected to it ) - }, - serviceId: serviceId, // uniquely identifies your app - ); - } catch (exception) { - // platform exceptions like unable to start bluetooth or insufficient permissions - } + Nearby().startAdvertising( + _userName, + strategy, + onConnectionInitiated: onConnectionInit, + onConnectionResult: (String id, Status status) async { + // Called when connection is accepted/rejected + // if connection is accepted send the transaction + if (status != Status.CONNECTED) { + return; + } + // Connected to other device, send combined hash and pub key + String str = await Transaction.generateHash(id); + print(str); + Nearby().sendBytesPayload(id, Uint8List.fromList(str.codeUnits)); + }, + onDisconnected: (String id) { + // Callled whenever a discoverer disconnects from advertiser + // delete connection info + endpointMap.remove(id); + // delete transaction info + transactionMap.remove(id); + }, + serviceId: serviceId, // uniquely identifies your app + ).catchError((e) { + print(e); + return true; + }); + + Nearby().startDiscovery( + _userName, + strategy, + onEndpointFound: (String id, String userName, String serviceId) { + // called when an advertiser is found + Nearby().requestConnection( + userName, + id, + onConnectionInitiated: onConnectionInit, + onConnectionResult: (String id, Status status) async { + // Called when connection is accepted/rejected + // if connection is accepted send the transaction + if (status != Status.CONNECTED) { + return; + } + // Connected to other device, send combined hash and pub key + String str = await Transaction.generateHash(id); + Nearby() + .sendBytesPayload(id, Uint8List.fromList(str.codeUnits)) + .catchError((e) { + print(e); + }); + }, + onDisconnected: (id) { + endpointMap.remove(id); + print( + "Disconnected from: ${endpointMap[id]!.endpointName}, id $id"); + }, + ).catchError((e) { + print(e); + return true; + }); + }, + onEndpointLost: (String? id) { + //called when an advertiser is lost (only if we weren't connected to it ) + }, + serviceId: serviceId, // uniquely identifies your app + ).catchError((e) { + print(e); + return true; + }); } - void onConnectionInit(String otherId, ConnectionInfo info) { + static void onConnectionInit(String otherId, ConnectionInfo info) { + print('Connection initialized with $otherId'); // Called whenever a discoverer requests connection // // onConnectionInit if (endpointMap.containsKey(otherId)) { + print('Connection rejected to/from $otherId'); Nearby().rejectConnection(otherId); + return; } + print('Connection accepted to/from $otherId'); + endpointMap[otherId] = info; Nearby().acceptConnection( otherId, @@ -114,7 +130,7 @@ class Connect { String str = String.fromCharCodes(payload.bytes!); var parts = str.split(':'); if (parts.length != 2) { - showSnackbar("$_otherId invalid payload: $str"); + print("$_otherId invalid payload: $str"); return; } // Store transaction @@ -123,7 +139,6 @@ class Connect { transactionMap[_otherId] = Transaction(hash: combinedHash, pubKey: publicKey); // sign combined hash with our private key - showSnackbar('Received $_otherId payload: $combinedHash'); print('Received $_otherId payload: $combinedHash:$publicKey'); // upload hash+otherKey to firebase }, @@ -131,14 +146,16 @@ class Connect { if (payloadTransferUpdate.status == PayloadStatus.IN_PROGRESS) { print(payloadTransferUpdate.bytesTransferred); } else if (payloadTransferUpdate.status == PayloadStatus.FAILURE) { - print("failed"); - showSnackbar(endid + ": FAILED to transfer file"); + print(endid + ": FAILED to transfer file"); } else if (payloadTransferUpdate.status == PayloadStatus.SUCCESS) { - showSnackbar( + print( "$endid success, total bytes = ${payloadTransferUpdate.totalBytes}"); } }, - ); + ).catchError((e) { + print(e); + return true; + }); } } diff --git a/loc_chain_app/pubspec.lock b/loc_chain_app/pubspec.lock index da7c214..17fbf33 100644 --- a/loc_chain_app/pubspec.lock +++ b/loc_chain_app/pubspec.lock @@ -43,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" cupertino_icons: dependency: "direct main" description: @@ -102,6 +109,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_udid: + dependency: "direct main" + description: + name: flutter_udid + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" flutter_web_plugins: dependency: transitive description: flutter @@ -345,4 +359,4 @@ packages: version: "0.2.0" sdks: dart: ">=2.12.0 <3.0.0" - flutter: ">=1.24.0-10" + flutter: ">=2.0.0" diff --git a/loc_chain_app/pubspec.yaml b/loc_chain_app/pubspec.yaml index af472f5..787e8e4 100644 --- a/loc_chain_app/pubspec.yaml +++ b/loc_chain_app/pubspec.yaml @@ -33,6 +33,7 @@ dependencies: fast_rsa: ^1.4.0-nullsafety.4 sqflite: ^2.0.0+3 dbcrypt: ^2.0.0 + flutter_udid: ^2.0.0 dev_dependencies: flutter_test: