在Android中使用asmack实现文件的接收和发送

本篇主要是基于最近帮助朋友在 Android 中使用 asmack 库实现文件的接收和发送 功能时,写了个参考示例,这里做个记录,以便于自己以后参考。

我们提供的服务有:成都网站设计、成都做网站、微信公众号开发、网站优化、网站认证、温州ssl等。为上千余家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的温州网站制作公司

文件传输相关的XEP协议参考:

2【XEP-0095】StreamInitiation: http://xmpp.org/extensions/xep-0095.html

2【XEP-0096】SI FileTransfer: http://xmpp.org/extensions/xep-0096.html

2【XEP-0030】ServiceDiscovery: http://xmpp.org/extensions/xep-0030.html

2【XEP-0065】SOCKS5Bytestreams: http://xmpp.org/extensions/xep-0065.html

2【XEP-0066】Out of BandData: http://xmpp.org/extensions/xep-0066.html

2【XEP-0047】In-BandBytestreams: http://xmpp.org/extensions/xep-0047.html

本实例中主要采用的是SI + IBB 的方式发送和接收文件。

1,首先在连接和登录之前设置 ProviderManager,同时设置好全局的文件传输管理器(FileTransferManager) fileTransferManager,如下:

   /**
      *登录 IM 服务器,同时负责  连接 和 登录
      */
     public boolean login(String user, String password)
     {
         ConnectionConfiguration conf = new  ConnectionConfiguration(
                  IM_HOST, IM_PORT, IM_SERVICE_NAME);
         conf.setDebuggerEnabled(true);
         conf.setCompressionEnabled(false);
         conf.setSendPresence(true);
          conf.setSASLAuthenticationEnabled(false);
          conf.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
         connection = new  XMPPConnection(conf);

         ProviderManager pm =  ProviderManager.getInstance();

         // Private Data Storage
          pm.addIQProvider("query", "jabber:iq:private", new  PrivateDataManager.PrivateDataIQProvider());

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

         try
         {
              connection.connect();
              connection.login(user, password);
         }
         catch (XMPPException e)
         {
              e.printStackTrace();
             connection  = null;
             return  false;
         }

         fileTransferManager = new  FileTransferManager(connection);
         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");
          FileTransferNegotiator.setServiceEnabled(connection, true);
         return true;
     }

2,发送文件,如下:

           Button btnSendFile  = (Button) rootView.findViewById(R.id.send_file_btn);
              btnSendFile.setOnClickListener(new View.OnClickListener()
             {
                  @Override
                  public void onClick(View v)
                  {
                      Toast.makeText(getActivity(), "send file",  Toast.LENGTH_SHORT).show();
new SendFileTask().execute(new Uri[]{ uriFile });
                  }
             });

 //将发送文件的操作采用 AsyncTask 的方式实现(SendFileTask):
     public class SendFileTask extends AsyncTask {

         @Override
         protected Long  doInBackground(Uri... params) {

             if  (params.length < 1) {
                  return Long.valueOf(-1);
             }

             Uri  uriFile = params[0];
              FileTransferManager ftm = MainHelloIM.getInstance().getFileTransferManager();
             if (ftm !=  null)
             {
OutgoingFileTransfer oft =  ftm.createOutgoingFileTransfer("blue@test.cn/Spark");
                  try
                  {
                      String[] proj = { MediaStore.Images.Media.DATA };
                      Cursor actualp_w_picpathcursor = managedQuery(uriFile,proj,null,null,null);
                      int actual_p_w_picpath_column_index
                              = actualp_w_picpathcursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                      actualp_w_picpathcursor.moveToFirst();
                      String filePath = actualp_w_picpathcursor.getString(actual_p_w_picpath_column_index);
                      File fileToSend = new File(filePath);
                      if (fileToSend.exists())
                      {
oft.sendFile(fileToSend, "recv my file!");
                          while (!oft.isDone())
                          {
                              if (oft.getStatus().equals(FileTransfer.Status.error))
                              {
                                  Log.e(TAG, "send failed");
                              }
                              else
                              {
                                  Log.i(TAG, "status:" + oft.getStatus() + "|progress:" +  oft.getProgress());
                              }
                              Thread.sleep(1000);
                          }
                      }
                  }
                  catch (XMPPException e)
                  {
                      e.printStackTrace();
                  }
                  catch (InterruptedException e)
                  {
                      e.printStackTrace();
                  }
             }

             return  Long.valueOf(0);
         }
     }

3,接收文件,主要通过设置 文件传输监听器 来实现:

            FileTransferManager ftm = MainHelloIM.getInstance().getFileTransferManager();
ftm.addFileTransferListener(new FileTransferListener()
             {
                  @Override
                  public void fileTransferRequest(FileTransferRequest fileTransferRequest)
                  {
                      Log.i(TAG, "has file");
IncomingFileTransfer transfer =  fileTransferRequest.accept();
                      File sdDir = Environment.getExternalStorageDirectory();
                      String filePath = sdDir.toString() + "/" +  fileTransferRequest.getFileName();
                      try
                      {
transfer.recieveFile(new File(filePath));
                      }
                      catch (XMPPException e)
                      {
                          e.printStackTrace();
                      }
                  }
             });

下面为完整的文件传输的消息交互流程:


 /**
 *前面主要遵循标准 XEP-0095 来协商采用的文件传输方式
 */

//----- negotiation profile and stream

hhy -> blue
// hhy需要发送 p_w_picpath/png 格式的文件 bookCater.png 给 blue
 
              id="jsi_7839940461539037483"
         mime-type="p_w_picpath/png"
          profile="http://jabber.org/protocol/si/profile/file-transfer">
         
              recv my file!
         

         
             
                 
                     
                     
                 

             

         

     

 


blue -> hhy
// blue返回的结果显示 blue 支持 bytestreams 和 ibb 两种方式传输文件
 
     
         
             
                 
                      http://jabber.org/protocol/bytestreams
                      http://jabber.org/protocol/ibb
                 

             

         

     

 


//----- service discovery

hhy -> blue
 
     
 


blue -> hhy
 
     
         
         
         
         
         
         
         
         
     

 


hhy -> [server]
 
     
 


blue -> hhy
 
     
         
         
         
     

 


[server] -> hhy
 
     
         
         
         
         
     

 


hhy -> [server proxy]
 
     
 


[server proxy] -> hhy
 
     
         
         
         
     

 


hhy -> [server pubsub]
 
     
 


[server pubsub] -> hhy
 
     
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
     

 


hhy -> [server search]
 
     
 


[server search] -> hhy
 
     
         
         
         
         
     

 


hhy -> [server conference]
 
     
 


[server conference] -> hhy
 
     
         
         
         
         
         
         
         
     

 


//-----首先是采用 bytestreams 方式传输文件的

hhy -> [server proxy]
 
     
 


[server proxy] -> hhy
 
     
         
     

 


 hhy -> blue
//这里要求 blue 采用 proxy server 方式来传输文件
 
     
         
         
     

 


 blue -> hhy
//可以看到 blue 无法连接到 代理服务器,并返回了 404 的错误响应
 
     
         
         
     

     
         
         Could not establish socket with any provided  host
     

 


//-----上面方式不行,采用 IBB 方式传输

hhy -> blue
//在上面无法采用代理服务器的方式后,这里协商采用 IBB 的方式来传输文件
 // 并且这里提示会采用 iq stanza 来传输文件内容
 
     
 


blue -> hhy
// blue确认采用此方式传输文件
 

hhy -> blue
// hhy使用 iq/data 方式来传输文件
 
     
         iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAdVBMVEU0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/I0m/L///9bqfRrsPR6t/WVxPeu0fnj7/1JovPE3fq51/nZ6fyiy/jt9P2IvvbP4/v2+v54PNP4AAAAFnRSTlMABQYJCg4PEZOWmJmiqaqu7/Hy9/n8hZw2JQAAAORJREFUeF7l08luwlAMhWG3acvQeYh955sJ3v8RmxAsQErEyYoF//qTdTampRUroOJAV58lA5Xvzz3+YLA3oscSxb9ELwx3jm2FYy+SUdyIHLWvJ7rEKaoOMpHiC11hmM1+AB7DbHsQLZ+lbEix5iUnRjF3zDhmCCc3lhDsZMzdFpsQQo1gLdwLtgbHjXgUpyySQeyjiLQQ1sx1vDvSaIHL7Wgr1tjMYF3RupO1cRbnwe6Sztfq2c2Bx9wJd9M4xYY1pXvP17/bh0Nd4gkMtBg//KH2h5i2KN70+On1G6Ff64IW9Q/DwZoIf1KdbAAAAABJRU5ErkJggg==
     

 


blue -> hhy
//确认已经接收完成
 

hhy -> blue
// hhy关闭本次传输
 
     
 


blue -> hhy
//本次文件传输结束
 


当前题目:在Android中使用asmack实现文件的接收和发送
转载来于:http://myzitong.com/article/iejhcg.html