Android 谷歌附近连接:文件交换不传输整个文件

Android 谷歌附近连接:文件交换不传输整个文件,android,google-nearby,Android,Google Nearby,我正在尝试使用附近的连接和P2P_STAR策略来实现文件传输,“辐射”将视频文件发送到“中心” 使用示例,我将filenameMessage作为字节负载和文件负载发送。接收方使用SimpleArrayMaps存储文件名、传入和完成的有效载荷,以便稍后重命名文件。目标是android:requestLegacyExternalStorage=“true”,因为Uri=filePayload.asFile().asUri()正在使用一种我认为尚未实现的方法 发送消息可以很好地工作,但当涉及到文件传输

我正在尝试使用附近的连接和P2P_STAR策略来实现文件传输,“辐射”将视频文件发送到“中心”

使用示例,我将filenameMessage作为字节负载和文件负载发送。接收方使用SimpleArrayMaps存储文件名、传入和完成的有效载荷,以便稍后重命名文件。目标是android:requestLegacyExternalStorage=“true”,因为
Uri=filePayload.asFile().asUri()正在使用一种我认为尚未实现的方法

发送消息可以很好地工作,但当涉及到文件传输时,只有一部分被传输。例如,我有一个大约24MB的视频,下载/附近文件夹中传输的文件是17MB,我等了很多分钟。其他时候,传输的文件只有几KB

我的代码,一个活动应用程序(设备为spoke或hub):

public void sendMessage(字符串endpointId,字符串msg){
if(endpointId!=null){
//将消息转换为字节
byte[]bytes=msg.getBytes(StandardCharsets.UTF_8);
//生成有效负载并将其发送到目标
Payload bytesPayload=Payload.fromBytes(字节);
getConnectionsClient(context).sendPayload(endpointId,bytesPayload);
}
}
私有PayloadCallback PayloadCallback=新的PayloadCallback(){
私有SimpleArrayMap incomingFilePayloads=新SimpleArrayMap();
私有SimpleArrayMap completedFilePayloads=新SimpleArrayMap();
私有SimpleArrayMap文件PayloadFileNames=新SimpleArrayMap();
@凌驾
onPayloadReceived上的公共无效(@NonNull字符串endpointId,@NonNull有效负载){
if(payload.getType()==payload.Type.BYTES){
//将有效负载从字节转换为字符串
String msg=新字符串(payload.asBytes(),StandardCharsets.UTF_8);
//检查是否是文件名字节负载
String[]parts=msg.split(“:”);
如果(部分[0]。等于(“文件名”)){
msg=零件[0];
}
开关(msg){
//其他情况。。。
案例“创建视频”:
//这里创建的视频
发送记录(endpointId);
打破
案例“文件名”:
long payloadId=long.parseLong(第[1]部分);
字符串filename=“视频”+部件[2]+“.mp4”;
filePayloadFilenames.put(payloadId,filename);
processFilePayload(payload.getId());
打破
}
}否则{
if(payload.getType()==payload.Type.FILE)
incomingFilePayloads.put(payload.getId(),payload);
}
}
@凌驾
PayloadTransferUpdate上的公共无效(@NonNull字符串endpointId,@NonNull PayloadTransferUpdate PayloadTransferUpdate){
if(payloadTransferUpdate.getStatus()==payloadTransferUpdate.Status.SUCCESS){
long payloadId=payloadTransferUpdate.getPayloadId();
有效载荷=incomingFilePayloads.remove(payloadId);
//总是空的?
如果(有效负载!=null){
completedFilePayloads.put(payloadId,payloads);
if(payload.getType()==payload.Type.FILE){
processFilePayload(payloadId);
}
}
}
}
私有void processFilePayload(长payloadId){
Payload filePayload=completedFilePayloads.get(payloadId);
字符串filename=filePayloadFilenames.get(payloadId);
if(filePayload!=null&&filename!=null){
completedFilePayloads.remove(payloadId);
filePayloadFilenames.remove(payloadId);
File payloadFile=filePayload.asFile().asJavaFile();
重命名为(新文件(payloadFile.getParentFile(),filename));
}
}
};
私有void sendRecording(字符串端点ID){
//uri在我首先创建文件时保存
Uri=Utils.getUriSavedVideo();
有效载荷videoPayload=null;
试一试{
ParcelFileDescriptor视频=getContentResolver().openFileDescriptor(uri,“r”);
videoPayload=Payload.fromFile(视频);
字符串filenameMsg=“filename”+:“+videoPayload.getId()+”:“+Utils.getTimeStampString();
sendMessage(endpointId,filenameMsg);
getConnectionsClient(context).sendPayload(endpointId,videoPayload);
}catch(filenotfounde异常){
e、 printStackTrace();
}
}
我注意到,在onPayloadTransferUpdate方法中,当从incomingFilePayload检索有效负载时,有效负载始终为null,但payloadId被插入onPayloadReceived payload.Type.FILE中的incomingFilePayload中。但是,此部分仅与重命名文件相关,手动重命名文件无效,因为视频文件不完整


由于至少传输了文件的一部分,这可能与设备本身有关吗?连接仍然存在,我仍然可以发送其他消息。我认为STAR策略可以在短时间内发送小视频。

乍一看,代码看起来是正确的。您可以为标签“NearbyConnections”附加logcat日志吗?它应该更详细地说明这个有效负载发生了什么。@xlyth我在几周后再次尝试了这段代码,现在它似乎可以工作,但速度非常慢(一个测试在10分钟内完成了10MB)。设备只断开了一次连接,但不幸的是我没有检查日志。我想在那里
    public void sendMessage(String endpointId, String msg) {

        if (endpointId != null) {
            // Convert the message to Bytes
            byte[] bytes = msg.getBytes(StandardCharsets.UTF_8);
            // Generate payload and send it to destination
            Payload bytesPayload = Payload.fromBytes(bytes);
            Nearby.getConnectionsClient(context).sendPayload(endpointId, bytesPayload);
        }
    }

    private PayloadCallback payloadCallback = new PayloadCallback() {

        private SimpleArrayMap<Long, Payload> incomingFilePayloads = new SimpleArrayMap<>();
        private SimpleArrayMap<Long, Payload> completedFilePayloads = new SimpleArrayMap<>();
        private SimpleArrayMap<Long, String> filePayloadFilenames = new SimpleArrayMap<>();

        @Override
        public void onPayloadReceived(@NonNull String endpointId, @NonNull Payload payload) {

            if (payload.getType() == Payload.Type.BYTES) {

                // Convert the payload from Bytes to a String
                String msg = new String(payload.asBytes(), StandardCharsets.UTF_8);
                // Check if it's the filename bytes payload
                String[] parts = msg.split(":");
                if (parts[0].equals("filename")) {
                    msg = parts[0];
                }
                switch (msg) {

                    // OTHER CASES...

                    case "create_video":

                        //Video created here
                        sendRecording(endpointId);
                        break;

                    case "filename":

                        long payloadId = Long.parseLong(parts[1]);
                        String filename = "video_" + parts[2] + ".mp4";
                        filePayloadFilenames.put(payloadId, filename);
                        processFilePayload(payload.getId());
                        break;

                }

            } else {

                if (payload.getType() == Payload.Type.FILE)
                    incomingFilePayloads.put(payload.getId(), payload);
            }
        }

        @Override
        public void onPayloadTransferUpdate(@NonNull String endpointId, @NonNull PayloadTransferUpdate payloadTransferUpdate) {

            if (payloadTransferUpdate.getStatus() == PayloadTransferUpdate.Status.SUCCESS) {
                long payloadId = payloadTransferUpdate.getPayloadId();
                Payload payload = incomingFilePayloads.remove(payloadId);

                // ALWAYS NULL?
                if (payload != null) {
                    completedFilePayloads.put(payloadId, payload);
                    if (payload.getType() == Payload.Type.FILE) {
                        processFilePayload(payloadId);
                    }
                }
            }

        }

        private void processFilePayload(long payloadId) {
            Payload filePayload = completedFilePayloads.get(payloadId);
            String filename = filePayloadFilenames.get(payloadId);
            if (filePayload != null && filename != null) {
                completedFilePayloads.remove(payloadId);
                filePayloadFilenames.remove(payloadId);

                File payloadFile = filePayload.asFile().asJavaFile();
                payloadFile.renameTo(new File(payloadFile.getParentFile(), filename));
            }
        }

    };
    

    private void sendRecording(String endpointId) {
        // The uri is saved when I create the file in the first place
        Uri uri = Utils.getUriSavedVideo();
        Payload videoPayload = null;
        try {
            ParcelFileDescriptor video = getContentResolver().openFileDescriptor(uri, "r");
            videoPayload = Payload.fromFile(video);
            String filenameMsg = "filename" + ":" + videoPayload.getId() + ":" + Utils.getTimeStampString();

            sendMessage(endpointId, filenameMsg);
            Nearby.getConnectionsClient(context).sendPayload(endpointId, videoPayload);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }