当前位置:  编程技术>移动开发
本页文章导读:
    ▪XMPP——Smack[一]连接、登陆及账户操作、会话、消息监听、字体表情和聊天窗口控制        XMPP——Smack[1]连接、登陆及账户操作、会话、消息监听、字体表情和聊天窗口控制 一、XMPP XMPP : The Extensible Messaging and Presence Protocol 中文全称:可扩展通讯和表示协议 简介: 可扩展通讯和表示.........
    ▪ XMPP——Smack[三]用户列表,头像,组操作,用户操作 状态,心情,头像更改        XMPP——Smack[3]用户列表,头像,组操作,用户操作 状态,心情,头像更改 这是显示用户列表方面的   1.       用户列表 Smack主要使用Roster进行列表管理的 connection.getRoster();   [c-sharp] .........
    ▪ XMPP——Smack[五]文件传输及离线消息的获取 离线消息和离线文件的实现       XMPP——Smack[5]文件传输及离线消息的获取 离线消息和离线文件的实现 1.       文件的发送 开一个文件选择框,选中文件后再调用下面的方法   [java] view plaincopyprint?   ConnectionConfigur.........

[1]XMPP——Smack[一]连接、登陆及账户操作、会话、消息监听、字体表情和聊天窗口控制
    来源: 互联网  发布时间: 2014-02-18
XMPP——Smack[1]连接、登陆及账户操作、会话、消息监听、字体表情和聊天窗口控制

一、XMPP

XMPP : The Extensible Messaging and Presence Protocol

中文全称:可扩展通讯和表示协议

简介:

可扩展通讯和表示协议 (XMPP) 可用于服务类实时通讯、表示和需求 - 响应服务中的 XML 数据元流式传输。XMPP 以 Jabber 协议为基础,而 Jabber 是即时通讯中常用的开放式协议。

 

二、Smack

    Smack是一个开源,易于使用的XMPP(jabber)客户端类库。

   Smack API, 是一个 Java 的XMPP Client Library,也是由Jive Software开发。 优点:编程简单。 缺点:API并非为大量并发用户设计,每个客户要1个线程,占用资源大,1台机器只能模拟有限(数千个)客户.

smack是一个用 java 写的XMPP客户端代码库, 是 spark 的核心.

 

二、连接及断开

基本方法

 XMPPConnection connection = new XMPPConnection("gmail.com");

        connection.connect();

实现的方法

 

 

 

[java] view plaincopyprint?
 
  • public static XMPPConnection getConnection(String domain) throws XMPPException {  
  •       
  •      XMPPConnection connection = new XMPPConnection(domain);  
  •      connection.connect();  
  •      return connection;  
  • }  
  •   
  •   
  • public static XMPPConnection getConnection(String domain,int port) throws XMPPException {  
  •      ConnectionConfiguration config = new ConnectionConfiguration(domain,port);  
  •      XMPPConnection connection = new XMPPConnection(config);  
  •      connection.connect();  
  •      return connection;  
  • }  
  •  

     

    断开  

         connection.disconnect();

         

    四、登陆

    connection.login("javatest2011@gmail.com", "*****");

     

     

    五、账户操作

     

       可以对账户进行基本操作,包括注册,注销,修改密码

    [c-sharp] view plaincopyprint?
     
  • /** 
  •      * 注册用户 
  •      * @param connection 
  •      * @param regUserName 
  •      * @param regUserPwd 
  •      * @return 
  •      */  
  •     public static boolean createAccount(XMPPConnection connection,String regUserName,String regUserPwd)  
  •     {  
  •         try {  
  •             connection.getAccountManager().createAccount(regUserName, regUserPwd);  
  •             return true;  
  •         } catch (Exception e) {  
  •             return false;  
  •         }  
  •     }  
  •       
  •     /** 
  •      * 删除当前用户 
  •      * @param connection 
  •      * @return 
  •      */  
  •     public static boolean deleteAccount(XMPPConnection connection)  
  •     {  
  •         try {  
  •             connection.getAccountManager().deleteAccount();  
  •           
  •             return true;  
  •         } catch (Exception e) {  
  •             return false;  
  •         }  
  •     }  
  •       
  •     /** 
  •      * 删除修改密码 
  •      * @param connection 
  •      * @return 
  •      */  
  •     public static boolean changePassword(XMPPConnection connection,String pwd)  
  •     {  
  •         try {  
  •             connection.getAccountManager().changePassword(pwd);  
  •           
  •             return true;  
  •         } catch (Exception e) {  
  •             return false;  
  •         }  
  •     }  
  •  

     XMPP——Smack[2]会话、消息监听、字体表情和聊天窗口控制

     

    拿到了connection,通过它可以搞定会话

     

     

    1.       建立一个会话

     

    [java] view plaincopyprint?
     
  • MessageListener msgListener  
  •  = new MessageListener()  
  •         {  
  •             public void processMessage(Chat chat, Message message)  
  •             {  
  •   
  •                 if (message != null && message.getBody() != null)  
  •                 {  
  •                     System.out.println("收到消息:" + message.getBody());  
  •                     // 可以在这进行针对这个用户消息的处理,但是这里我没做操作,看后边聊天窗口的控制  
  •                 }  
  •   
  •             }  
  •         };  
  • Chat chat = Client.getConnection().getChatManager()  
  •                 .createChat(userName, msgListener);  
  •  

     

     

    通过会话发送消息

    两个方法,一个直接发送一条文本,一个发送一个Message对象,可包含一些信息,一般使用后者,因为需要包装字体等信息

    [java] view plaincopyprint?
     
  • public static void sendMessage(Chat chat,String message) throws XMPPException {  
  •         chat.sendMessage(message);  
  •     }  
  •       
  •     public static void sendMessage(Chat chat,Message message) throws XMPPException {  
  •         chat.sendMessage(message);  
  •     }  
  •  

     

     

    2.       消息监听

    每个connection的chatManager可以设置一个消息监听器,因为IM必须实现他人对你发起会话也会弹出窗口,即自己可以主动发起会话,也可以接收他人发起的会话

     

    [java] view plaincopyprint?
     
  • ChatManager manager = Client.getConnection().getChatManager();  
  •         manager.addChatListener(new ChatManagerListener() {  
  •             public void chatCreated(Chat chat, boolean arg1) {  
  •                 chat.addMessageListener(new MessageListener() {  
  •                     public void processMessage(Chat arg0, Message message) {  
  •                      //若是聊天窗口已存在,将消息转往目前窗口  
  •                      //若是窗口不存在,开新的窗口并注册  
  •   
  •                     }     
  •                 });  
  •             }  
  •         });  
  •  

       其实窗口的管理是使用线程的,来一个新的会话,起线程

     

    3.  字体表情

    在这里实现字体和表情是使用自身开发IM之间的实现。

     

    字体实现思想:

    在发送消息的同时,将字体内容作为附加信息发送,接收方接收到根据字体信息进行处理后显示

      

       实现:使用Message对消息进行封装

     

     

    [java] view plaincopyprint?
     
  • Message msg = new Message();  
  •         msg.setProperty("size", size);  
  •         msg.setProperty("kind", kind);  
  •         msg.setProperty("bold", bold);  
  •         msg.setProperty("italic", italic);  
  •         msg.setProperty("underline", underline);  
  •         msg.setProperty("color", color);  
  •         msg.setBody(getSendInfo());//真正的消息  
  •         chat.sendMessage(msg);  
  •  

     

     

    接收方先获取设置信息后展示

           展示的控件: JTextPane receiveText = new JTextPane();

     

    [java] view plaincopyprint?
     
  • Style style = receiveText.addStyle("font", null);  
  •         StyleConstants.setFontSize(style, size);  
  •         StyleConstants.setFontFamily(style, kind);  
  •         StyleConstants.setBold(style, bold);  
  •         StyleConstants.setItalic(style, italic);  
  •         StyleConstants.setUnderline(style, underline);  
  •         StyleConstants.setForeground(style, color);  
  •  

     

      表情:

           实现机制是客户端本身存有一套表情图片,在选中时,将表情编号加入到消息中,实际发送出去的只是文本,拿到后解析字符串,将编号转为具体表情展示

          具体就不写了

     

     

    1.  聊天窗口控制

    所谓控制,主要是控制唯一性

    无论是你发起一个会话开启一个窗口,还是对方给你发送会话开启,你与对方之间有且仅有一个窗口,之后任何消息都在这个窗口中处理

     

    思想:单例类,持有一个

    //现有的聊天窗口

        public static TreeMap<String,TelFrame> currentChat = new TreeMap<String,TelFrame>();

     

    其实应该用concurrentHashMap可能会更好,不顾我这边分派的主线程只有一个,不涉及多个线程并发的问题,所以用了Treemap,汗一个,貌似应该hashmap,当时考虑不同

     

    然后,在接收消息的时候根据发消息的用户,判定窗口是否存在,存在,转发消息到该窗口,不存在,建立新的窗口

    若是关闭窗口,注销之

     

     

     

    [java] view plaincopyprint?
     
  • //注册聊天室  
  •     public static void registerChat(String userName,TelFrame chatroom)  
  •     {  
  •         //System.out.println("注册:"+userName);  
  •         currentChat.put(userName, chatroom);  
  •     }  
  •     //注销注册  
  •     public static void removeChat(String userName)  
  •     {  
  •         System.out.println("用户注销聊天室:"+userName);  
  •         currentChat.remove(userName);  
  •     }  
  •     //查看是否已有  
  •     public static boolean isChatExist(String userName)  
  •     {  
  •           
  •         return currentChat.containsKey(userName);  
  •     }  
  •     //获取对象  
  •     public static TelFrame getChatRoom(String userName)  
  •     {  
  •         return currentChat.get(userName);  
  •     }  
  •  

     

     

     


        
    [2] XMPP——Smack[三]用户列表,头像,组操作,用户操作 状态,心情,头像更改
        来源: 互联网  发布时间: 2014-02-18
    XMPP——Smack[3]用户列表,头像,组操作,用户操作 状态,心情,头像更改

    这是显示用户列表方面的

     

    1.       用户列表

    Smack主要使用Roster进行列表管理的

    connection.getRoster();

     

    [java] view plaincopyprint?
     
  • /** 
  •      * 返回所有组信息 <RosterGroup> 
  •      *  
  •      * @return List(RosterGroup) 
  •      */  
  •     public static List<RosterGroup> getGroups(Roster roster) {  
  •         List<RosterGroup> groupsList = new ArrayList<RosterGroup>();  
  •         Collection<RosterGroup> rosterGroup = roster.getGroups();  
  •         Iterator<RosterGroup> i = rosterGroup.iterator();  
  •         while (i.hasNext())  
  •             groupsList.add(i.next());  
  •         return groupsList;  
  •     }  
  •   
  •     /** 
  •      * 返回相应(groupName)组里的所有用户<RosterEntry> 
  •      *  
  •      * @return List(RosterEntry) 
  •      */  
  •     public static List<RosterEntry> getEntriesByGroup(Roster roster,  
  •             String groupName) {  
  •         List<RosterEntry> EntriesList = new ArrayList<RosterEntry>();  
  •         RosterGroup rosterGroup = roster.getGroup(groupName);  
  •         Collection<RosterEntry> rosterEntry = rosterGroup.getEntries();  
  •         Iterator<RosterEntry> i = rosterEntry.iterator();  
  •         while (i.hasNext())  
  •             EntriesList.add(i.next());  
  •         return EntriesList;  
  •     }  
  •   
  •     /** 
  •      * 返回所有用户信息 <RosterEntry> 
  •      *  
  •      * @return List(RosterEntry) 
  •      */  
  •     public static List<RosterEntry> getAllEntries(Roster roster) {  
  •         List<RosterEntry> EntriesList = new ArrayList<RosterEntry>();  
  •         Collection<RosterEntry> rosterEntry = roster.getEntries();  
  •         Iterator<RosterEntry> i = rosterEntry.iterator();  
  •         while (i.hasNext())  
  •             EntriesList.add(i.next());  
  •         return EntriesList;  
  •     }  
  •  

     

    这里注意下,与gtalk通讯,貌似gtalk是没有分组的,汗,所以使用第三个方法直接取

     

    当然,还要处理,若是刚注册用户,一个组都没有的,需要默认两个组,我的好友及黑名单

    黑名单的消息,一律杀掉,不会接受处理

    2.       用户头像的获取

    使用VCard,很强大,具体自己看API吧

    可以看看VCard传回来XML的组成,含有很多信息的

     

     

    [java] view plaincopyprint?
     
  • /** 
  •      * 获取用户的vcard信息 
  •      * @param connection 
  •      * @param user 
  •      * @return 
  •      * @throws XMPPException 
  •      */  
  •     public static VCard getUserVCard(XMPPConnection connection, String user) throws XMPPException  
  •     {  
  •         VCard vcard = new VCard();  
  •         vcard.load(connection, user);  
  •           
  •         return vcard;  
  •     }  
  •   
  • 获取头像使用  
  •     /** 
  •      * 获取用户头像信息 
  •      */  
  •     public static ImageIcon getUserImage(XMPPConnection connection, String user) {  
  •         ImageIcon ic = null;  
  •         try {  
  •             System.out.println("获取用户头像信息: "+user);  
  •             VCard vcard = new VCard();  
  •             vcard.load(connection, user);  
  •               
  •             if(vcard == null || vcard.getAvatar() == null)  
  •             {  
  •                 return null;  
  •             }  
  •             ByteArrayInputStream bais = new ByteArrayInputStream(  
  •                     vcard.getAvatar());  
  •             Image image = ImageIO.read(bais);  
  •       
  •               
  •             ic = new ImageIcon(image);  
  •             System.out.println("图片大小:"+ic.getIconHeight()+" "+ic.getIconWidth());  
  •           
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •         }  
  •         return ic;  
  •     }  
  •   

     

     

    3.       组操作和用户分组操作

    主要是建立删除分组,用户添加到分组等操作

     

     

     

    [c-sharp] view plaincopyprint?
     
  • /** 
  •      * 添加一个组 
  •      */  
  •     public static boolean addGroup(Roster roster,String groupName)  
  •     {  
  •         try {  
  •             roster.createGroup(groupName);  
  •             return true;  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •             return false;  
  •         }  
  •     }  
  •       
  •     /** 
  •      * 删除一个组 
  •      */  
  •     public static boolean removeGroup(Roster roster,String groupName)  
  •     {  
  •         return false;  
  •     }  
  •       
  •     /** 
  •      * 添加一个好友  无分组 
  •      */  
  •     public static boolean addUser(Roster roster,String userName,String name)  
  •     {  
  •         try {  
  •             roster.createEntry(userName, name, null);  
  •             return true;  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •             return false;  
  •         }  
  •     }  
  •     /** 
  •      * 添加一个好友到分组 
  •      * @param roster 
  •      * @param userName 
  •      * @param name 
  •      * @return 
  •      */  
  •     public static boolean addUser(Roster roster,String userName,String name,String groupName)  
  •     {  
  •         try {  
  •             roster.createEntry(userName, name,new String[]{ groupName});  
  •             return true;  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •             return false;  
  •         }  
  •     }  
  •       
  •     /** 
  •      * 删除一个好友 
  •      * @param roster 
  •      * @param userName 
  •      * @return 
  •      */  
  •     public static boolean removeUser(Roster roster,String userName)  
  •     {  
  •         try {  
  •               
  •             if(userName.contains("@"))  
  •             {  
  •                 userName = userName.split("@")[0];  
  •             }  
  •             RosterEntry entry = roster.getEntry(userName);  
  •             System.out.println("删除好友:"+userName);  
  •             System.out.println("User: "+(roster.getEntry(userName) == null));  
  •             roster.removeEntry(entry);  
  •               
  •             return true;  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •             return false;  
  •         }  
  •           
  •     }  
  •   

     

     

    4.     用户查询

    本来是用户操作的,分组和增删在3里讲了,这里主要是查询操作

    查询用户

     

    [java] view plaincopyprint?
     
  • public static List<UserBean> searchUsers(XMPPConnection connection,String serverDomain,String userName) throws XMPPException  
  •     {  
  •         List<UserBean> results = new ArrayList<UserBean>();  
  •         System.out.println("查询开始..............."+connection.getHost()+connection.getServiceName());  
  •           
  •         UserSearchManager usm = new UserSearchManager(connection);  
  •           
  •           
  •         Form searchForm = usm.getSearchForm(serverDomain);  
  •         Form answerForm = searchForm.createAnswerForm();  
  •         answerForm.setAnswer("Username", true);  
  •         answerForm.setAnswer("search", userName);  
  •         ReportedData data = usm.getSearchResults(answerForm, serverDomain);  
  •            
  •          Iterator<Row> it = data.getRows();  
  •          Row row = null;  
  •          UserBean user = null;  
  •          while(it.hasNext())  
  •          {  
  •              user = new UserBean();  
  •              row = it.next();  
  •              user.setUserName(row.getValues("Username").next().toString());  
  •              user.setName(row.getValues("Name").next().toString());  
  •              user.setEmail(row.getValues("Email").next().toString());  
  •              System.out.println(row.getValues("Username").next());  
  •              System.out.println(row.getValues("Name").next());  
  •              System.out.println(row.getValues("Email").next());  
  •              results.add(user);  
  •              //若存在,则有返回,UserName一定非空,其他两个若是有设,一定非空  
  •          }  
  •            
  •          return results;  
  •     }  
  •  

     

     

    以上查询貌似是多字段查询,即用户多个属性中某一个符合即作为查询结果

    实际是可以实现根据某一特定字段查询的,如用户名,或昵称,这里笼统了,若需扩展去查看下API重写下

     1.       修改自身状态

    包括上线,隐身,对某人隐身,对某人上线

     

    [java] view plaincopyprint?
     
  • public static void updateStateToAvailable(XMPPConnection connection)  
  •     {  
  •         Presence presence = new Presence(Presence.Type.available);  
  •         connection.sendPacket(presence);  
  •      }  
  •       
  •     public static void updateStateToUnAvailable(XMPPConnection connection)  
  •     {  
  •         Presence presence = new Presence(Presence.Type.unavailable);  
  •         connection.sendPacket(presence);  
  •         }  
  •       
  •     public static void updateStateToUnAvailableToSomeone(XMPPConnection connection,String userName)  
  •     {  
  •         Presence presence = new Presence(Presence.Type.unavailable);  
  •         presence.setTo(userName);  
  •         connection.sendPacket(presence);  
  •     }  
  •     public static void updateStateToAvailableToSomeone(XMPPConnection connection,String userName)  
  •     {  
  •         Presence presence = new Presence(Presence.Type.available);  
  •         presence.setTo(userName);  
  •         connection.sendPacket(presence);  
  •   
  •     }  
  •  

     

    2.       心情修改

     

      

    [java] view plaincopyprint?
     
  • /** 
  •      * 修改心情 
  •      * @param connection 
  •      * @param status 
  •      */  
  •     public static void changeStateMessage(XMPPConnection connection,String status)  
  •     {  
  •         Presence presence = new Presence(Presence.Type.available);  
  •         presence.setStatus(status);  
  •         connection.sendPacket(presence);  
  •       
  •     }  
  •  

     

    3.       修改用户头像

    有点麻烦,主要是读入图片文件,编码,传输之

     

     

    [java] view plaincopyprint?
     
  • public static void changeImage(XMPPConnection connection,File f) throws XMPPException, IOException  
  •     {  
  •       
  •         VCard vcard = new VCard();  
  •         vcard.load(connection);  
  •           
  •             byte[] bytes;  
  •             
  •                 bytes = getFileBytes(f);  
  •                 String encodedImage = StringUtils.encodeBase64(bytes);  
  •                 vcard.setAvatar(bytes, encodedImage);  
  •                 vcard.setEncodedImage(encodedImage);  
  •                 vcard.setField("PHOTO", "<TYPE>image/jpg</TYPE><BINVAL>"  
  •                         + encodedImage + "</BINVAL>", true);  
  •                   
  •                   
  •                 ByteArrayInputStream bais = new ByteArrayInputStream(  
  •                         vcard.getAvatar());  
  •                 Image image = ImageIO.read(bais);  
  •                 ImageIcon ic = new ImageIcon(image);  
  •                    
  •              
  •             
  •             vcard.save(connection);  
  •              
  •     }  
  •       
  •     private static byte[] getFileBytes(File file) throws IOException {  
  •         BufferedInputStream bis = null;  
  •         try {  
  •             bis = new BufferedInputStream(new FileInputStream(file));  
  •             int bytes = (int) file.length();  
  •             byte[] buffer = new byte[bytes];  
  •             int readBytes = bis.read(buffer);  
  •             if (readBytes != buffer.length) {  
  •                 throw new IOException("Entire file not read");  
  •             }  
  •             return buffer;  
  •         } finally {  
  •             if (bis != null) {  
  •                 bis.close();  
  •             }  
  •         }  
  • }  
  •  

     

    4.  补充,用户状态的监听

     

    即对方改变头像,状态,心情时,更新自己用户列表,其实这里已经有smack实现的监听器

     

     

     

     

     

     

     

     

    [java] view plaincopyprint?
     
  • final Roster roster = Client.getRoster();  
  •           
  •         roster.addRosterListener(  
  •                 new RosterListener() {  
  •   
  •                     @Override  
  •                     public void entriesAdded(Collection<String> arg0) {  
  •                         // TODO Auto-generated method stub  
  •                         System.out.println("--------EE:"+"entriesAdded");  
  •                     }  
  •   
  •                     @Override  
  •                     public void entriesDeleted(Collection<String> arg0) {  
  •                         // TODO Auto-generated method stub  
  •                         System.out.println("--------EE:"+"entriesDeleted");  
  •                     }  
  •   
  •                     @Override  
  •                     public void entriesUpdated(Collection<String> arg0) {  
  •                         // TODO Auto-generated method stub  
  •                         System.out.println("--------EE:"+"entriesUpdated");  
  •                     }  
  •   
  •                     @Override  
  •                     public void presenceChanged(Presence arg0) {  
  •                         // TODO Auto-generated method stub  
  •                         System.out.println("--------EE:"+"presenceChanged");  
  •                     }     
  •                       
  •                 });  
  •               
  •  

     

     

     


        
    [3] XMPP——Smack[五]文件传输及离线消息的获取 离线消息和离线文件的实现
        来源: 互联网  发布时间: 2014-02-18
    XMPP——Smack[5]文件传输及离线消息的获取 离线消息和离线文件的实现

    1.       文件的发送

    开一个文件选择框,选中文件后再调用下面的方法

     

    [java] view plaincopyprint?
     
  • public static void sendFile(XMPPConnection connection,  
  •             String user, File file) throws XMPPException, InterruptedException {  
  •           
  •         System.out.println("发送文件开始"+file.getName());  
  •         FileTransferManager transfer = new FileTransferManager(Client.getConnection());  
  •         System.out.println("发送文件给: "+user+Client.getServiceNameWithPre());  
  •         OutgoingFileTransfer out = transfer.createOutgoingFileTransfer(user+Client.getServiceNameWithPre()+"/Smack");//  
  •           
  •         out.sendFile(file, file.getName());  
  •           
  •         System.out.println("//////////");  
  •         System.out.println(out.getStatus());  
  •         System.out.println(out.getProgress());  
  •         System.out.println(out.isDone());  
  •           
  •         System.out.println("//////////");  
  •           
  •         System.out.println("发送文件结束");  
  •     }  
  •  

     

     

    2.       文件接收,必须使用监听

     

     

    [java] view plaincopyprint?
     
  • FileTransferManager transfer = new FileTransferManager(connection);  
  • transfer.addFileTransferListener(new RecFileTransferListener());  
  •   
  • public class RecFileTransferListener implements FileTransferListener {  
  •   
  •     public String getFileType(String fileFullName)  
  •     {  
  •         if(fileFullName.contains("."))  
  •         {  
  •             return "."+fileFullName.split("//.")[1];  
  •         }else{  
  •             return fileFullName;  
  •         }  
  •           
  •     }  
  •       
  •     @Override  
  •     public void fileTransferRequest(FileTransferRequest request) {  
  •         System.out.println("接收文件开始.....");  
  •         final IncomingFileTransfer inTransfer = request.accept();  
  •         final String fileName = request.getFileName();  
  •         long length = request.getFileSize();   
  •         final String fromUser = request.getRequestor().split("/")[0];  
  •         System.out.println("文件大小:"+length + "  "+request.getRequestor());  
  •         System.out.println(""+request.getMimeType());  
  •         try {   
  •               
  •             JFileChooser chooser = new JFileChooser();   
  •             chooser.setCurrentDirectory(new File("."));   
  •               
  •             int result = chooser.showOpenDialog(null);  
  •               
  •             if(result==JFileChooser.APPROVE_OPTION)  
  •             {  
  •                 final File file = chooser.getSelectedFile();  
  •                 System.out.println(file.getAbsolutePath());  
  •                     new Thread(){  
  •                         public void run()  
  •                         {  
  •                         try {  
  •   
  •                             System.out.println("接受文件: " + fileName);  
  •                             inTransfer  
  •                                     .recieveFile(new File(file  
  •                                             .getAbsolutePath()  
  •                                             + getFileType(fileName)));  
  •   
  •                             Message message = new Message();  
  •                             message.setFrom(fromUser);  
  •                             message.setProperty("REC_SIGN", "SUCCESS");  
  •                             message.setBody("["+fromUser+"]发送文件: "+fileName+"/r/n"+"存储位置: "+file.getAbsolutePath()+ getFileType(fileName));  
  •                             if (Client.isChatExist(fromUser)) {  
  •                                 Client.getChatRoom(fromUser).messageReceiveHandler(  
  •                                         message);  
  •                             } else {  
  •                                 ChatFrameThread cft = new ChatFrameThread(  
  •                                         fromUser, message);  
  •                                 cft.start();  
  •                                   
  •                             }  
  •                         } catch (Exception e2) {  
  •                             e2.printStackTrace();  
  •                         }  
  •                         }  
  •                     }.start();  
  •             }else{  
  •                   
  •                 System.out.println("拒绝接受文件: "+fileName);  
  •                   
  •                 request.reject();  
  •                 Message message = new Message();  
  •                 message.setFrom(fromUser);  
  •                 message.setBody("拒绝"+fromUser+"发送文件: "+fileName);  
  •                 message.setProperty("REC_SIGN", "REJECT");  
  •                 if (Client.isChatExist(fromUser)) {  
  •                     Client.getChatRoom(fromUser)  
  •                             .messageReceiveHandler(message);  
  •                 } else {  
  •                     ChatFrameThread cft = new ChatFrameThread(  
  •                             fromUser, message);  
  •                     cft.start();  
  •                 }  
  •             }  
  •               
  •               
  •               
  •               
  •                
  •             /* InputStream in = inTransfer.recieveFile(); 
  •               
  •              String fileName = "r"+inTransfer.getFileName(); 
  •               
  •              OutputStream out = new FileOutputStream(new File("d:/receive/"+fileName)); 
  •              byte[] b = new byte[512]; 
  •              while(in.read(b) != -1) 
  •              { 
  •                  out.write(b); 
  •                  out.flush(); 
  •              } 
  •               
  •              in.close(); 
  •              out.close();*/  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •         }  
  •           
  •         System.out.println("接收文件结束.....");  
  •   
  •     }  
  •   
  • }  
  •  

     

     1.离线消息

      openfire本身是支持离线消息的,不需要进行额外处理,可以用spark测试下

      使用smack,其实他提供了相应的方法

      Class OfflineMessageManager

     

      可以看下描述

     

    The OfflineMessageManager helps manage offline messages even before the user has sent an available presence. When a user asks for his offline messages before sending an available presence then the server will not send a flood with all the offline messages when the user becomes online. The server will not send a flood with all the offline messages to the session that made the offline messages request or to any other session used by the user that becomes online.

     

    英文退化了点,汗,大意就是,必须在发送在线信息之前去获取离线消息 

     

    刚开始没看这个,结果在上线之后,去取,结果。。。。离线消息数量总是为零,囧

     

    首先,连接,状态要设为离线

     

    [java] view plaincopyprint?
     
  • ConnectionConfiguration connConfig = new ConnectionConfiguration(serverDomain);  
  •     
  •   connConfig.setSendPresence(false); // where connConfig is object of .  
  •   
  •      connection = new XMPPConnection(connConfig);  
  •      connection.connect();  
  •  

     

    然后,登陆

      connection.login(userName, pwd);

     

    接着,拿离线消息

     

    [java] view plaincopyprint?
     
  • OfflineMessageManager offlineManager = new OfflineMessageManager(  
  •                 Client.getConnection());  
  •         try {  
  •             Iterator<org.jivesoftware.smack.packet.Message> it = offlineManager  
  •                     .getMessages();  
  •   
  •             System.out.println(offlineManager.supportsFlexibleRetrieval());  
  •             System.out.println("离线消息数量: " + offlineManager.getMessageCount());  
  •   
  •               
  •             Map<String,ArrayList<Message>> offlineMsgs = new HashMap<String,ArrayList<Message>>();  
  •               
  •             while (it.hasNext()) {  
  •                 org.jivesoftware.smack.packet.Message message = it.next();  
  •                 System.out  
  •                         .println("收到离线消息, Received from 【" + message.getFrom()  
  •                                 + "】 message: " + message.getBody());  
  •                 String fromUser = message.getFrom().split("/")[0];  
  •   
  •                 if(offlineMsgs.containsKey(fromUser))  
  •                 {  
  •                     offlineMsgs.get(fromUser).add(message);  
  •                 }else{  
  •                     ArrayList<Message> temp = new ArrayList<Message>();  
  •                     temp.add(message);  
  •                     offlineMsgs.put(fromUser, temp);  
  •                 }  
  •             }  
  •   
  •             //在这里进行处理离线消息集合......  
  •             Set<String> keys = offlineMsgs.keySet();  
  •             Iterator<String> offIt = keys.iterator();  
  •             while(offIt.hasNext())  
  •             {  
  •                 String key = offIt.next();  
  •                 ArrayList<Message> ms = offlineMsgs.get(key);  
  •                 TelFrame tel = new TelFrame(key);  
  •                 ChatFrameThread cft = new ChatFrameThread(key, null);  
  •                 cft.setTel(tel);  
  •                 cft.start();  
  •                 for (int i = 0; i < ms.size(); i++) {  
  •                     tel.messageReceiveHandler(ms.get(i));  
  •                 }  
  •             }  
  •               
  •               
  •             offlineManager.deleteMessages();  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •         }  
  •  

     

    记得最后要把离线消息删除,即通知服务器删除离线消息

    offlineManager.deleteMessages();

    否则,下次上了消息还存在

    接着,上线

     Presence presence = new Presence(Presence.Type.available);
            connection.sendPacket(presence);

     

    2.离线文件

     

    这个我没实现,汗

    主要思想:开发openfire插件,拦截离线文件,将文件存到服务器上,同时在数据库里开一张表,存储文件信息

                   当用户上线时,查表,若是有,根据路径,拿了发送

    当然,大家可以谷歌下是否有相应的插件,时间紧迫,我倒是没找着

     

     

     

    到这里,大概就这些了,对了,还扩展了个视频音频聊天,不过使用的是JMF,点对点的,本来打算使用jingle的,结果连API文档都没找到,晕死

     

    就这些

     

     

     


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android提高之自定义Menu(TabMenu)实现方法 iis7站长之家
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3