文件传输无法正常工作 smack 4.1 android

File Transfer not working smack 4.1 android

目前我正在使用新的 Smack 4.1,它完全支持 android。发送和接收消息没问题,工作正常。但是现在,我陷入了发送和接收文件的困境。例如:

发送文件

public void sendFile(String fileName,String to){

        if(transferManager==null) {
            transferManager = FileTransferManager.getInstanceFor(mConnection);

        }


        OutgoingFileTransfer transfer = transferManager.createOutgoingFileTransfer(to);

        try {

            transfer.sendFile(new File(fileName), "This is a Test!");
        } catch (SmackException e) {
            e.printStackTrace();
        }
    }

接收文件

 public void setReceiveFileListener(){


        if(transferManager==null) {
            transferManager = FileTransferManager.getInstanceFor(mConnection);
        }
        transferManager.addFileTransferListener(new FileTransferListener() {
            @Override
            public void fileTransferRequest(FileTransferRequest request) {
                IncomingFileTransfer transfer = request.accept();

                try {
                    File file = new File(Environment.getExternalStorageDirectory()  + File.separator +"TEST"+File.separator+ "new.txt");
                    transfer.recieveFile(file);

                } catch (SmackException | IOException e) {
                    e.printStackTrace();

                }
            }
        });

    }

在这种情况下,我只是发送了一个文本文件,并希望将其另存为 sd 卡中的新文本文件 "new.txt"。问题不在于文件本身,文件存在。此外,接收者 ID 是正确的,就像 "user@host.com/Smack" 一样。那是我可以成功发送普通消息的同一个接收器。

我从 Smack 得到的错误代码:

错误 503 - 服务不可用

这个错误响应是我在发送文件后直接从 smack 得到的,似乎文件没有传输,因为接收器监听器什么都不显示(我在发送和接收上都做了日志),但监听器肯定是注册的。 但我完全确定,服务器支持文件传输,它在他们的网站上声明 www.coderollers.com 。我在 SO 和 Smack 开发者社区中阅读了很多关于这里的问题。没有任何帮助,所以我的问题是:

  1. 这个问题可能是什么原因造成的?
  2. 难道是因为我必须更改端口?
  3. 如何在 smack 中更改现有连接的端口?
  4. 文件传输的任何替代方法?

我的正常端口是 5222,可以正常发送消息。我希望有人让它工作并能引导我走向正确的方向....感谢您的帮助!

解决方案

对于所有感兴趣的人:Devendra Singhs 的回答是正确的,我自己做了一点注释。使用哪种资源似乎很重要。从手机到手机,你得用"mobile"。 "Smack" 或任何其他资源标识符都不能在这里工作。所以像这样正确初始化 OutgoingFileTransfer 很重要:

        OutgoingFileTransfer oft = ftm1.createOutgoingFileTransfer
(XmppStringUtils.completeJidFrom(USER, SERV, "mobile"));//important resource "mobile"

研究了很久才搞定

FileTransferManager ftm1 = FileTransferManager.getInstanceFor(connection);
    FileTransferManager ftm2 = FileTransferManager.getInstanceFor(connection2);

    ftm2.addFileTransferListener(new FileTransferListener() {
        @Override
        public void fileTransferRequest(FileTransferRequest request) {
            IncomingFileTransfer ift = request.accept();
            try {
                InputStream is = ift.recieveFile();
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                int nRead;
                byte[] buf = new byte[1024];
                while ((nRead = is.read(buf,  0, buf.length)) != -1) {
                    os.write(buf, 0, nRead);
                }
                os.flush();
                dataReceived = os.toByteArray();
            } catch (SmackException | IOException | XMPPErrorException e) {
                e.printStackTrace();
            }
            if (Arrays.equals(dataToSend, dataReceived)) {
                System.out.println("Received data matches send data. \o/");
            } else {
                System.err.println("Recieved data DOES NOT match send data. :(");
            }
        }
    });

    OutgoingFileTransfer oft = ftm1.createOutgoingFileTransfer(XmppStringUtils.completeJidFrom(USER, SERV, "resourse"));
    oft.sendStream(new ByteArrayInputStream(dataToSend), "hello.txt", dataToSend.length, "A greeting");
    outerloop: while (!oft.isDone()) {
        switch (oft.getStatus()) {
        case error:
            System.out.println("Filetransfer error: " + oft.getError());
            break outerloop;
        default:
            System.out.println("Filetransfer status: " + oft.getStatus() + ". Progress: " + oft.getProgress());
            break;
        }
        Thread.sleep(1000);
    }

    connection.disconnect();
    connection2.disconnect();
    Thread.sleep(1000);
}

一个连接正在发送文件,另一个连接正在接收这是工作代码。

我遇到了同样的问题,我调查了节并以这种方式解决了它。

许多人使用 "/Smack" 或 "/Resource" 作为 jid 中的资源部分,但这可以通过其他方式完成.

资源路径随着用户的每次存在变化而变化。假设我们要将图像发送给该用户: "user1@mydomain"

您必须将“/Resource”或“/Smack”部分添加到此 jid,它会变成这样: user1@mydomain/Resource

但是资源路径会随着在线状态而变化,因此您必须跟随每次在线状态变化来更新资源路径。 最好的方法是让用户出现在花名册侦听器中,在 presencheChanged() 方法中,您可以获得最后一个用户资源部分,如下所示:

Roster roster=getRoster();
roster.addRosterListener(new RosterListener() {
                @Override
                public void entriesAdded(Collection<Jid> addresses) {
                    Log.d("entriesAdded", "ug");
                    context.sendBroadcast(new Intent("ENTRIES_ADDED"));
                }

                @Override
                public void entriesUpdated(Collection<Jid> addresses) {
                    Log.d("entriesUpdated", "ug");
                }

                @Override
                public void entriesDeleted(Collection<Jid> addresses) {
                    Log.d("entriesDeleted", "ug");
                }

                @Override
                public void presenceChanged(Presence presence) {
                    Log.d("presenceChanged", "ug");
                    //Resource from presence
                    String resource = presence.getFrom().getResourceOrEmpty().toString();
                    //Update resource part for user in DB or preferences
                    //...
                }
            });
}

资源字符串将是一些生成的字符串,如 "6u1613j3kv" 并且 jid 将变为: user1@mydomain/6u1613j3kv

这意味着您必须像这样创建传出转账:

EntityFullJid jid = JidCreate.entityFullFrom("user1@mydomain/6u1613j3kv"); 
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(jid)

在您的情况下,此资源部分是 "mobile"。只需用资源部分从名册侦听器中的存在更改它。

这就是我在 smack 和 Openfire 上解决文件传输问题的方法。

还要提一下,您必须在 Openfire 服务器中添加以下属性:

xmpp.proxy.enabled - true
xmpp.proxy.externalip - MY_IP_ADDRESS
xmpp.proxy.port -7777

顺便提一下,我使用的是 Openfire 4.0.2 和 Smack 4.2.2。

这也可以通过简单的方式配置,只需将资源设置为

XMPPTCPConnectionConfiguration.Builder .

喜欢

XMPPTCPConnectionConfiguration.Builder configurationBuilder = 
XMPPTCPConnectionConfiguration.builder(); 

configurationBuilder.setResource("yourResourceName");