这篇文章主要介绍如何实现点对点单人聊天、多人的群聊、以及如何给对方发送文件,如何发送图片消息和语音消息等功能。

1.单人聊天

1.首先创建聊天对象

/**

* 创建聊天窗口

* @param jid 好友的JID

* @return

*/

public Chat createChat(String jid) {

if(isConnected()) {

ChatManager chatManager = ChatManager.getInstanceFor(connection);

return chatManager.createChat(jid);

}

throw new NullPointerException("服务器连接失败,请先连接服务器");

}

创建聊天对象时,参数JID记得传聊天JID(解释请参考我的系列文章之基于openfire+smack开发Android即时聊天应用[三]-账号信息、添加好友、JID理解等)给好友发送文本消息

chat.sendMessage(message);

2.获取聊天对象管理器

/**

* 获取聊天对象管理器

* @return

*/

public ChatManager getChatManager() {

if(isConnected()) {

ChatManager chatManager = ChatManager.getInstanceFor(connection);

return chatManager;

}

throw new NullPointerException("服务器连接失败,请先连接服务器");

}

3.接收文本消息

//创建聊天对象管理器监听

private ChatManagerListener chatManagerListener = new ChatManagerListener() {

@Override

public void chatCreated(Chat chat, boolean createdLocally) {

chat.addMessageListener(new ChatMessageListener() {

@Override

public void processMessage(Chat chat, Message message) {

//接收到消息Message之后进行消息展示处理,这个地方可以处理所有人的消息

}

});

}

};

//设置聊天对象管理器处理监听

getChatManager().addChatListener(chatManagerListener);

上述代码会在你创建聊天对象时对该聊天对象设置消息处理监听,当接收到消息之后,会自动调用processMessage方法进行处理,我们可以在该方法中对接收到的消息进行展示或其他处理,所有好友发送过来的消息都会通过该方法处理。所以该监听最好在登陆之后进行设置,同时在断开连接或是注销时移除该监听。

2.群聊

1.创建群聊聊天室

/**

* 创建群聊聊天室

* @param roomName 聊天室名字

* @param nickName 创建者在聊天室中的昵称

* @param password 聊天室密码

* @return

*/

public MultiUserChat createChatRoom(String roomName, String nickName, String password) {

if(!isConnected()) {

throw new NullPointerException("服务器连接失败,请先连接服务器");

}

MultiUserChat muc = null;

try {

// 创建一个MultiUserChat

muc = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(roomName + "@conference." + connection.getServiceName());

// 创建聊天室

boolean isCreated = muc.createOrJoin(nickName);

if(isCreated) {

// 获得聊天室的配置表单

Form form = muc.getConfigurationForm();

// 根据原始表单创建一个要提交的新表单。

Form submitForm = form.createAnswerForm();

// 向要提交的表单添加默认答复

List fields = form.getFields();

for(int i = 0; fields != null && i < fields.size(); i++) {

if(FormField.Type.hidden != fields.get(i).getType() &&

fields.get(i).getVariable() != null) {

// 设置默认值作为答复

submitForm.setDefaultAnswer(fields.get(i).getVariable());

}

}

// 设置聊天室的新拥有者

List owners = new ArrayList();

owners.add(connection.getUser());// 用户JID

submitForm.setAnswer("muc#roomconfig_roomowners", owners);

// 设置聊天室是持久聊天室,即将要被保存下来

submitForm.setAnswer("muc#roomconfig_persistentroom", true);

// 房间仅对成员开放

submitForm.setAnswer("muc#roomconfig_membersonly", false);

// 允许占有者邀请其他人

submitForm.setAnswer("muc#roomconfig_allowinvites", true);

if(password != null && password.length() != 0) {

// 进入是否需要密码

submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true);

// 设置进入密码

submitForm.setAnswer("muc#roomconfig_roomsecret", password);

}

// 能够发现占有者真实 JID 的角色

// submitForm.setAnswer("muc#roomconfig_whois", "anyone");

// 登录房间对话

submitForm.setAnswer("muc#roomconfig_enablelogging", true);

// 仅允许注册的昵称登录

submitForm.setAnswer("x-muc#roomconfig_reservednick", true);

// 允许使用者修改昵称

submitForm.setAnswer("x-muc#roomconfig_canchangenick", false);

// 允许用户注册房间

submitForm.setAnswer("x-muc#roomconfig_registration", false);

// 发送已完成的表单(有默认值)到服务器来配置聊天室

muc.sendConfigurationForm(submitForm);

}

} catch (XMPPException | SmackException e) {

e.printStackTrace();

return null;

}

return muc;

}

上面这段创建群聊聊天室设置表单属性的那段代码引用于网上的代码段。

2.加入群聊聊天室

/**

* 加入一个群聊聊天室

* @param roomName 聊天室名字

* @param nickName 用户在聊天室中的昵称

* @param password 聊天室密码

* @return

*/

public MultiUserChat joinChatRoom(String roomName, String nickName, String password) {

if(!isConnected()) {

throw new NullPointerException("服务器连接失败,请先连接服务器");

}

try {

// 使用XMPPConnection创建一个MultiUserChat窗口

MultiUserChat muc = MultiUserChatManager.getInstanceFor(connection).

getMultiUserChat(roomName + "@conference." + connection.getServiceName());

// 聊天室服务将会决定要接受的历史记录数量

DiscussionHistory history = new DiscussionHistory();

history.setMaxChars(0);

// history.setSince(new Date());

// 用户加入聊天室

muc.join(nickName, password);

return muc;

} catch (XMPPException | SmackException e) {

e.printStackTrace();

return null;

}

}

在实现加入群聊聊天室的这段代码中有这么一段代码:

getMultiUserChat(roomName + "@conference." + connection.getServiceName());

在@与ServiceName中间必须加上conference这个字符串,我也不知道为什么,我最开始时不知道没有加,然后无论如何都加入失败,后来在网上查资料查了半天,有人说是要加上这个,然后我加上就成功了,暂时没搞明白为什么,先把程序跑通会用了再研究其他的原因。

3.群聊发送消息

当你创建或是加入群聊聊天室后,即可获得群聊对象MultiUserChat,通过该对象即可发送群聊消息:

multiUserChat.sendMessage(msg);//发送群聊消息

4.接收群聊消息

//聊天室消息监听

private MessageListener messageListener = new MessageListener() {

@Override

public void processMessage(Message message) {

//与单聊接收处理消息类似,聊天室里所有人(包括发送人自己)发送的消息都会通过此方法进行回调处理

}

};

//设置聊天室消息监听

multiUserChat.addMessageListener(messageListener);

群聊接收消息与单聊接收消息还是很像的,只是监听对象,监听方式稍稍有点区别,整个来说,消息接收还是很简单的。

3.文件传输

1.获取文件传输对象

/**

* 获取发送文件的发送器

* @param jid 一个完整的jid(如:laohu@192.168.0.108/Smack

* 后面的Smack应该客户端类型,不加这个会出错)

* @return

*/

public OutgoingFileTransfer getSendFileTransfer(String jid) {

if(isConnected()) {

return FileTransferManager.getInstanceFor(connection).createOutgoingFileTransfer(jid);

}

throw new NullPointerException("服务器连接失败,请先连接服务器");

}

获取文件传输对象时的参数JID记得为文件传输JID:解释请参考我的系列文章之基于openfire+smack开发Android即时聊天应用[三]-账号信息、添加好友、JID理解等

2.发送文件

//获取文件传输对象

OutgoingFileTransfer transfer = getSendFileTransfer(jid);

//发送文件

transfer.sendFile(File file, String description);

//此处执行文件发送状态监听

以上代码为发送文件file,参数description为对这次文件传输的描述

3.文件传输(包括文件发送与接收)过程监听(传输开始、完成、进度百分比)

//文件传输过程中的状态监听分析

if(transfer.getProgress() < 1) {//开始传输

//传输进度,值为0~1

}

while(!transfer.isDone()) {//判断传输是否完成,传输取消、传输完成、传输发生错误都会返回true

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

if(FileTransfer.Status.complete.equals(transfer.getStatus())) {

//传输完成

} else if(FileTransfer.Status.cancelled.equals(transfer.getStatus())) {

//传输取消

} else if(FileTransfer.Status.error.equals(transfer.getStatus())) {

//传输错误

} else if(FileTransfer.Status.refused.equals(transfer.getStatus())) {

//传输拒绝

}

以上代码需在子线程执行,可以在文件传输(发送、接收)开始时设置进度条,传输完成时去掉进度条,同时可以通过getProgress()方法获得文件传输的具体进度百分比。

4.接收文件

/**

* 添加文件接收的监听

* @param fileTransferListener

*/

public void addFileTransferListener(FileTransferListener fileTransferListener) {

if(isConnected()) {

FileTransferManager.getInstanceFor(connection).addFileTransferListener(fileTransferListener);

return;

}

throw new NullPointerException("服务器连接失败,请先连接服务器");

}

addFileTransferListener(new FileTransferListener() {

@Override

public void fileTransferRequest(FileTransferRequest request) {

// Accept it

IncomingFileTransfer transfer = request.accept();

try {

String description = request.getDescription();

//在目录fileDir目录下新建一个名字为request.getFileName()的文件

File file = new File(fileDir ,request.getFileName());

//开始接收文件(将传输过来的文件内容输出到file中)

transfer.recieveFile(file);

//此处执行文件传输监听

} catch (SmackException | IOException e) {

e.printStackTrace();

}

}

});

上面代码为设置文件接收监听

4.发送语音、图片消息

我查看了半天的Smack的API,但是没有找到直接发送语音、图片消息的API,我说说我的实现思路。

其实图片、语音都是文件,我们可以把它们当做文件发送给好友。

在发送文件的同时,用描述字段进行标记传输过来的是图片还是语音。

然后在接收到该文件后通过描述字段进行区分当前接收的是图片文件还是语音文件,然后进行区分展示即可,这样就可以达到发送图片消息和语音消息。

但是我的这种实现方式还是有问题的,因为这种方式对于单聊还是可以实现的。但是如果是群聊的话,我就必须给每个人都发一个相同的文件,这样的话一条语音或图片消息,其实是要发送N次的,对于发送人来说流量就多消耗了N-1倍,所以这种方式对于实现群聊是行不通的。

对于群聊发送语音和图片消息,我的思路是这样的:

自己写一个上传文件的服务。

发送语音或图片消息时,将图片或语音通过上述上传服务上传到服务器上。

在上传完语音或图片后,再向聊天室里发送一个文本消息,发送内容为文件的类似下载地址这样的信息,同时还要告诉群成员这个文件是图片还是语音。

群成员接收到这样的特殊文本消息后去自动下载这个文件然后进行展示或是其他处理。

群聊天里发送图片或语音消息的这个实现方式我没有验证,但我觉得应该是可行的。至于单聊发送语音或图片消息的思路我是实现验证成功了的,是可行的。

openfire android 发送图片,基于openfire+smack开发Android即时聊天应用[四]-单人聊天、群聊、发送接收文件等...相关推荐

  1. android如何调取网站后台的图片,基于Bmob后台开发Android的APP项目——从后端获取图片,以及在后端上上传图片...

    第一次写博客感觉还心情还挺激动.当听说有Bmob为移动端制定的后台,正好现在我还并未学会开发后台,于是抱着尝试的心去了解一下(其实我还是个小萌新). 下面这些操作的前提已经创建好项目. 1 . 直接在 ...

  2. 基于openfire+smack开发Android即时聊天应用[三]-账号信息、添加好友、JID理解等

    基于openfire+smack开发Android即时聊天应用[三]-账号信息.添加好友.JID理解等 标签: SmackOpenfireandroid 2015-10-30 18:06  3068人 ...

  3. Android基于环信开发的即时通讯APP

    Android基于环信开发的即时通讯APP,源代码在Github上,GitHub地址为:https://github.com/PowerDos/BLChat ,希望能够帮到你们,下面是系统简介. 简介 ...

  4. android studio 课程表,基于课程表的安卓Android手机控制APP设计(AndroidStudio,SQLite)(含录像)...

    基于课程表的安卓Android手机控制APP设计(AndroidStudio,SQLite)(含录像)(毕业论文12000字,程序代码) 摘 要 随着IT技术的发展,以前老套的课程表内容查询管理方式已 ...

  5. golang开发android的jni,用纯Golang开发Android与IOS应用

    Golang1.4就对Android开发做了些支持,1.5版本前几天好像发布了,特意看了整理下,1.5支持32位与64位的android与IOS应用开发了,当然还不是很好用,听说性能比Java做的程序 ...

  6. android jni 结构体_Android应用开发Android JNI-c/c++调用java方法

    本文将带你了解Android应用开发Android JNI-c/c++调用java方法,希望本文对大家学Android有所帮助. " Android   JNI-c/c++调用java方法, ...

  7. Android 视频图片 轮播,详解android 视频图片混合轮播实现

    循环添加视频view  图片view for (int i = 0 ;i if (beansarraylist.get(i).gettype()==1){ videoplayer = new nice ...

  8. Android官方开发文档Training系列课程中文版:通过NFC共享文件之从其它设备接收文件

    原文地址:http://android.xsoftlab.net/training/beam-files/receive-files.html Android Beam文件传输系统会将文件拷贝到接收设 ...

  9. java多人聊天室实现(可群聊私聊/添加好友/发送文件)

    一.功能介绍 本程序基于websocket实现,程序主要借鉴参考 https://www.cnblogs.com/csu-lmw/p/10981374.html,并在原程序的基本框架下扩充了添加好友以 ...

最新文章

  1. hbuilder egit插件的安装使用--项目文件丢失的教训
  2. StringBuilder对象的常用方法 c#1614651638
  3. 高性能 php api 开发,ThinkPHP 3.2 性能优化,实现高性能API开发
  4. Django框架 day02
  5. linux查看程序写文件内容,Linux 文件内容查看命令
  6. 战神笔记本电脑自带access吗_书评:6本二次元小说,每一本都很有想象力,你都读过吗?...
  7. 资产管理界的风控大师-贝莱德BlackRock集团
  8. 解决Apex英雄下载慢、origin平台下载打开的究极3种方法
  9. java架构师证书_java架构师证书怎么考?做架构师有什么要求?
  10. STM32单片机Flash模拟EEPROM
  11. 单片机蜂鸣器的控制程序与驱动电路图
  12. 用计算机怎么计算税率表,个税税率表计算器
  13. 再爆hzhost6.5虚拟主机管理系统的SQL注入漏洞
  14. 户外佩戴哪款耳机好、户外运动耳机推荐
  15. 定位推送分享轻社交网络平台《足迹》——数据库设计
  16. Spring官方文档翻译(7章)
  17. 《计算传播学导论》读书笔记:第二章 文本分析简介
  18. PreparedStatement和Statement的区别
  19. java图片处理工具类,很实用哦
  20. python 爬取财经新闻股票_Python进阶量化交易专栏场外篇20-爬虫抓取股票论坛帖子...

热门文章

  1. Hutool工具类ExcelWriter导出excel列宽自适应问题解决
  2. 有头发学计算机表情包,沙雕表情包:你的屏幕上有一根头发!
  3. 古剑奇谭2服务器1月20维护,《古剑奇谭二》10月25日例行维护更新公告
  4. CF163E e-Government(ACAM fail树上dfs序)
  5. 飞思卡尔mc9s08烧录方法_飞思卡尔MC9S08及MC9S12 单片机通过SCI口更新程序的一种方法...
  6. 输入框掩码规则与提示技巧
  7. SecureCRT 配色方案(仿 Solarized)
  8. 实战:OpenKruise运维增强控制器-2022.3.12
  9. Java Unsafe数据变量操作
  10. 加码中文 AIGC,IDEA 推出“盖亚计划”