diff --git a/android/src/main/java/com/pkmnapps/nearby_connections/NearbyConnectionsPlugin.java b/android/src/main/java/com/pkmnapps/nearby_connections/NearbyConnectionsPlugin.java index 8fd4ec5..cceb1d7 100644 --- a/android/src/main/java/com/pkmnapps/nearby_connections/NearbyConnectionsPlugin.java +++ b/android/src/main/java/com/pkmnapps/nearby_connections/NearbyConnectionsPlugin.java @@ -3,6 +3,8 @@ package com.pkmnapps.nearby_connections; import android.Manifest; import android.app.Activity; import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.ParcelFileDescriptor; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; @@ -23,6 +25,8 @@ import com.google.android.gms.nearby.connection.Strategy; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; +import java.io.File; +import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Map; @@ -221,6 +225,27 @@ public class NearbyConnectionsPlugin implements MethodCallHandler { result.success(true); break; } + case "sendFilePayload": { + String endpointId = (String) call.argument("endpointId"); + String filePath = (String) call.argument("filePath"); + + assert endpointId != null; + assert filePath != null; + + try { + File file = new File(filePath); + + Payload filePayload = Payload.fromFile(file); + Nearby.getConnectionsClient(activity).sendPayload(endpointId, filePayload); + Log.d("NearbyCon java", "sentFilePayload"); + result.success(filePayload.getId()); //return payload id to dart + } catch (FileNotFoundException e) { + Log.e("NearbyCon java", "File not found", e); + result.error("Failure", "File Not found", null); + return; + } + break; + } default: result.notImplemented(); } @@ -326,15 +351,31 @@ public class NearbyConnectionsPlugin implements MethodCallHandler { Log.d("NearbyCon java", "onPayloadReceived"); Map args = new HashMap<>(); args.put("endpointId", endpointId); - byte[] bytes = payload.asBytes(); - assert bytes != null; - args.put("bytes", bytes); + args.put("payloadId", payload.getId()); + args.put("type", payload.getType()); + + if (payload.getType() == Payload.Type.BYTES) { + byte[] bytes = payload.asBytes(); + assert bytes != null; + args.put("bytes", bytes); + } + channel.invokeMethod("onPayloadReceived", args); } @Override - public void onPayloadTransferUpdate(@NonNull String s, @NonNull PayloadTransferUpdate payloadTransferUpdate) { + public void onPayloadTransferUpdate(@NonNull String endpointId, @NonNull PayloadTransferUpdate payloadTransferUpdate) { //required for files and streams + + Log.d("NearbyCon java", "onPayloadTransferUpdate"); + Map args = new HashMap<>(); + args.put("endpointId", endpointId); + args.put("payloadId", payloadTransferUpdate.getPayloadId()); + args.put("status", payloadTransferUpdate.getStatus()); + args.put("bytesTransferred", payloadTransferUpdate.getBytesTransferred()); + args.put("totalBytes", payloadTransferUpdate.getTotalBytes()); + + channel.invokeMethod("onPayloadTransferUpdate", args); } }; diff --git a/example/lib/main.dart b/example/lib/main.dart index e44db47..792446f 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -190,7 +190,7 @@ class _MyBodyState extends State { cId = id; Nearby().acceptConnection( id, - onPayLoadRecieved: (endid, bytes) { + onPayLoadRecieved: (endid, bytes, payloadType) { showSnackbar(endid + ": " + String.fromCharCodes(bytes)); }, ); diff --git a/lib/nearby_connections.dart b/lib/nearby_connections.dart index 12a0548..6282d68 100644 --- a/lib/nearby_connections.dart +++ b/lib/nearby_connections.dart @@ -5,13 +5,14 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; /// **P2P_CLUSTER** - best for small payloads and multiplayer games -/// +/// /// **P2P_STAR** - best for medium payloads, higher bandwidth than cluster -/// +/// /// **P2P_POINT_TO_POINT** - single connection, very high bandwidth enum Strategy { P2P_CLUSTER, P2P_STAR, P2P_POINT_TO_POINT } enum Status { CONNECTED, REJECTED, ERROR } - +enum PayloadStatus { NONE, SUCCESS, FAILURE, IN_PROGRRESS, CANCELED } +enum PayloadType { NONE, BYTES, FILES, STREAM } typedef void OnConnctionInitiated( String endpointId, ConnectionInfo connectionInfo); typedef void OnConnectionResult(String endpointId, Status status); @@ -21,7 +22,22 @@ typedef void OnEndpointFound( String endpointId, String endpointName, String serviceId); typedef void OnEndpointLost(String endpointId); -typedef void OnPayloadReceived(String endpointId, Uint8List bytes); +/// For Bytes, this contains the bytes dala +/// +/// For File, this marks the start of transfer +/// +/// Uint8List bytes may be null, if [payloadType] is not [PayloadType.BYTES] +typedef void OnPayloadReceived( + String endpointId, Uint8List bytes, PayloadType payloadType); + +/// Called only once for Bytes and repeatedly for File until transfer is complete +typedef void OnPayloadTransferUpdate( + {String endpointId, + int payloadId, + PayloadStatus payloadStatus, + int bytesTransferred, + int totalBytes}); + // typedef void OnPayloadTransferUpdate(); /// The NearbyConnection class /// @@ -120,10 +136,26 @@ class Nearby { return null; case "onPayloadReceived": String endpointId = args['endpointId']; + int type = args['type']; Uint8List bytes = args['bytes']; - _onPayloadReceived?.call(endpointId, bytes); + _onPayloadReceived?.call(endpointId, bytes, PayloadType.values[type]); + break; + case "onPayloadTransferUpdate": + String endpointId = args['endpointId']; + int payloadId = args['payloadId']; + int success = args['success']; + int bytesTransferred = args['bytesTransferred']; + int totalBytes = args['totalBytes']; + + _onPayloadTransferUpdate?.call( + endpointId: endpointId, + payloadId: payloadId, + payloadStatus: PayloadStatus.values[success], + bytesTransferred: bytesTransferred, + totalBytes: totalBytes, + ); break; } return null; @@ -138,6 +170,7 @@ class Nearby { OnEndpointLost _onEndpointLost; OnPayloadReceived _onPayloadReceived; + OnPayloadTransferUpdate _onPayloadTransferUpdate; static const MethodChannel _channel = const MethodChannel('nearby_connections'); @@ -281,9 +314,10 @@ class Nearby { Future acceptConnection( String endpointId, { @required OnPayloadReceived onPayLoadRecieved, + OnPayloadTransferUpdate onPayloadTransferUpdate, }) async { this._onPayloadReceived = onPayLoadRecieved; - + this._onPayloadTransferUpdate = onPayloadTransferUpdate; return await _channel.invokeMethod( 'acceptConnection', { @@ -327,6 +361,23 @@ class Nearby { }, ); } + + /// Returns the payloadID as soon as file transfer has begun + /// + /// File is received in DOWNLOADS_DIRECTORY and is given a generic name + /// without extension + /// You must also send a bytes payload to send the filename and extension + /// so that receiver can rename the file accordingly + /// Send the payloadID and filename to receiver as bytes payload + Future sendFilePayload(String endpointId, String filePath) async { + return await _channel.invokeMethod( + 'sendFilePayload', + { + 'endpointId': endpointId, + 'filePath': filePath, + }, + ); + } } /// ConnectionInfo class