File Transfer not working smack 4.1 android

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

Currently I am playing around with the new Smack 4.1 that offers full support for android. Sending and receiving messages is no problem, works fine. But now, I get stuck on sending and receiving Files. For example:

Send File

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

Receive files

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

The error code I get from Smack:

error 503 - service unavailable

  1. What could be the cause of this problem?
  2. Could it be because I have to change the Port?
  3. How to change the port of an existing connection in smack?
  4. Any alternatives to file transport?

My normal port is 5222, that works fine to send messages. I hope someone get it work and can lead me to the right directions....thanks for helping!

SOLUTION

For all who are interested: Devendra Singhs answer is correct, with a little note by myself. It seems to be important, which resource is used. From mobile to mobile, You have to use "mobile". Wether "Smack" nor any other resource identifier would work here. So it is important to initialize the OutgoingFileTransfer correctly like this:

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

回答1:

I got it after very research.

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

the one connection is sending file and another connection is receiving this is working code.



回答2:

I had same problem, I investigated the stanza and solved it this way.

Many people use "/Smack" or "/Resource" as resource part in jid, but that can be done another way.

Resource path is changing with every presence changed of user. Lets say we want to send image to this user: "user1@mydomain"

You must add "/Resource" or "/Smack" part to this jid and it become this: user1@mydomain/Resource

But resource path is changing with presence so you must follow every presence change to update resource path. Best way is to get user presence is in roster listener and in presencheChanged() method you get last user resource part like this:

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

Resource string will be some generated string like "6u1613j3kv" and jid will become: user1@mydomain/6u1613j3kv

That means that you must create your outgoing transfer like this:

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

In your case this resource part is "mobile". Just change it with resource part from presence in roster listener.

And that is how i have solved my problem with file transfer on smack and Openfire.

Also to mention you must add following properties in your Openfire server:

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

Just to mention, I am using Openfire 4.0.2 and Smack 4.2.2.

Also this can be configured the easy way, just set the resource on

XMPPTCPConnectionConfiguration.Builder .

like

XMPPTCPConnectionConfiguration.Builder configurationBuilder =  XMPPTCPConnectionConfiguration.builder();   configurationBuilder.setResource("yourResourceName"); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!