diff --git a/README.md b/README.md index b23270d..16cfc18 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # nearby_connections An **android** flutter plugin for the Nearby Connections API +Currently supports Bytes and Files. [![pub package](https://img.shields.io/pub/v/nearby_connections.svg)](https://pub.dartlang.org/packages/nearby_connections) @@ -27,8 +28,11 @@ Add these to AndroidManifest.xml + + + ``` -Since ACCESS_FINE_LOCATION is considered to be dangerous system permissions, in addition to adding them to your manifest, you must request these permissions at runtime. +Since ACCESS_FINE_LOCATION and READ_EXTERNAL_STORAGE is considered to be dangerous system permissions, in addition to adding them to your manifest, you must request these permissions at runtime. ##### As a convinience the library provides methods to check and request location permissions ```java @@ -41,7 +45,7 @@ Nearby().askPermission() ## Work Flow -The work flow is similar to the [android nearby connections library](https://developers.google.com/nearby/connections/overviewoverview) +The work flow is similar to the [Android Nearby Connections library](https://developers.google.com/nearby/connections/overview) ### Advertise for connection ```dart diff --git a/example/lib/main.dart b/example/lib/main.dart index a996030..5b81e65 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -35,119 +35,133 @@ class Body extends StatefulWidget { class _MyBodyState extends State { final String userName = Random().nextInt(1000).toString(); final Strategy strategy = Strategy.P2P_STAR; - String cId = "0"; + String cId = "0"; //currently connected device ID + File tempFile; //stores the file being transferred + Map map = Map(); @override Widget build(BuildContext context) { return Center( child: Column( children: [ - RaisedButton( - child: Text("checkPermission"), - onPressed: () async { - if (await Nearby().checkPermissions()) { - Scaffold.of(context) - .showSnackBar(SnackBar(content: Text("yes"))); - } else { - Scaffold.of(context) - .showSnackBar(SnackBar(content: Text("No"))); - } - }, - ), - RaisedButton( - child: Text("askPermission(location)"), - onPressed: () async { - await Nearby().askPermission(); - }, - ), - Text("UserName: " + userName), - RaisedButton( - child: Text("Start Advertising"), - onPressed: () async { - try { - bool a = await Nearby().startAdvertising( - userName, - strategy, - onConnectionInitiated: (id, info) { - oci(id, info); - }, - onConnectionResult: (id, status) { - showSnackbar(status); - }, - onDisconnected: (id) { - showSnackbar(id); - }, - ); - showSnackbar(a); - } catch (exception) { - showSnackbar(exception); - } - }, + Wrap( + children: [ + RaisedButton( + child: Text("checkPermission"), + onPressed: () async { + if (await Nearby().checkPermissions()) { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text("Location permissions granted :)"))); + } else { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text("Location permissions not granted :("))); + } + }, + ), + RaisedButton( + child: Text("askPermission"), + onPressed: () async { + await Nearby().askPermission(); + }, + ), + ], ), - RaisedButton( - child: Text("Stop Advertising"), - onPressed: () async { - await Nearby().stopAdvertising(); - }, + Text("User Name: " + userName), + Wrap( + children: [ + RaisedButton( + child: Text("Start Advertising"), + onPressed: () async { + try { + bool a = await Nearby().startAdvertising( + userName, + strategy, + onConnectionInitiated: (id, info) { + oci(id, info); + }, + onConnectionResult: (id, status) { + showSnackbar(status); + }, + onDisconnected: (id) { + showSnackbar("Disconnected: "+id); + }, + ); + showSnackbar(a); + } catch (exception) { + showSnackbar(exception); + } + }, + ), + RaisedButton( + child: Text("Stop Advertising"), + onPressed: () async { + await Nearby().stopAdvertising(); + }, + ), + ], ), - RaisedButton( - child: Text("Start Discovery"), - onPressed: () async { - try { - bool a = await Nearby().startDiscovery( - userName, - strategy, - onEndpointFound: (id, name, serviceId) { - print("in callback"); - showModalBottomSheet( - context: context, - builder: (builder) { - return Center( - child: Column( - children: [ - Text("id: " + id), - Text("Name: " + name), - Text("ServiceId: " + serviceId), - RaisedButton( - child: Text("Request Connection"), - onPressed: () { - Navigator.pop(context); - Nearby().requestConnection( - userName, - id, - onConnectionInitiated: (id, info) { - oci(id, info); - }, - onConnectionResult: (id, status) { - showSnackbar(status); - }, - onDisconnected: (id) { - showSnackbar(id); + Wrap( + children: [ + RaisedButton( + child: Text("Start Discovery"), + onPressed: () async { + try { + bool a = await Nearby().startDiscovery( + userName, + strategy, + onEndpointFound: (id, name, serviceId) { + print("in callback"); + showModalBottomSheet( + context: context, + builder: (builder) { + return Center( + child: Column( + children: [ + Text("id: " + id), + Text("Name: " + name), + Text("ServiceId: " + serviceId), + RaisedButton( + child: Text("Request Connection"), + onPressed: () { + Navigator.pop(context); + Nearby().requestConnection( + userName, + id, + onConnectionInitiated: (id, info) { + oci(id, info); + }, + onConnectionResult: (id, status) { + showSnackbar(status); + }, + onDisconnected: (id) { + showSnackbar(id); + }, + ); }, - ); - }, + ), + ], ), - ], - ), + ); + }, ); }, + onEndpointLost: (id) { + showSnackbar(id); + }, ); - }, - onEndpointLost: (id) { - showSnackbar(id); - }, - ); - showSnackbar(a); - } catch (e) { - showSnackbar(e); - } - }, - ), - RaisedButton( - child: Text("Stop Discovery"), - onPressed: () async { - await Nearby().stopDiscovery(); - }, + showSnackbar(a); + } catch (e) { + showSnackbar(e); + } + }, + ), + RaisedButton( + child: Text("Stop Discovery"), + onPressed: () async { + await Nearby().stopDiscovery(); + }, + ), + ], ), RaisedButton( child: Text("Stop All Endpoints"), @@ -171,8 +185,12 @@ class _MyBodyState extends State { if (file == null) return; - Nearby().sendFilePayload(cId, file.path); + int payloadId = await Nearby().sendFilePayload(cId, file.path); showSnackbar("Sending file to $cId"); + Nearby().sendBytesPayload( + cId, + Uint8List.fromList( + "$payloadId:${file.path.split('/').last}".codeUnits)); }, ), ], @@ -205,12 +223,32 @@ class _MyBodyState extends State { cId = id; Nearby().acceptConnection( id, - onPayLoadRecieved: (endid, payload) { + onPayLoadRecieved: (endid, payload) async { if (payload.type == PayloadType.BYTES) { - showSnackbar( - endid + ": " + String.fromCharCodes(payload.bytes)); + String str = String.fromCharCodes(payload.bytes); + showSnackbar(endid + ": " + str); + + if (str.contains(':')) { + // used for file payload as file payload is mapped as + // payloadId:filename + int payloadId = int.parse(str.split(':')[0]); + String fileName = (str.split(':')[1]); + + if (map.containsKey(payloadId)) { + if (await tempFile.exists()) { + tempFile.rename( + tempFile.parent.path + "/" + fileName); + } else { + showSnackbar("File doesnt exist"); + } + } else { + //add to map if not already + map[payloadId] = fileName; + } + } } else if (payload.type == PayloadType.FILE) { showSnackbar(endid + ": File transfer started"); + tempFile = File(payload.filePath); } }, onPayloadTransferUpdate: (endid, payloadTransferUpdate) { @@ -227,6 +265,15 @@ class _MyBodyState extends State { "success, total bytes = ${payloadTransferUpdate.totalBytes}"); showSnackbar(endid + ": SUCCESS in file transfer (file is un-named in downloads) "); + + if (map.containsKey(payloadTransferUpdate.id)) { + //rename the file now + String name = map[payloadTransferUpdate.id]; + tempFile.rename(tempFile.parent.path + "/" + name); + } else { + //bytes not received till yet + map[payloadTransferUpdate.id] = ""; + } } }, ); diff --git a/lib/nearby_connections.dart b/lib/nearby_connections.dart index 1d48426..70ba0e2 100644 --- a/lib/nearby_connections.dart +++ b/lib/nearby_connections.dart @@ -1,6 +1,6 @@ -/// https://pub.dev/packages/nearby_connections#-readme-tab- +/// https://pub.dev/packages/nearby_connections#-readme-tab- library nearby_connections; export 'src/classes.dart'; export 'src/defs.dart'; -export 'src/nearby_connections.dart'; \ No newline at end of file +export 'src/nearby_connections.dart'; diff --git a/lib/src/classes.dart b/lib/src/classes.dart index 1c78a67..236ae78 100644 --- a/lib/src/classes.dart +++ b/lib/src/classes.dart @@ -3,17 +3,17 @@ import 'dart:typed_data'; import 'package:nearby_connections/src/defs.dart'; -/// Bytes may be null if [Payload.type] is not [PayloadType.BYTES] -/// File may be null if [Payload.type] is not [PayloadType.FILE] -/// +/// Bytes may be null if [Payload.type] is not [PayloadType.BYTES] +/// File may be null if [Payload.type] is not [PayloadType.FILE] +/// /// Filepath is the complete filepath(with name) of the file -/// +/// /// The file at this location is incomplete until payloadTransferUpdate /// gives SUCCESS for this payloadId class Payload { int id; PayloadType type; - + Uint8List bytes; String filePath; @@ -51,4 +51,4 @@ class ConnectionInfo { ConnectionInfo( this.endpointName, this.authenticationToken, this.isIncomingConnection); -} \ No newline at end of file +}