File transfer in android with asmack and Openfire

I have seen many peoples struggling from file transfer in asmackAndroid build environment and patches for smack. I tried same library with Openfire server after some debugging got success in it. So I will like to share my problem and solution for it.  I found that the problem is in Byte Stream host, it tries to connect to wrong host for initiating file transfer using byte streams.  If you have not configured the file transfer proxy properly then it will choose 127.0.0.1 or localhost or any internally configured host/ip as a bytestream host, which in android is not considered as proper ip for communicating.  But wait then why it is working properly with desktop client with same server. The reason is desktop clients can easily identify this ips and can use it to open socket for file transfer.

The variable names used in following discussions are:

Name Meaning
myHost The hostname of machine on which Openfire is running.
user1@myHost File transfer initiator user
user2@myHost Recipient of file

How to know which host is chosen for byte streams: (Following XMLs are shown as they are sent and received to the file transfer initiator.)

  • First query other client for information about supported features:

Sent:

<iq id="x1ixz-13" to="user2@myHost/Smack" type="get">
   <query xmlns="http://jabber.org/protocol/disco#info"></query>
</iq>

Received:

<iq id="x1ixz-13" to="user1@myHost/Smack" type="result" from="user2@myHost/Smack">
   <query xmlns="http://jabber.org/protocol/disco#info">
      <!—some other items -->
      <feature var="http://jabber.org/protocol/bytestreams"/>
      <!—some other items -->
   </query>
</iq>

Here you can know that whether bytestream file transfer is supported on the client other side or not. If you see a xml like above in response then it’s supported on the other side and you can go further.

  • Query server for disco items:

Sent:

<iq id="x1ixz-14" to="myHost" type="get">
   <query xmlns="http://jabber.org/protocol/disco#items"></query>
</iq>

Received:

<iq type="result" id="x1ixz-14" from="myHost" to="user1@ myHost /Smack">
   <query xmlns="http://jabber.org/protocol/disco#items">
      <!—some other items -->
      <item jid="proxy. myHost " name="Socks 5 Bytestreams Proxy"/>
      <!—some other items -->
   </query>
</iq>

Here you will receive various items for different items supported by server like , file transfer proxy, search service, conference service… The item we should look for is ` Socks 5 Bytestreams Proxy `.

  • Request for more information on proxy

Sent:

<iq id="x1ixz-19" to="proxy. myHost " type="get">
   <query xmlns="http://jabber.org/protocol/bytestreams"/>
</iq>

Received:

<iq type="result" id="x1ixz-19" from="proxy. myHost "  to="user1@ myHost /Smack">
   <query xmlns="http://jabber.org/protocol/bytestreams">
      <streamhost jid="proxy. myHost " host=" myHost " port="7777"/>
   </query>
</iq>

Here the host in the <streamhost> is the key for the file transfer. You have to make sure that this host is accessible from your android phone. It should not be like localhost, 127.0.0.1 or any company’s internal configured server which is not accessible outside of the company. It must be a publicly accessible ip address or host.

To configure proper proxy add/change these 3 properties in Openfire:

  1. xmpp.proxy.enabled                – true
  2. xmpp.proxy.port                        – 7777
  3. xmpp.proxy.externalip            – [publicly accessible host or ip]

The code for file transfer:

FileTransferManager manager = new FileTransferManager(connection);
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer("usre2@myHost/Smack");
File file = new File(filenameWithPath);
try {
   transfer.sendFile(file, "test_file");
} catch (XMPPException e) {
   e.printStackTrace();
}
while(!transfer.isDone()) {
   if(transfer.getStatus().equals(Status.error)) {
      System.out.println("ERROR!!! " + transfer.getError());
   } else if (transfer.getStatus().equals(Status.cancelled)
                    || transfer.getStatus().equals(Status.refused)) {
      System.out.println("Cancelled!!! " + transfer.getError());
   }
   try {
      Thread.sleep(1000L);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
}
if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
 || transfer.getStatus().equals(Status.cancelled)){
   System.out.println("refused cancelled error " + transfer.getError());
} else {
   System.out.println("Success");
}

And the code for file receive:

FileTransferManager manager = new FileTransferManager(connection);
manager.addFileTransferListener(new FileTransferListener() {
   public void fileTransferRequest(final FileTransferRequest request) {
      new Thread(){
         @Override
         public void run() {
            IncomingFileTransfer transfer = request.accept();
            File mf = Environment.getExternalStorageDirectory();
            File file = new File(mf.getAbsoluteFile()+"/DCIM/Camera/" + transfer.getFileName());
            try{
                transfer.recieveFile(file);
                while(!transfer.isDone()) {
                   try{
                      Thread.sleep(1000L);
                   }catch (Exception e) {
                      Log.e("", e.getMessage());
                   }
                   if(transfer.getStatus().equals(Status.error)) {
                      Log.e("ERROR!!! ", transfer.getError() + "");
                   }
                   if(transfer.getException() != null) {
                      transfer.getException().printStackTrace();
                   }
                }
             }catch (Exception e) {
                Log.e("", e.getMessage());
            }
         };
       }.start();
    }
 });

Also configure ProviderManager to properly decode/parse bytestreams and other required xmls:

ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());

The asmack library I used was asmack-jse-buddycloud.jar.

Let me know your feedbacks and if you have configured all things well and still face the issue the please drop a comment on this post; I will try my best to help you.  🙂

122 thoughts on “File transfer in android with asmack and Openfire

  1. Thank you for this article. I’ve been trying to implement file transer unsuccesfully. Unfortunately, your suggestions still did not solve my problem, which despite all the efforts is always the same. “Service-unavailable” when sending files and no errors, but not transfer (progress on the other side doesn’t increase). I’m testing on android and spark as other client, on an external openfire server (accessible without problems). I’m really not getting where the problem lies. If you have anymore suggestions…please, they are more then welcomed!

    1. Hi Ewix,

      As far as I know (503) service unavailable means the server you are using does not support the implementation of the feature you are trying to use. Check and verify that your smack and server are using same version of specification for file transfer. It can be possible that your server supports file transfer but specification it uses is different or of different version than you have in smack.

      1. actually the problem was a different one: I was not getting the resource name of the sender correctly (the /Spark 2.6.3 for instance): once I corrected that the file got sent without any problems from android to Spark. Not I still have the issue of receiving files: the listener fires, the path on the sdcard is correct but I always only get a 0byte file

            1. I have tried the same but not able to transfer file. Login and messaging works fine though.
              Every time I am sending file at other side (spark). File progress is 0 and stopped in some seconds.
              And android side it is just negotiating stream progress : 0.0

              Here is my sending file code

              ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
              ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
              ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
              ProviderManager.getInstance().addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());
              					
              ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
              if (sdm == null)
                  sdm = new ServiceDiscoveryManager(connection);
              			
              sdm.addFeature("http://jabber.org/protocol/disco#info");
              sdm.addFeature("http://jabber.org/protocol/disco#item");
              sdm.addFeature("jabber:iq:privacy");
              					
              FileTransferManager manager = new FileTransferManager(connection);
              FileTransferNegotiator.setServiceEnabled(connection, true);
              OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(user2destination);	//Watch Out!!..
              File extStore = Environment.getExternalStorageDirectory();
              			
              File file = new File(extStore.getAbsolutePath()+"/finalscope.txt");
              				
              long length = file.length();
              try {
                 transfer.sendFile(file, "test_file");
              } catch (XMPPException e) {
                 e.printStackTrace();
              }
              while(!transfer.isDone()) {
                 if(transfer.getStatus().equals(Status.error)) {
                    System.out.println("ERROR!!! " + transfer.getError());
                 } else if (transfer.getStatus().equals(Status.cancelled)
                                  || transfer.getStatus().equals(Status.refused)) {
                   System.out.println("Cancelled!!! " + transfer.getError());
                 }
              try {
                    Thread.sleep(1000L);
              			      
                    Log.i("transfer file", "sending file status :- " + transfer.getStatus() + " "
                              + "progress:-" + transfer.getProgress());
              					      
              } catch (InterruptedException e) {
                    e.printStackTrace();
              }
              }
              if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
              		 || transfer.getStatus().equals(Status.cancelled)){
                 System.out.println("refused cancelled error " + transfer.getError());
              } else {
                 System.out.println("Success");
              }
              
            1. Hi Sravani,

              First of all Ewix will not get notified this way unless and until if visits this site very often, as this is not his site. (This is second time I’m writing this, may be ewix is getting more famous than in me in my site and I should invite him as an admin to the site 😛 )

              And second, as answer to your question, I have used asmack-jse-buddycloud.jar and latest open fire server.

              Thanks & Regards.

    2. Hello,
      i am getting error:503 while sending the file.log is as follows:

      04:17:16 AM RCV (1105550496): test_filehttp://jabber.org/protocol/bytestreamshttp://jabber.org/protocol/ibb

    1. Hi Gaurav,

      First of all Ewix will not get notified this way unless and until if visits this site very often, as this is not his site.

      Second thing about your problem of adding friends, it seems like you have not changed the Subscription mode in roster. Change it to manual and you will get the notification. To change the subscription mode do as follows:

      roster.setSubscriptionMode(Roster.SubscriptionMode.manual);
      

      And then you will receive Presence packets for add requests which will have type equal to Subscribe. To listen to this presence you can either add packet listener to connection with packet type filter for Presence class or you can add roster listener and listen this in its presenceChanged method.

  2. Hello harry joy,
    Actually I tried what u said and deleted my code 😦 Can you please help me by taking the code example for how can I send one notification that so and so friend wants to add you or have added. Please reply me bro. I am in big problem and wants to solve it fast.
    Thanks very much for the reply bro

    1. Hi Gaurav,

      Here are some code highlights to help you better:

      1. Set subscription mode for roster request to manual after you successfully get logged in

      //---- after successful login
      roster.setSubscriptionMode(Roster.SubscriptionMode.manual);
      

      2. Now to add a roster you have to send a Presence packet with type equal to Subscribe. For this you can use Roster class’ createEntry method.

      roster.createEntry(userId, "userAlias", new String[]{"userGroup"});
      

      3. As I said in previous comment you can listen to this event by adding a packet listener to connection with PacketFilter of Presence class.

      connection.addPacketListener(new PacketListener() {
         @Override
         public void processPacket(Packet packet) {
            // here you have to check if request is for adding a buddy or just simple presence change event
            Presence pres = (Presence) pack;
            if (pres.getType().equals(Presence.Type.subscribe)) {
               // request handling code will go here.
               // here you have to show a notification to the user that someone is trying to add you in 
      his buddy list
               // you can get the jid of user who is trying to add you as pres.getFrom();
            }
         }
        }, new PacketTypeFilter(Presence.class));
      

      This is it! 🙂 Hope this helps you.

      1. Hello,
        Now I understand what you are saying but actually when I debugged the code I saw that the debugger actually doesn’t comes in the process packet part. What’s the error can you please tell me?
        😦
        Here is my code

        if (!roster.contains(idExtension)) {
        try {
           roster.setSubscriptionMode(Roster.SubscriptionMode.manual);
           roster.createEntry(idExtension, nickname, null);
           /*Presence subscribe = new Presence(Presence.Type.subscribe);
           subscribe.setTo(idExtension);				
           connection.sendPacket(subscribe);	*/
           connection.addPacketListener(new PacketListener() {
           @Override
           public void processPacket(Packet arg0) {
              Presence presence = (Presence)pac;
              if(presence.getType().equals(Presence.Type.subscribe)){
                  System.out.println("Hello Worlddddddddddddddddddd");
              }
           }
        },new PacketTypeFilter(Presence.class));
        
        1. Hi Gaurav,

          Make sure you are checking it with the correct user id. It will go in this listener method for the user to whom you are sending the request, in your case ‘idExtension’ is the user who will receive the the request packet in processPacket method. It will not go inside the method at the initiator side means from which you are sending the request.

          Regards.

          1. Hi bro,
            Its all rite at our end but the code is not executing at all ( the process packet one)

            Can you please help ??

            1. Hi,

              This is the small example I can come up with to make you understand what I’m saying. Run this class and you will understand what I am trying to say.

              import java.awt.EventQueue;
              import java.awt.FlowLayout;
              import java.awt.event.ActionEvent;
              import java.awt.event.ActionListener;
              
              import javax.swing.JButton;
              import javax.swing.JFrame;
              import javax.swing.JOptionPane;
              
              import org.jivesoftware.smack.ConnectionConfiguration;
              import org.jivesoftware.smack.PacketListener;
              import org.jivesoftware.smack.Roster;
              import org.jivesoftware.smack.XMPPConnection;
              import org.jivesoftware.smack.XMPPException;
              import org.jivesoftware.smack.filter.PacketTypeFilter;
              import org.jivesoftware.smack.packet.Packet;
              import org.jivesoftware.smack.packet.Presence;
              
              public class AddRoster {
              	private static final String host = "myHost"; 
              	private static final int port = 5222; 
              	private static final String user_1_id = "user1"; // request initiator user
              	private static final String user_1_pass = "password"; 
              	private static final String user_2_id = "user2"; // request receiver user
              	private static final String user_2_pass = "password"; 
              	public static void main(String[] args) {
              		EventQueue.invokeLater(new Runnable() {
              			@Override
              			public void run() {
              				JFrame frame = new JFrame("Add user");
              				frame.setLayout(new FlowLayout(FlowLayout.CENTER));
              				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              				JButton button = new JButton("Add user in my list");
              				button.addActionListener(new ActionListener() {
              					@Override
              					public void actionPerformed(ActionEvent e) {
              						ConnectionConfiguration configuration = new ConnectionConfiguration(host, port);
              						XMPPConnection connection = new XMPPConnection(configuration);
              						try {
              							connection.connect();
              							connection.login(user_1_id, user_1_pass);
              							connection.getRoster().setSubscriptionMode(Roster.SubscriptionMode.manual);
              							connection.getRoster().createEntry(user_2_id + "@" + host, "add user test", new String[]{"Default"});
              						} catch (XMPPException e1) {
              							e1.printStackTrace();
              						}
              					}
              				});
              				frame.add(button);
              				frame.setSize(200, 200);
              				frame.setVisible(true);
              
              				final JFrame frame2 = new JFrame("Listen to add user request");
              				frame2.setLayout(new FlowLayout(FlowLayout.CENTER));
              				frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              				JButton button2 = new JButton("Start listening to events");
              				button2.addActionListener(new ActionListener() {
              					@Override
              					public void actionPerformed(ActionEvent e) {
              						ConnectionConfiguration configuration = new ConnectionConfiguration(host, port);
              						XMPPConnection connection = new XMPPConnection(configuration);
              						try {
              							connection.connect();
              							connection.login(user_2_id, user_2_pass);
              							connection.getRoster().setSubscriptionMode(Roster.SubscriptionMode.manual);
              							connection.addPacketListener(new PacketListener() {
              								@Override
              								public void processPacket(Packet packet) {
              									Presence presence = (Presence) packet;
              									if (presence.getType().equals(Presence.Type.subscribe))
              										JOptionPane.showMessageDialog(frame2, "New buddy request from: " + presence.getFrom());
              								}
              							}, new PacketTypeFilter(Presence.class));
              							System.out.println("Started listening to events");
              						} catch (XMPPException e1) {
              							e1.printStackTrace();
              						}
              					}
              				});
              				frame2.add(button2);
              				frame2.setSize(200, 200);
              				frame2.setVisible(true);
              			}
              		});
              	}
              }
              

              Before running this change the private variables with appropriate values. Then when you run the class, first click on “Start listening to events” button. And when you see “Started listening to events” on console, click on “Add user in my list” button. Once it runs successfully, you can use relevant code part in your application.

              1. Thanks Harry, I was able to achieve the same by some other means. Its ok now no problem.
                Harry, but now I am facing a problem when I chat with my friend, me and my friend have to be on same chatting screen then only we receive each others message. How can I send a notification to my friend if he is not on the same chat screen or he is working on any other screen??

                1. Hi Gaurav,

                  Sorry but this is not a QA forum where I will answer all your questions or help you build your app. Please ask such questions on some QA site. Anyways as a hint what you do is run a packet listener of message class in a service in its process method check for sender and check if it is same to which you are currently chatting or not. If not then show a notification.

                  Regards,
                  Harsh raval.

  3. Harry,

    I am implementing File Transfer in my application and I am getting null pointer exception on this line:
    FileTransferManager ftm = new FileTransferManager(connection);

    now after studying the solution from the stackoverflow, now I have added one more line with it as :

    new ServiceDiscoveryManager(connection);

    FileTransferManager ftm = new FileTransferManager(connection);

    Now no force close is coming but my code is not working also.

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == LOAD_IMAGE_GALLERY && resultCode == RESULT_OK && null != data) {
    Uri selectedImage = data.getData();
    String[] filePathColumn = { MediaStore.Images.Media.DATA };

    Cursor cursor = getContentResolver().query(selectedImage,
    filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    String picturePath = cursor.getString(columnIndex);
    cursor.close();

    System.out.println(“Path Of the Image “+picturePath);

    new ServiceDiscoveryManager(connection);

    FileTransferManager ftm = new FileTransferManager(connection);
    OutgoingFileTransfer transfer = ftm.createOutgoingFileTransfer(“abc@hostname.com/Smack”);
    File file = new File(picturePath);

    try {
    transfer.sendFile(file, “test_file”);
    Toast.makeText(getApplicationContext(), “Sending file..”, Toast.LENGTH_SHORT).show();

    } catch (XMPPException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    while(!transfer.isDone()){

    if(transfer.getStatus().equals(Status.error)){

    System.out.println(“Error!!”+transfer.getError());

    }
    else if (transfer.getStatus().equals(Status.cancelled)||transfer.getStatus().equals(Status.refused)){
    System.out.println(“Cancelled/Refused”+transfer.getError());
    }

    try {
    Thread.sleep(1000L);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    }

    }

    }

    Please reply if you can.

      1. Hi harry,
        I want to tell you the thing that when I click on the photo nothing happens ( no force close ) no error. and when I debugged the app I saw that the cursor is not even coming on the line FileTranfer ftm… and directly moves the last line i.e Toast – Sending File..

        Thanks

        Please help me

  4. Hi Harryjoy,

    Thanks for such nice tutorial. I am struggling with same issue of file transfer and finally i got your blog.I am going to follow your steps but at first step my question is where do i find those xml files ?

    Thanks

    1. Hi,

      Xml shown here is not a part of any file. They are xml presentation of packets transferred between client and server. If you are using asmack then enable debug option in code and you will see such xml in logs.

      Regards.

      1. Hi Thanks for reply i got this error while running the project.

        10-31 10:40:50.528: E/AndroidRuntime(25546): FATAL EXCEPTION: main
        10-31 10:40:50.528: E/AndroidRuntime(25546): java.lang.VerifyError: org.jivesoftware.smack.sasl.SASLMechanism
        10-31 10:40:50.528: E/AndroidRuntime(25546): at java.lang.Class.getDeclaredConstructors(Native Method)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at java.lang.Class.getConstructor(Class.java:472)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:303)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at org.sipchat.sipua.ui.SettingsDialog.(SettingsDialog.java:89)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at org.sipchat.sipua.ui.XMPPClient.onCreate(XMPPClient.java:230)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.os.Handler.dispatchMessage(Handler.java:99)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.os.Looper.loop(Looper.java:123)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at android.app.ActivityThread.main(ActivityThread.java:3683)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at java.lang.reflect.Method.invokeNative(Native Method)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at java.lang.reflect.Method.invoke(Method.java:507)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
        10-31 10:40:50.528: E/AndroidRuntime(25546): at dalvik.system.NativeStart.main(Native Method)

        1. i am using smack api, should i use i asmack?? if yes then please provice me relevant link. i want to get it working any how

          Thanks

          1. It depends on platform you are developing the application for. If you are developing android application then use asmack else for developing desktop and web app use smack. Regarding links for the jar, you can easily search this jar files on internet. Just Google it.

            Best Regards.

            1. Hi Harryjoy,

              I tried to do file transfer but still i am getting a error. My application is crashes on this line

              FileTransferManager manager = new FileTransferManager(connection);

              And yeah now i am using asmack-jse-buddycloud-2010.12.11.jar. Messages are fine but application crashes on above line, here is my code

              http://pastie.org/5364412

              I am using this sampe chat tutorial

              http://davanum.wordpress.com/2008/12/29/updated-xmpp-client-for-android/

              Please help me on this and if i am on wrong direction.

              Thanks & Regards

            2. Hi Harryjoy,

              I tried to do file transfer but still i am getting a error. My application is crashes on this line

              FileTransferManager manager = new FileTransferManager(connection);

              And yeah now i am using asmack-jse-buddycloud-2010.12.11.jar. Messages are fine but application crashes on above line, here is my code

              http://pastie.org/5364412

              I am using this sampe chat tutorial

              http://davanum.wordpress.com/2008/12/29/updated-xmpp-client-for-android/

              Please help me on this and if i am on wrong direction.

              Thanks & Regards

                  1. You are using localhost.localdomain as host, which is not correct as I have mentioned in my post. Android does not identift localhost as a valid transfer host. Read my post once again and also check by using 2 desktop client, does file transfer works properly in desktop version? Also verify that your server supports file transfer.

                    1. Actually i am testing locally and initial chating is work fine, but i am not sure about server, i am using openfire server by the way. i guess its supports file transfer.

                      Thanks

  5. Hi Harryjoy,

    Thanks for such a nice tutoria. i am struggling with same issue of file transfer. I am going to follow this steps but my my question is where do i get those xml files?

    Thanks

  6. Harry,

    First of a good tutorial , i have not started implementing this yet but i have few questions which caught while i was looking through your code.

    1. As in basic normal file transfer in android apps, from app to server we need to compress the image a lot so that they don’t crash the app while transfer. Like new android mobiles take images which are at a size of more than 1mb or 2mb , if we transfer these files the app cant take the load and crashes out so we need to compress them a lot. My question is in the chat app do we need to compress the image in similar way before transferring or is it taken care by Openfire or XXMP?

    2. Can we use the same code for video upload ?

    3. Video sizes will be huge as i have seen in normal app we are able to upload videos below size of 1mb , video above 1mb crashes out.

    a. Can you tell me is it possible to upload above 1mb too here in chat app? .
    b. If yes is it that we need to compress the video and upload or not ?
    c. If video need to be compressed can you please help me on this how can this be done on android , if you have a sample or tutorial it would be great help for one of my other android apps too.

    Waiting to know more on these from you, please do reply.

    Thanks

    1. Hi Vinod,

      Answers are as follows:

      1) no you have to do it, openfire will not handle it..
      2) yes
      3) I’m not sure about how to compress the video, but you can find it online give a try.

      Thanks,

      1. Harry,

        Good the hear from you, thanks for your answers.

        Ok that means i need to do the byte compression at android app end and then send it across.

        I have tried searching around for compressing the video on android but couldn’t find anything useful still.

        One more question i got is that we cant test file transfer on emulator ? As i read through your post i got such an understanding , let me know am i right ?

        My chat app has MUC and File Transfer, if i use “asmack-jse-buddycloud.jar.” my MUC doens’t work because of some code issue and if i used the jar in which MUC works in that case file transfer throws null pointer error in the code for which we receive the file transferred. To fix this i followed this post and i got issue fixed with my old jar file

        http://community.igniterealtime.org/thread/41391.

        Just for anyone comes across this issue.

        1. Vinod,

          Yes you can test it on emulator. About using jar, in this post I have just shown way to do file transfer but yes one needs to configure other IQProvider and Extensions to work with other functionality of chat smoothly.

          Thanks.

    1. Hi Bala,

      It seems like your mobile network is not able to connect to file transfer host. Did you properly checked the host in file transfer? It should not be a host or ip that is not pingable from the mobile.

      Thanks and regards.

  7. Harry,

    I have a dedicated server on which openfire is installed and i am building an app. I am trying file transfer over it now.

    I have followed you blog and according to that i am able to connect from one user to other while transferring file but i am getting this following error.

    05-14 00:27:29.982: I/System.out(318): File Name Received/mnt/sdcard/DCIM/Camera/test.jpg
    05-14 00:27:29.982: E/(318): Could not create file to write too

    The file path building the file is as used as below

    File mf = Environment.getExternalStorageDirectory();File file = new File(mf.getAbsoluteFile()+”/DCIM/Camera/” + transfer.getFileName());

    I am testing file transfer from phone to emulator i.e from phone i choose photo and transfer to emulator.

    Can you tell me y i am not able to create a file to write too is it the file path issue or is it that i can create a file on emulator ?

    Thanks

    1. Hi Vinod,

      It seems like you have not given permission to write on external card. If not given then write following line in manifest:

      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      

      For more and better help, please provide full stack trace of the exception.

      Thanks.

      1. Harry

        I have already added these in my manifest

        Here the file it getting written to emulator storage not to the phone storage. Is this an issue ?

        Thanks

        1. Hi Vinod,

          Provide stack trace of the exception. When you get this exception, use “e.printStackTrace()” to print it’s stack trace. (Assuming e is the reference to the exception being caught.)

          Thanks.

    2. Hi Harry,

      Hen creating the AVD, ensure that you are setting a size to it – it is not done by default. Without that, no sdcard is created and you can not write to sdcard at all.

      BR,

    1. Harry,

      I was out of station so was not able to reply on this chain. I was able to sort out the issue, it was basically the file path, i was fetching image and compressing it while compressing the file path was changed as a temporary file on sdcard. This file path had to be same on the receiving user side too (this one i had a different one so it was not downloading the image).

      Ones i gave the same file path on receiver side it started transferring the image properly.

      I have one question, the to username in file transfer needs to be with “/Smack” resource. Now my app is being built on iphone too so i need to get the resource of the user how do i do this ? How can i get the resource of the receiving side user ?

      Thanks

      1. Hi Vinod,

        You can use getRequestor method of FileTransferRequest when you receive the file.

        public String getRequestor()

        This will return you the JID of the user who wants to transfer the file. This will be the user’s id with resource so you can have complete JID with resource that you can process. Or else to extract only resource from this JID, you can use StringUtils class’ parseResource(String XMPPAddress) method to get resource name out of it.

        And if you are talking about setting resource of logged in user then you can use login method of XMPPConnection class which takes 3 argument where 3rd argument is the resource name to be used for user.

        Regards.

  8. I just want to share. If you have problems both transfering or receiving file, maybe it caused by the RESOURCE of your friend is. For example, the code :

    OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(“user2@myHost/Smack”);

    “Smack” is your friend resource. So you have to change it with Fully JID, for example : user2@myHost/Spark 2.6.3

    Hopefully may solve your problems.

      1. The resource also helps me too. But I have problem in getting Roster/friend Resource. When roster/friend connected by using Spark, full JID will be “friend@host/Spark 2.63” for example.

        Maybe you have any solution in getting roster/fried resource.
        Thank you 🙂

        1. Hi,

          You can use StringUtils class from Smack jar. It has a method called parseResource(String XMPPAddress) which returns resource name from JID.

          Thanks.

  9. Hello harryjoy,
    i am follow your Link for File transfer with asmack and openfire,But getting problem:-
    Empty file is received on other device while transferring file one device to another,its show the 0KB size.i mean when i opened it,its shows blank screen.i do not know what’s the problem behind it,,Plzz help me…

    My code and Log files are Present on this link:
    http://stackoverflow.com/questions/17608424/file-transfer-show-file-size-0kb-while-transfering-file-using-smack-in-android

  10. Hey Dear Brother I am working with asmack but it is giving me a strange exception while sending a file. It works fine for the message sending but not allowing the file sending. Follwing is the code that I am trying.I am picking a file from sdCard. It is fine I have checked the file it exists and gives right path. Under the code I have also added the Log messages.

    if (resultCode == RESULT_OK)
    {
    Uri uri = data.getData();
    Log.d(“URI”, uri.toString());

    File nfile=new File(Environment.getExternalStorageDirectory().toString()+”/”+uri.toString());
    Log.v(“”, nfile.getAbsolutePath());
    // Create the outgoing file transfer
    FileTransferManager ftm = new FileTransferManager(
    connection);
    OutgoingFileTransfer transfer = ftm.createOutgoingFileTransfer(recipient.getText().toString());
    try {
    transfer.sendFile(nfile, “Hello Jigar”);

    } catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    catch (XMPPException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    08-13 14:01:42.260: D/URI(15466): file:///mnt/sdcard/c.v.pdf
    08-13 14:01:42.260: V/(15466): /mnt/sdcard/file:/mnt/sdcard/c.v.pdf
    08-13 14:01:42.310: W/System.err(15466): java.lang.IllegalArgumentException: Could not read file
    08-13 14:01:42.310: W/System.err(15466): at org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer.sendFile(OutgoingFileTransfer.java:206)
    08-13 14:01:42.310: W/System.err(15466): at com.swenggco.androidxmpp.ChatClient.onActivityResult(ChatClient.java:214)
    08-13 14:01:42.320: W/System.err(15466): at android.app.Activity.dispatchActivityResult(Activity.java:4740)
    08-13 14:01:42.320: W/System.err(15466): at android.app.ActivityThread.deliverResults(ActivityThread.java:3383)
    08-13 14:01:42.320: W/System.err(15466): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3437)
    08-13 14:01:42.320: W/System.err(15466): at android.app.ActivityThread.access$1100(ActivityThread.java:139)
    08-13 14:01:42.320: W/System.err(15466): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1291)
    08-13 14:01:42.320: W/System.err(15466): at android.os.Handler.dispatchMessage(Handler.java:99)
    08-13 14:01:42.320: W/System.err(15466): at android.os.Looper.loop(Looper.java:154)
    08-13 14:01:42.330: W/System.err(15466): at android.app.ActivityThread.main(ActivityThread.java:4945)
    08-13 14:01:42.330: W/System.err(15466): at java.lang.reflect.Method.invokeNative(Native Method)
    08-13 14:01:42.330: W/System.err(15466): at java.lang.reflect.Method.invoke(Method.java:511)
    08-13 14:01:42.330: W/System.err(15466): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    08-13 14:01:42.330: W/System.err(15466): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    08-13 14:01:42.330: W/System.err(15466): at dalvik.system.NativeStart.main(Native Method)

    Please Help me I will be very thankfull to you.

      1. Thanks for the response. Yes I have provided the permisions

        .
        Now I have changed the code a bit and now It always says request confused to accept file.
        I am currently using these parametters to make connection.

        ConnectionConfiguration connectionConfig = new ConnectionConfiguration(
        “talk4.l.google.com”, Integer.parseInt(“5222”), “gmail.com”);

        please help. Is it due to the service? Means is googletalk not allowing it or some thing else? Plus can we chat right now I can email you my code if you can help it will be really nice. Also, at which service I should test this if not google talk?

        Waiting for your kind response.

          1. Yes it could be due to the service, I’m not sure but google might not be providing this functionality. You should first try on your local machine by downloading and installing openfire.

        1. muhammad shahnawaz and harryjoy

          i also stuck in same problem “cannot read file” every after giving every permission..if you rid of the problem can you please tell me what changes you have done…

          if anyone successfully implemented file transfer ,may you please forward source code i tried all ways from last 1 week (pramod_7858@yahoo.com). any help will be appreciated

          thanks

  11. I have tried your code. I m getting error while sending a file. I am getting null error. i.e. refused cancelled error null

    1. Hi krishna

      It seems like you have NPE in there. Check your variables debug mode to see which required thing is null. once you get cause of npe, resolve it and try see again to see if it works for you.

      Thanks.

      1. Actually i have debugged the code. XMPPException generates in the line treansfer.sendFile().
        I think the problem is of service unavailable 503

  12. The problem occuring is of version I think so. My openfire server version is 3.7.1 and smack version is 3.1.0. So can I know what can I do further to run my code properly to transfer the code

  13. Hi Harry,

    I have used your above described methods for file transfer and receiving with my chat application. But I am getting this very response during file transfer :

    10-21 12:31:41.161: I/transfere file(6112): Error is: nullTarget returned an error: feature-not-implemented(501)

    Please let me know what is the problem with my application.

    Thanks

    1. Hi Gaurav,

      It seems like your server doesn’t have the feature for file transfer or it is disabled. Please check for the same and then try again by either installing the missing feature or enabling it.

      Regards.

      1. Hi Harry,

        I have double checked in Openfire Server Portal – File Transfer Settings. It is enabled well and a port number is also written.

        Now please let me know the possible problem/cause for my problem?

          1. Hi Harry, It is not working on either side. On sender’s side error 501 is coming and on receiver side following errors/warnings are coming.

            10-25 12:23:07.929: I/Recieve File(6920): new file transfere request new file transfer request new file transfer request
            10-25 12:23:07.929: I/file request(6920): from: ramu@ec202.abcd.com/Smack
            10-25 12:23:07.929: I/Recieve File alert dialog(6920): accepted
            10-25 12:23:07.929: W/System.err(6920): Could not create file to write too:
            10-25 12:23:07.929: W/System.err(6920): — caused by: java.io.IOException: Permission denied
            10-25 12:23:07.929: W/System.err(6920): at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.recieveFile(IncomingFileTransfer.java:109)
            10-25 12:23:07.929: W/System.err(6920): at com.abc.CCM.BootReceiver.UpdaterService$7$1.fileTransferRequest(UpdaterService.java:709)

          2. Sometimes this exception also comes at the receiver’s end (Connection Refused). I am stuck in this File Transfer Scenario. Please help me.

            10-25 12:45:38.173: D/SMACK(593): 12:45:38 PM RCV (1121099488):
            10-25 12:45:38.188: W/System.err(593): java.net.ConnectException: failed to connect to /127.0.0.1 (port 7777): connect failed: ECONNREFUSED (Connection refused)
            10-25 12:45:38.188: W/System.err(593): at libcore.io.IoBridge.connect(IoBridge.java:114)
            10-25 12:45:38.193: W/System.err(593): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
            10-25 12:45:38.193: W/System.err(593): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
            10-25 12:45:38.198: W/System.err(593): at java.net.Socket.startupSocket(Socket.java:566)
            10-25 12:45:38.198: W/System.err(593): at java.net.Socket.tryAllAddresses(Socket.java:127)
            10-25 12:45:38.198: W/System.err(593): at java.net.Socket.(Socket.java:177)
            10-25 12:45:38.203: W/System.err(593): at java.net.Socket.(Socket.java:149)
            10-25 12:45:38.203: W/System.err(593): at org.jivesoftware.smackx.filetransfer.Socks5TransferNegotiator.selectHost(Socks5TransferNegotiator.java:196)
            10-25 12:45:38.208: W/System.err(593): at org.jivesoftware.smackx.filetransfer.Socks5TransferNegotiator.negotiateIncomingStream(Socks5TransferNegotiator.java:114)
            10-25 12:45:38.208: W/System.err(593): at org.jivesoftware.smackx.filetransfer.FaultTolerantNegotiator$NegotiatorService.call(FaultTolerantNegotiator.java:181)
            10-25 12:45:38.208: W/System.err(593): at org.jivesoftware.smackx.filetransfer.FaultTolerantNegotiator$NegotiatorService.call(FaultTolerantNegotiator.java:166)
            10-25 12:45:38.208: W/System.err(593): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            10-25 12:45:38.208: W/System.err(593): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            10-25 12:45:38.208: W/System.err(593): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
            10-25 12:45:38.208: W/System.err(593): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            10-25 12:45:38.213: W/System.err(593): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            10-25 12:45:38.213: W/System.err(593): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            10-25 12:45:38.213: W/System.err(593): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            10-25 12:45:38.213: W/System.err(593): at java.lang.Thread.run(Thread.java:856)
            10-25 12:45:38.213: W/System.err(593): Caused by: libcore.io.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
            10-25 12:45:38.213: W/System.err(593): at libcore.io.Posix.connect(Native Method)
            10-25 12:45:38.213: W/System.err(593): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85)
            10-25 12:45:38.218: W/System.err(593): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
            10-25 12:45:38.218: W/System.err(593): at libcore.io.IoBridge.connect(IoBridge.java:112)
            10-25 12:45:38.218: W/System.err(593): … 18 more

  14. Hi, I’m trying to setup a basic test sample of file transfer useing SIP XEP-0096 XMPP extension.

    for may test case I run openfire on CentOS6.4-64Bit Virtual Box. iptables is off.

    Storage solution is based on DB (mysql).

    It seems that receiver doesn’t negotiates well with the sender, Could you please have a look at logcats and my sample code(Attached)?

    Sender LogCat Main Part:

    Start Sending . . .

    avatar1.pnghttp://jabber.org/protocol/bytestreamshttp://jabber.org/protocol/ibb

    Sender gets No submit from receiver, it seems receiver gets request but Listener is not invoked!

    LogCat of receiver is:

    avatar1.pnghttp://jabber.org/protocol/bytestreamshttp://jabber.org/protocol/ibb

    That’s it, Nothing more!!!

    I’m working on a customized version of Xabber Client (https://github.com/redsolution/xabber-android/).

    Thanks a lot

  15. Hi I am facing (feature-not-implemented(501)) issue.I done all above steps but not working.If anyone have knowledge,please reply

  16. I have this mistake when I try to receive files [CDS][DNS]Unable to resolve host “null”: No address associated with hostname

    1. You Havnet Configured your Server, do as the topic said, and also try Turning on your File Transfer Proxy in your Server

  17. Hi,

    I am dhaval shah working on file transfer using xmpp.I am getting feature not implemented(501) error on transferring the file .I am using gmail as host .I am using asmack jse buddy cloud-2010.12.11 .jar library. my code for sending ,receiving and provider manager are as follows.any help will be appreciated.

    sending a file:-
    public static void sendFile(Connection connection,Context context)
    {

    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
    if (sdm == null)
    {
    sdm = new ServiceDiscoveryManager(connection);
    Log.e(“service discovery”, “SDM”);
    // sdm.addFeature(“http://jabber.org/protocol/disco#info”);
    // sdm.addFeature(“jabber:iq:privacy”);
    // sdm.addFeature(“officebeacon”);
    }
    FileTransferNegotiator.setServiceEnabled(connection, true);
    FileTransferNegotiator.IBB_ONLY = true;
    FileTransferManager manager = new FileTransferManager(connection);
    OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(“2007.dhaval@gmail.com”);
    File file = new File(MainActivity.files_paths[0]);
    try
    {
    transfer.sendFile(file, “test_file”);
    }
    catch (XMPPException e)
    {
    e.printStackTrace();
    }
    while (!transfer.isDone())
    {
    if (transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.error))
    {
    System.out.println(“ERROR!!! ” + transfer.getError());
    Log.e(“while status error”, “error”);
    }
    else if (transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.refused)
    || transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.cancelled))
    {
    System.out.println(“Cancelled!!! ” + transfer.getException());
    Log.e(“while Cancelled”, “cancel refuse”);
    }
    try
    {
    Thread.sleep(1000L);
    }
    catch (InterruptedException e)
    {
    e.printStackTrace();
    }
    }
    if (transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.refused)
    || transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.error)
    || transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.cancelled))
    {
    System.out.println(“refused cancelled error ” + transfer.getException());
    Log.e(“if cancelled”, “refused cancel”);
    Toast.makeText(context, “cancelled”, 4000).show();
    }
    else
    {
    System.out.println(“Success”);
    Log.e(“if no error”, “Success”);
    Toast.makeText(context, “success”, 4000).show();
    }
    }

    file receiving :-
    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
    if (sdm == null)
    {
    sdm = new ServiceDiscoveryManager(connection);
    Log.e(“service discovery”, “SDM”);
    // sdm.addFeature(“http://jabber.org/protocol/disco#info”);
    // sdm.addFeature(“jabber:iq:privacy”);
    // sdm.addFeature(“officebeacon”);
    }

    FileTransferManager manager = new FileTransferManager(connection);
    FileTransferNegotiator.setServiceEnabled(connection, true);
    FileTransferNegotiator.IBB_ONLY = true;
    Log.e(“after manager”, “manager”);
    manager.addFileTransferListener(new FileTransferListener()
    {
    public void fileTransferRequest(final FileTransferRequest request)
    {
    new Thread()
    {
    @Override
    public void run()
    {
    Log.e(“Thread running”, “staring”);
    IncomingFileTransfer transfer = request.accept();
    File mf = Environment.getExternalStorageDirectory();
    File file = new File(mf.getAbsoluteFile() + “/DCIM/Camera/” + transfer.getFileName());
    try
    {
    transfer.recieveFile(file);
    while (!transfer.isDone())
    {
    try
    {
    Thread.sleep(1000L);
    }
    catch (Exception e)
    {
    Log.e(“”, e.getMessage());
    }
    if (transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.error))
    {
    Log.e(“ERROR!!! “, transfer.getError() + “”);
    }
    if (transfer.getException() != null)
    {
    transfer.getException().printStackTrace();
    Log.e(“not null”, “print stack success”);
    Log.e(“msg”,
    “Received Path File:” + Environment.getExternalStorageDirectory().getPath() + “” + transfer.getFileName());
    Log.e(“msg”, “File ” + transfer.getFileName() + “Sent”);

    }
    }
    }
    catch (Exception e)
    {
    Log.e(“”, e.getMessage());
    }
    }

    }.start();
    }
    });
    provider manager:-
    public void configure(ProviderManager pm)
    {

    // Private Data Storage

    ProviderManager.getInstance().addIQProvider(“query”, “http://jabber.org/protocol/bytestreams”, new org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider());

    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#items”, new DiscoverItemsProvider());

    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#info”, new DiscoverInfoProvider());
    pm.addIQProvider(“query”, “jabber:iq:private”, new PrivateDataManager.PrivateDataIQProvider());

    // Time
    try
    {
    pm.addIQProvider(“query”, “jabber:iq:time”, Class.forName(“org.jivesoftware.smackx.packet.Time”));
    }
    catch (ClassNotFoundException e)
    {
    Log.w(“TestClient”, “Can’t load class for org.jivesoftware.smackx.packet.Time”);
    }

    // Roster Exchange
    pm.addExtensionProvider(“x”, “jabber:x:roster”, new RosterExchangeProvider());

    // Message Events
    pm.addExtensionProvider(“x”, “jabber:x:event”, new MessageEventProvider());

    // Chat State
    pm.addExtensionProvider(“active”, “http://jabber.org/protocol/chatstates”, new ChatStateExtension.Provider());
    pm.addExtensionProvider(“composing”, “http://jabber.org/protocol/chatstates”, new ChatStateExtension.Provider());
    pm.addExtensionProvider(“paused”, “http://jabber.org/protocol/chatstates”, new ChatStateExtension.Provider());
    pm.addExtensionProvider(“inactive”, “http://jabber.org/protocol/chatstates”, new ChatStateExtension.Provider());
    pm.addExtensionProvider(“gone”, “http://jabber.org/protocol/chatstates”, new ChatStateExtension.Provider());

    // XHTML
    pm.addExtensionProvider(“html”, “http://jabber.org/protocol/xhtml-im”, new XHTMLExtensionProvider());

    // Group Chat Invitations
    pm.addExtensionProvider(“x”, “jabber:x:conference”, new GroupChatInvitation.Provider());

    // Service Discovery # Items
    pm.addIQProvider(“query”, “http://jabber.org/protocol/disco#items”, new DiscoverItemsProvider());

    // Service Discovery # Info
    pm.addIQProvider(“query”, “http://jabber.org/protocol/disco#info”, new DiscoverInfoProvider());

    // Data Forms
    pm.addExtensionProvider(“x”, “jabber:x:data”, new DataFormProvider());

    // MUC User
    pm.addExtensionProvider(“x”, “http://jabber.org/protocol/muc#user”, new MUCUserProvider());

    // MUC Admin
    pm.addIQProvider(“query”, “http://jabber.org/protocol/muc#admin”, new MUCAdminProvider());

    // MUC Owner
    pm.addIQProvider(“query”, “http://jabber.org/protocol/muc#owner”, new MUCOwnerProvider());

    // Delayed Delivery
    pm.addExtensionProvider(“x”, “jabber:x:delay”, new DelayInformationProvider());

    // Version
    try
    {
    pm.addIQProvider(“query”, “jabber:iq:version”, Class.forName(“org.jivesoftware.smackx.packet.Version”));
    }
    catch (ClassNotFoundException e)
    {
    // Not sure what’s happening here.
    }

    // VCard
    pm.addIQProvider(“vCard”, “vcard-temp”, new VCardProvider());

    // Offline Message Requests
    pm.addIQProvider(“offline”, “http://jabber.org/protocol/offline”, new OfflineMessageRequest.Provider());

    // Offline Message Indicator
    pm.addExtensionProvider(“offline”, “http://jabber.org/protocol/offline”, new OfflineMessageInfo.Provider());

    // Last Activity
    pm.addIQProvider(“query”, “jabber:iq:last”, new LastActivity.Provider());

    // User Search
    pm.addIQProvider(“query”, “jabber:iq:search”, new UserSearch.Provider());

    // SharedGroupsInfo
    pm.addIQProvider(“sharedgroup”, “http://www.jivesoftware.org/protocol/sharedgroup”, new SharedGroupsInfo.Provider());

    // JEP-33: Extended Stanza Addressing
    pm.addExtensionProvider(“addresses”, “http://jabber.org/protocol/address”, new MultipleAddressesProvider());

    // FileTransfer
    pm.addIQProvider(“si”, “http://jabber.org/protocol/si”, new StreamInitiationProvider());

    // pm.addIQProvider(“query”, “http://jabber.org/protocol/bytestreams”, new BytestreamsProvider());

    // Privacy
    pm.addIQProvider(“query”, “jabber:iq:privacy”, new PrivacyProvider());
    pm.addIQProvider(“command”, “http://jabber.org/protocol/commands”, new AdHocCommandDataProvider());
    pm.addExtensionProvider(“malformed-action”, “http://jabber.org/protocol/commands”, new AdHocCommandDataProvider.MalformedActionError());
    pm.addExtensionProvider(“bad-locale”, “http://jabber.org/protocol/commands”, new AdHocCommandDataProvider.BadLocaleError());
    pm.addExtensionProvider(“bad-payload”, “http://jabber.org/protocol/commands”, new AdHocCommandDataProvider.BadPayloadError());
    pm.addExtensionProvider(“bad-sessionid”, “http://jabber.org/protocol/commands”, new AdHocCommandDataProvider.BadSessionIDError());
    pm.addExtensionProvider(“session-expired”, “http://jabber.org/protocol/commands”, new AdHocCommandDataProvider.SessionExpiredError());
    }

    1. its Because you are sending file with Wrong id, for example you are sending to “admin@myServer” but you should send to “admin@myServer/Smack”

  18. hello Harry
    this is very great example.
    i have some query, can you please solve it

    i m using windows 7, standalone PC with no internet connection
    i have configure the openfire well and it work perfectly for message sending
    i can access my openfire admin on 127.0.0.1:9090 easily

    i have followed your step carefully for file transfer. but unfortunately i m not able to send file,
    when i debug and follow each step , it stuck at below point

    (transfer.getStatus().equals(Status.error)){
    System.out.println(“refused cancelled error ” + transfer.getError());
    and i get value Null.

    i have added the system property as below

    xmpp.domain = testexample
    xmpp.filetransfer.enabled = true
    xmpp.proxy.enabled = true
    xmpp.proxy.externalip = 127.0.0.1
    xmpp.proxy.port = 7777

    also when i check the variable value
    manager variable has below propery and value

    connection = xmppconnection
    filetransfernegotiator = FileTransferNegotiator
    listners = null

    transfer variable has below property value
    amountwritten = -1
    callback = null
    error = null
    exception = null
    outputstream= null

    can u please tell me , where im doing wrong, i have googled lot almost 5- days, but not got ans

    below is code snippest

    if (connection!=null){
    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
    if (sdm == null)
    {
    sdm = new ServiceDiscoveryManager(connection);

    }
    XMPPConnection.DEBUG_ENABLED = true;
    sdm.addFeature(“http://jabber.org/protocol/disco#info”);
    sdm.addFeature(“http://jabber.org/protocol/disco#item”);
    sdm.addFeature(“jabber:iq:privacy”);

    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/bytestreams”, new BytestreamsProvider());
    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#items”, new DiscoverItemsProvider());
    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#info”, new DiscoverInfoProvider());

    FileTransferManager manager = new FileTransferManager(connection);

    FileTransferNegotiator.setServiceEnabled(connection, true);
    FileTransferNegotiator.IBB_ONLY = true;

    OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(“xxx@xxx/Smack”);
    File file = new File(Environment.getExternalStorageDirectory()+”/c.jpeg”);
    try {
    OutgoingFileTransfer.setResponseTimeout(30000);
    transfer.sendFile(file, “test_file”);
    } catch (XMPPException e) {
    e.printStackTrace();
    }
    while(!transfer.isDone()) {
    if(transfer.getStatus().equals(Status.error)) {
    System.out.println(“ERROR!!! ” + transfer.getError());
    } else if (transfer.getStatus().equals(Status.cancelled)
    || transfer.getStatus().equals(Status.refused)) {
    System.out.println(“Cancelled!!! ” + transfer.getError());
    }
    try {
    Thread.sleep(1000L);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    if(transfer.getStatus().equals(Status.refused)) {
    System.out.println(“refused cancelled error ” + transfer.getError());
    }
    else if (transfer.getStatus().equals(Status.cancelled)){
    System.out.println(“refused cancelled error ” + transfer.getError());
    }
    else if (transfer.getStatus().equals(Status.error)){
    System.out.println(“refused cancelled error ” + transfer.getError());
    }
    else {
    System.out.println(“Success”);
    }
    }

    1. Before all, you should not put 127.0.0.1 as Server ip, its Local, Second if you are Using Emulator 127.0.0.1 loops inside the Emulator, replacement for that in the Emulator is 10.0.2.2
      .so dont use localhost ip, use some thing like : 192.168.1.103

  19. any one Having Problem with asmack File Transfer, Leave a message to my yahoo messenger:
    oblivion_b@yahoo , ill try to answer

  20. Hello Harry Joy,
    i am trying file transfer from android to spark(desktop ) client . i was able to transfer the file successfully .but while trying to receive the i am unable to get accept or reject dilog and the receiver listener is not being called Here is my code :

    public void receiveFile(){

    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/bytestreams”, new BytestreamsProvider());
    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#items”, new DiscoverItemsProvider());
    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#info”, new DiscoverInfoProvider());
    ProviderManager.getInstance().addIQProvider(“si”,”http://jabber.org/protocol/si”, new StreamInitiationProvider());
    ProviderManager.getInstance().addIQProvider(“open”, “http://jabber.org/protocol/ibb”,new OpenIQProvider());
    ProviderManager.getInstance().addIQProvider(“close”, “http://jabber.org/protocol/ibb”,new CloseIQProvider());
    ProviderManager.getInstance().addExtensionProvider(“data”, “http://jabber.org/protocol/ibb”,new DataPacketProvider());

    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
    if (sdm == null)
    sdm = new ServiceDiscoveryManager(connection);

    sdm.addFeature(“http://jabber.org/protocol/disco#info”);
    sdm.addFeature(“http://jabber.org/protocol/disco#item”);
    sdm.addFeature(“jabber:iq:privacy”);
    Log.d(” intiated”,””);
    FileTransferManager manager = new FileTransferManager(connection);
    manager.addFileTransferListener(new FileTransferListener() {

    public void fileTransferRequest(final FileTransferRequest request) {
    Log.i(“Hello Receiver”, “in fileTransferRequest”);
    new Thread(){
    @Override
    public void run() {
    IncomingFileTransfer transfer = request.accept();
    File mf = Environment.getExternalStorageDirectory();
    File file = new File(mf.getAbsoluteFile()+”/DCIM/Camera/” + transfer.getFileName());
    try{
    transfer.recieveFile(file);
    while(!transfer.isDone()) {
    try{
    Thread.sleep(1000L);
    }catch (Exception e) {
    Log.e(“”, e.getMessage());
    }
    if(transfer.getStatus().equals(Status.error)) {
    Log.e(“ERROR!!! “, transfer.getError() + “”);
    }
    if(transfer.getException() != null) {
    transfer.getException().printStackTrace();
    }
    }

    }catch (Exception e) {
    Log.e(“”, e.getMessage());
    }
    };
    }.start();
    }
    });

    }

    i am checking the xmpp connection before calling the receive file function. Also i am not running on localhost.Can you please help me how to handle file reception in android

  21. Hello harryjoy ,
    I have tried your code,its working fine when two users in online .Can you please help me how to get offline files like offline messages.Iam using openfire 3.9.3.

    1. Hi Madhavi,

      Sending offline would be quite tricky as receiving user needs to confirm file transfer and initiates a pipe between them. I have not tried this yet but still you can try by queuing file transfer on server (by this you might also needs to be get file uploaded on server from sender first) and then when user is online send it to him. For this you might need to require to change code in server side.

      Thanks

  22. Hello harryjoy,

    I am using your code to implement chat app. When I am going to send file it response me with
    “refused cancelled error null” I debug the code and found XMPPException is there and Service unavailable (503) ..

    So please help me to solve this issue I tried everything.. No solution yet

    Thanks in Advance…:)

    1. I think its a resource problem once i added /Spark 2.6.3 it works but now i want to know what is resource and what should treat as resource when file transfer mobile to mobile… or anyy.

      1. Resource is also required in file transfer because that helps identifying right device when same account is logged in from different places.
        You should use some unique resource for your application which is combination of user’s name and app identifier so it does not conflicts with other.

        Thanks for visiting.

  23. I have tried with this I am able to transfer file between Android and spark using (/Spark 2.6.3) as a resource but Android to Android I have tried /asmack , /ashish123 …. can you help me on this apart this everything is perfect for me… thanks…

    1. Hi Ashish,

      On Android you can provide resource name by yourself while login in to server. Set that and try afterwards using same resource name.

      Thanks

  24. Hi, anyone has solved the problem of file transfer please give me the code for that , i am using jabber server and xmpp client for file transfer all the time the transfer.status==Status.error.
    my code is

    Thread thread = new Thread() {

    public void run() {
    //ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/bytestreams”, new BytestreamsProvider());
    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#items”, new DiscoverItemsProvider());
    ProviderManager.getInstance().addIQProvider(“query”,”http://jabber.org/protocol/disco#info”, new DiscoverInfoProvider());
    ProviderManager.getInstance().addIQProvider(“si”,”http://jabber.org/protocol/si”, new StreamInitiationProvider());

    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);

    if (sdm == null)
    sdm = new ServiceDiscoveryManager(connection);

    sdm.addFeature(“http://jabber.org/protocol/disco#info”);

    sdm.addFeature(“jabber:iq:privacy”);
    System.out.println(“sdm………”+sdm);

    // Create the file transfer manager
    // FileTransferNegotiator.setServiceEnabled(connection, true);

    FileTransferManager manager = new FileTransferManager(connection);
    FileTransferNegotiator.setServiceEnabled(connection, true);
    FileTransferNegotiator.IBB_ONLY = true;
    // Create the outgoing file transfer
    OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(“831444450221463@192.168.1.193/Smack”);
    Log.i(“transfere file”, “outgoingfiletransfere is created”);

    try {

    OutgoingFileTransfer.setResponseTimeout(300000);
    System.out.println(“Path of the File”+ imagepath);

    transfer.sendFile(new File(imagepath),”image_test”);
    System.out.println(“Transfer File Name:” + transfer.getFileName() );
    System.out.println(“Transfer File Size:”+ transfer.getFileSize());

    Log.i(“transfere file”, “sending file”);

    while(!transfer.isDone()) {
    if(transfer.getStatus().equals(Status.error)) {
    System.out.println(“ERROR!!! ” + transfer.getError());
    } else if (transfer.getStatus().equals(Status.cancelled)
    || transfer.getStatus().equals(Status.refused)) {
    System.out.println(“Cancelled!!! ” + transfer.getError());
    }
    try {
    Thread.sleep(1000L);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
    || transfer.getStatus().equals(Status.cancelled)){
    System.out.println(“refused cancelled error ” + transfer.getStatus());
    } else {
    System.out.println(“Success”);
    }

    } catch (XMPPException e) {
    e.printStackTrace();
    }

    Log.i(“transfere file”, “sending file done”);

    }
    };
    thread.start();

    I am stuck over there from last 2 days please resolve the issue

    thanks

      1. Hi Nitesh,

        From which client you are trying to send? Can you check the protocol it selected to transfer file and whether that protocol is supported at receiving end or not? Which version of asmack and xmpp server are you using? can you post full logs and errors for transferred packets?

        Thanks

  25. i am using asmack 16 library. i am able to send files. but i am not able to receive. when i try send file from desktop client(pidgin) to my android client, i am getting log that FileNegotiation 0.0. and some percentage like 20% or 10% showing on desktop client… Please help me..

    1. From desktop to android the file sending strategy will be different. You need to check how file is sent from desktop and whether that is supported on device if not then send file with other options on desktop.

  26. Hello harry!
    I’m trying to implement file transfer in my chat application but can’t to get an idea of what to do. I’m very much a beginner at this so please forgive me :).
    My question is where do I put the xml files for the sent and received? Also the code to send and receive file, I need to know how exactly do I run them. Please help me out with this. Thanks

    1. Hello harry!
      I made the functions for send and receive files. I wanted to know that how do I call the sendFile() and receiveFile() function. And how do I know where a file is SENT and when is it received.

      1. Hi Sibtain,

        You can call it as you call other java methods. For status you can use transfer.isDone() and transfer.getStatus() to know file is sent or not.

        Thanks

  27. hey harryjoy,
    i implemented file share with one to one using asmack 18 as Android client
    now i am stuck in file share in group(MUC). any idea how can it work..?

Leave a reply to krishna Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.