文件传输不工作smack 4.1 android

时间:2015-07-13 08:15:34

标签: android file-transfer smack

目前我正在使用新的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. 文件传输的替代方法吗?
  5. 我的正常端口是5222,可以正常发送消息。我希望有人能够让它发挥作用并引导我走向正确的方向....感谢您的帮助!

    对于所有感兴趣的人:Devendra Singhs的回答是正确的,我自己也有一点注意事项。似乎重要的是,使用哪种资源。从移动设备到移动设备,您必须使用“mobile”。 Wether“Smack”或任何其他资源标识符都适用于此处。因此,正确初始化OutgoingFileTransfer非常重要:

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

2 个答案:

答案 0 :(得分:5)

我经过深入研究后得到了它。

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);
}

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

答案 1 :(得分:0)

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

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

资源路径随着用户的每次更改而变化。让我们说我们想要向这个用户发送图像: 的 “USER1 @ MYDOMAIN”

你必须在这个jid中添加“/ Resource”或“/ Smack”部分,它会变为: 的 USER1 @ MYDOMAIN /资源

但资源路径随着状态而变化,因此您必须遵循每个状态更改来更新资源路径。 最好的方法是让用户出现在名册监听器中,并在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)

在您的情况下,此资源部分是“移动”。只需使用资源部分从名册监听器中的状态进行更改即可。

这就是我在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");