import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:nearby_connections/nearby_connections.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('Nearby Connections example app'), ), body: Body(), ), ); } } class Body extends StatefulWidget { @override _MyBodyState createState() => _MyBodyState(); } class _MyBodyState extends State { final String userName = Random().nextInt(10000).toString(); final Strategy strategy = Strategy.P2P_STAR; Map endpointMap = Map(); File? tempFile; //reference to the file currently being transferred Map map = Map(); //store filename mapped to corresponding payloadId @override Widget build(BuildContext context) { return Center( child: Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ Text( "Permissions", ), Wrap( children: [ ElevatedButton( child: Text("checkLocationPermission"), onPressed: () async { if (await Nearby().checkLocationPermission()) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Location permissions granted :)"))); } else { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Location permissions not granted :("))); } }, ), ElevatedButton( child: Text("askLocationPermission"), onPressed: () async { if (await Nearby().askLocationPermission()) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Location Permission granted :)"))); } else { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Location permissions not granted :("))); } }, ), ElevatedButton( child: Text("checkExternalStoragePermission"), onPressed: () async { if (await Nearby().checkExternalStoragePermission()) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("External Storage permissions granted :)"))); } else { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( "External Storage permissions not granted :("))); } }, ), ElevatedButton( child: Text("askExternalStoragePermission"), onPressed: () { Nearby().askExternalStoragePermission(); }, ), ], ), Divider(), Text("Location Enabled"), Wrap( children: [ ElevatedButton( child: Text("checkLocationEnabled"), onPressed: () async { if (await Nearby().checkLocationEnabled()) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Location is ON :)"))); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Location is OFF :("))); } }, ), ElevatedButton( child: Text("enableLocationServices"), onPressed: () async { if (await Nearby().enableLocationServices()) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Location Service Enabled :)"))); } else { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Enabling Location Service Failed :("))); } }, ), ], ), Divider(), Text("User Name: " + userName), Wrap( children: [ ElevatedButton( child: Text("Start Advertising"), onPressed: () async { try { bool a = await Nearby().startAdvertising( userName, strategy, onConnectionInitiated: onConnectionInit, onConnectionResult: (id, status) { showSnackbar(status); }, onDisconnected: (id) { showSnackbar( "Disconnected: ${endpointMap[id]!.endpointName}, id $id"); setState(() { endpointMap.remove(id); }); }, ); showSnackbar("ADVERTISING: " + a.toString()); } catch (exception) { showSnackbar(exception); } }, ), ElevatedButton( child: Text("Stop Advertising"), onPressed: () async { await Nearby().stopAdvertising(); }, ), ], ), Wrap( children: [ ElevatedButton( child: Text("Start Discovery"), onPressed: () async { try { bool a = await Nearby().startDiscovery( userName, strategy, onEndpointFound: (id, name, serviceId) { // show sheet automatically to request connection showModalBottomSheet( context: context, builder: (builder) { return Center( child: Column( children: [ Text("id: " + id), Text("Name: " + name), Text("ServiceId: " + serviceId), ElevatedButton( child: Text("Request Connection"), onPressed: () { Navigator.pop(context); Nearby().requestConnection( userName, id, onConnectionInitiated: (id, info) { onConnectionInit(id, info); }, onConnectionResult: (id, status) { showSnackbar(status); }, onDisconnected: (id) { setState(() { endpointMap.remove(id); }); showSnackbar( "Disconnected from: ${endpointMap[id]!.endpointName}, id $id"); }, ); }, ), ], ), ); }, ); }, onEndpointLost: (id) { showSnackbar( "Lost discovered Endpoint: ${endpointMap[id]!.endpointName}, id $id"); }, ); showSnackbar("DISCOVERING: " + a.toString()); } catch (e) { showSnackbar(e); } }, ), ElevatedButton( child: Text("Stop Discovery"), onPressed: () async { await Nearby().stopDiscovery(); }, ), ], ), Text("Number of connected devices: ${endpointMap.length}"), ElevatedButton( child: Text("Stop All Endpoints"), onPressed: () async { await Nearby().stopAllEndpoints(); setState(() { endpointMap.clear(); }); }, ), Divider(), Text( "Sending Data", ), ElevatedButton( child: Text("Send Random Bytes Payload"), onPressed: () async { endpointMap.forEach((key, value) { String a = Random().nextInt(100).toString(); showSnackbar("Sending $a to ${value.endpointName}, id: $key"); Nearby() .sendBytesPayload(key, Uint8List.fromList(a.codeUnits)); }); }, ), ElevatedButton( child: Text("Send File Payload"), onPressed: () async { PickedFile? file = await ImagePicker().getImage(source: ImageSource.gallery); if (file == null) return; for (MapEntry m in endpointMap.entries) { int payloadId = await Nearby().sendFilePayload(m.key, file.path); showSnackbar("Sending file to ${m.key}"); Nearby().sendBytesPayload( m.key, Uint8List.fromList( "$payloadId:${file.path.split('/').last}".codeUnits)); } }, ), ], ), ), ); } void showSnackbar(dynamic a) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(a.toString()), )); } /// Called upon Connection request (on both devices) /// Both need to accept connection to start sending/receiving void onConnectionInit(String id, ConnectionInfo info) { showModalBottomSheet( context: context, builder: (builder) { return Center( child: Column( children: [ Text("id: " + id), Text("Token: " + info.authenticationToken), Text("Name" + info.endpointName), Text("Incoming: " + info.isIncomingConnection.toString()), ElevatedButton( child: Text("Accept Connection"), onPressed: () { Navigator.pop(context); setState(() { endpointMap[id] = info; }); Nearby().acceptConnection( id, onPayLoadRecieved: (endid, payload) async { if (payload.type == PayloadType.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 doesn't 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) { if (payloadTransferUpdate.status == PayloadStatus.IN_PROGRESS) { print(payloadTransferUpdate.bytesTransferred); } else if (payloadTransferUpdate.status == PayloadStatus.FAILURE) { print("failed"); showSnackbar(endid + ": FAILED to transfer file"); } else if (payloadTransferUpdate.status == PayloadStatus.SUCCESS) { showSnackbar( "$endid success, total bytes = ${payloadTransferUpdate.totalBytes}"); 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] = ""; } } }, ); }, ), ElevatedButton( child: Text("Reject Connection"), onPressed: () async { Navigator.pop(context); try { await Nearby().rejectConnection(id); } catch (e) { showSnackbar(e); } }, ), ], ), ); }, ); } }