下边接着上边的介绍,给出部分实例代码:
- ===============================================================
- 主动发送信息给某个用户
- ------------------------------------
- XMPPConnection.DEBUG_ENABLED = true;
- //设置服务器地址
- XMPPConnection conn = new XMPPConnection("127.0.0.1");
- conn.connect();
- //输入账号和密码登陆
- conn.login("test2@127.0.0.1", "123456");
- //创建一个和test1的对话,并设置信息监听
- Chat mychat = conn.getManager().create("test1@127.0.0.1",
- new MessageListener() {
- @Override
- public void processMessage(Chat chat,, Message message) {
- String messageBody = message.getBody();
- System.out.println("收到信息:"+messageBody);
- }
- });
- //发送给test1文本信息
- mychat.sendMessage("hello");
- //退出登陆
- conn.disconnect();
- ===============================================================
- 设置自己的登陆状态
- ------------------------------------
- XMPPConnection.DEBUG_ENABLED = true;
- //设置服务器地址
- XMPPConnection conn = new XMPPConnection("127.0.0.1");
- conn.connect();
- //输入账号和密码登陆
- conn.login("test2@127.0.0.1", "123456");
- //设置登陆后的个人状态信息
- Presence p = new Presence(Presence.Type.available);
- p.setStatus("发呆中。。。");
- conn.sendPacket(p);
- //退出登陆
- conn.disconnect();
- ==========================================================================
- 被动接收用户发来的信息
- ------------------------------------
- XMPPConnection.DEBUG_ENABLED = true;
- //设置服务器地址
- XMPPConnection conn = new XMPPConnection("127.0.0.1");
- conn.connect();
- //输入账号和密码登陆
- conn.login("test1@127.0.0.1", "123456");
- //设置信息的监听
- conn.getChatManager().addChatListener(new ChatManagerListener() {
- @Override
- public void chatCreated(Chat chat, boolean createdLocally) {
- chat.addMessageListener(new MessageListener() {
- @Override
- public void processMessage(Chat chat, Message message) {
- String messageBody = message.getBody();
- System.out.println("接收到信息:"+messageBody);
- }
- });
- }
- });
- //退出登陆
- conn.disconnect();
- ==========================================================================
- 获取我的好友列表
- ------------------------------------
- //设置服务器地址
- XMPPConnection conn = new XMPPConnection("127.0.0.1");
- conn.connect();
- //输入账号和密码登陆
- conn.login("test1@127.0.0.1", "123456");
- Collection<RosterEntry> rosters = conn.getRoster().getEntries();
- System.out.println("我的好友列表:=======================");
- for(RosterEntry rosterEntry : rosters){
- System.out.print("name: "+rosterEntry.getName()+",jid: "+rosterEntry.getUser());
- System.out.println("");
- }
- System.out.println("我的好友列表:=======================");
- conn.disconnect();
- ==========================================================================
- 聊天窗口输入状态,使用XEP-0085 协议
- ------------------------------------
- //发送给test1初始文本信息,附带输入状态
- Message mess = new Message();
- mess.addExtension(new ChatStateExtension(ChatState.active));
- mychat.sendMessage(mess);
- //发送给test1初始文本信息,附带正在输入的状态
- Message mess = new Message();
- mess.addExtension(new ChatStateExtension(ChatState.composing));
- mychat.sendMessage(mess);
- //发送给test1初始文本信息,附带暂停输入的状态
- Message mess = new Message();
- mess.addExtension(new ChatStateExtension(ChatState.paused));
- mychat.sendMessage(mess);
- //其他略。。。
- //接收的时候
- public void processMessage(Chat chat, Message message) {
- String messageBody = message.getBody();
- PacketExtension pe;
- pe = message.getExtension("composing","http://jabber.org/protocol/chatstates");
- if(pe != null){
- System.out.println("对方正在输入......");
- }
- pe = message.getExtension("active","http://jabber.org/protocol/chatstates");
- if(pe != null){
- System.out.println("接收到信息:"+messageBody);
- }
- pe = message.getExtension("paused","http://jabber.org/protocol/chatstates");
- if(pe != null){
- System.out.println("对方已暂停输入");
- }
- pe = message.getExtension("inactive","http://jabber.org/protocol/chatstates");
- if(pe != null){
- System.out.println("对方聊天窗口失去焦点");
- }
- pe = message.getExtension("gone","http://jabber.org/protocol/chatstates");
- if(pe != null){
- System.out.println("对方聊天窗口被关闭");
- }
- }
- ==========================================================================
- 接收邀请,加入多人聊天房间
- ------------------------------------
- MultiUserChat.addInvitationListener(conn, new InvitationListener() {
- @Override
- public void invitationReceived(XMPPConnection conn, String room,
- String inviter, String reason, String password, Message message) {
- MultiUserChat multiUserChat = new MultiUserChat(conn, room);
- System.out.println("收到来自 "+inviter+" 的聊天室邀请。邀请附带内容:"+reason);
- try {
- multiUserChat.join("test2", password);
- } catch (XMPPException e) {
- System.out.println("加入聊天室失败");
- e.printStackTrace();
- }
- System.out.println("成功加入聊天室");
- multiUserChat.addMessageListener(new PacketListener() {
- @Override
- public void processPacket(Packet packet) {
- Message message = (Message)packet;
- //接收来自聊天室的聊天信息
- System.out.println(message.getFrom()+":"+message.getBody());
- }
- });
- }
- //发送信息到聊天室
- multiUserChat.sendMessage("新手到来,大家关照!");
- });
- ==========================================================================
- 登陆gtalk
- ------------------------------------
- XMPPConnection conn = new XMPPConnection(new ConnectionConfiguration("talk.google.com", 5222, "gmail.com"));
- conn.connect();
- //输入gtalk的账号密码
- conn.login("88888888", "8888888888");
- Collection<RosterEntry> rosters = conn.getRoster().getEntries();
- //获取gtalk上的好友列表
- System.out.println("我的好友列表:=======================");
- for(RosterEntry rosterEntry : rosters){
- System.out.print("name: "+rosterEntry.getName()+",jid: "+rosterEntry.getUser());
- System.out.println("");
- }
- System.out.println("我的好友列表:=======================");
- conn.disconnect();
- ==========================================================================
转载自:http://blog.csdn.net/ainibaifenbai/article/details/6863767
补充内容,主要是加入房间的操作:
这里简单列出几个函数的实现
1:登录
- public static ConnectionConfiguration connConfig;
- public static XMPPConnection xmppConnection;
- //函数传入的参数为,openfire IP,端口一般为5222,用户名,密码,
- //以及含域名的用户名,如admin@xmpptest
- public static void Login(final String ServerIP, final int serverport,
- final String Username, final String Password, String userid) {
- connConfig = new ConnectionConfiguration(ServerIP, serverport);
- connConfig.setSASLAuthenticationEnabled(false);
- xmppConnection = new XMPPConnection(connConfig); //设定connection配置
- new Thread() {
- @Override
- public void run() {
- try {
- xmppConnection.connect();
- xmppConnection.login(Username, Password); //登录
- } catch (Exception ex) {
- }
- }
- }.start();
- }
登录完了以后便是收发消息
2:接收一对一的对话(不含群组会话)
- public static Chat chat;
- public static ChatManager chatManager;
- // 注册单人对话监听
- protected static void RegisterMessageListener() {
- chatManager = xmppConnection.getChatManager();
- chatManager.addChatListener(new ChatManagerListener() {
- public void chatCreated(Chat chat, boolean arg1) {
- chat.addMessageListener(new MessageListener() { //通过添加一个messaagelitener 来接收消息
- public void processMessage(Chat arg0, Message message) {
- String msg = message.getBody(); //消息主体
- sendhandlemsg(message.getFrom(), msg, false);
- }
- });
- }
- });
- }
3:发送一对一的对话
- public static void semdmessage(final String msg, final String msgto) {
- // 初始化发送消息,chatManager在前文初始化过
- chat = chatManager.createChat(msgto, null);
- new Thread() {
- @Override
- public void run() {
- try {
- //消息发送出去
- chat.sendMessage(msg);
- sendhandlemsg(User, msg, true);
- } catch (XMPPException e) {
- e.printStackTrace();
- }
- }
- }.start();
- }
接下来是加入房间
代码比较多,前两段是查找房间,并储存在一个map中,第三段是加入
4:加入房间
- // 获取房间列表的adpter,当然也可以直接返回list
- public static RoomListAdapter GetRoomAdapter() {
- RoomListAdapter adapter;
- //储存系统最上层的房间名称
- List<Map<String, String>> groups = new ArrayList<Map<String, String>>(); // 一级目录组
- //储存系统最上层房间名称,及其子房间的名称与jid
- List<List<Map<String, String>>> childs = new ArrayList<List<Map<String, String>>>(); // 二级目录组
- Map<String, String> group;
- try {
- //第一次第二个参数为空,可以获取到系统最上层的房间,包括公共房间等
- //但是此时获取的房间是不能加入的
- Collection<HostedRoom> ServiceCollection = MultiUserChat
- .getHostedRooms(xmppConnection, "");
- //遍历讲上文获取到的房间的Jid传入第二个参数,从而获取子房间
- //此时获取的房间便能加入
- for (HostedRoom s : ServiceCollection) {
- group = new HashMap<String, String>();
- group.put("group", s.getName());
- groups.add(group);
- childs.add(GetRoomFromServers(s.getJid()));
- }
- } catch (XMPPException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- adapter = new RoomListAdapter(groups, childs, activity);
- return adapter;
- }
- // 根据服务器获取房间列表
- private static List<Map<String, String>> GetRoomFromServers(String jid) {
- List<Map<String, String>> resultList = new ArrayList<Map<String, String>>();
- Map<String, String> result;
- try {
- Collection<HostedRoom> ServiceCollection = MultiUserChat
- .getHostedRooms(xmppConnection, jid);
- for (HostedRoom s : ServiceCollection) {
- result = new HashMap<String, String>();
- result.put("child", s.getName());
- result.put("childid", s.getJid());
- resultList.add(result);
- }
- } catch (XMPPException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return resultList;
- }
- // 加入一个房间
- public static void JoinRoom(String jid) {
- MultiUserChat multiUserChat = new MultiUserChat(xmppConnection, jid);
- curmultchat = multiUserChat;
- try {
- multiUserChat.join(User); //user为你传入的用户名
- RegisterRoomMessageListener();
- } catch (XMPPException e) {
- e.printStackTrace();
- }
- }
此时你便能在服务器的房间列表中看到你登录的用户了,
然后便是房间内消息的收发
房间发送消息与单人发送消息的方法一致
补充内容三:上边是加房间的操作,下面补充的加好友的操作!
搜索好友的实现:
Form.getSearchForm()这个方法要求的参数是一个服务名,openfire默认的搜索服务是search.+域名。
Form.setAnswer();这个方法意思是,把某个字段设成true就会在那个字段里搜索关键字,search字段设置要搜索的关键字,什么不输入不会返回。
try{
UserSearchManager search = new UserSearchManager(conn);
Form searchForm = search.getSearchForm("search.202.118.239.46");
Form answerForm = searchForm.createAnswerForm();
answerForm.setAnswer("Username", true);
answerForm.setAnswer("search", UserName.getText().toString());
ReportedData data = search.getSearchResults(answerForm,"search.202.118.239.46");
Iterator<Row> it = data.getRows();
Row row=null;
String ansS="";
while(it.hasNext()){
row=it.next();
ansS+=row.getValues("Username").next().toString()+"\n";
//Log.i("Username",row.getValues("Username").next().toString());
}
Toast.makeText(this,ansS, Toast.LENGTH_SHORT).show();
}catch(Exception e){
Toast.makeText(this,e.getMessage()+" "+e.getClass().toString(), Toast.LENGTH_SHORT).show();
}
添加好友的实现:
Roster roster = conn.getRoster();
roster.createEntry(UserName.getText().toString(), null, new String[] { "friends" });
Toast.makeText(this, "success", Toast.LENGTH_SHORT).show();
//列出所有好友的实现:
roster=conn.getRoster();
Collection<RosterEntry> it = roster.getEntries();
friends = new ArrayList<String>();
for(RosterEntry rosterEnter:it){
friends.add(rosterEnter.getUser());
}
if (friends.size()==0){
friends.add("You have no friend");
}
补充内容二:
获取昵称
1
2
3
4
|
VCard vCard =
new
VCard();
vCard.load(Asmackconniciton.connection,number+
"@linhuic99.vicp.cc"
);
Log.d(
"ccc"
,
"昵称是"
+vCard.getOrganization());
//公司
Log.d(
"ccc"
,
"昵称是"
+vCard.getNickName());
|
设置昵称
1
2
3
4
|
VCard vCard1 =
new
VCard();
vCard1.setNickName(
"我是小伍"
);
vCard1.setOrganization(
"当前这个人的电话号码当前这个人的电话号码当前这个人的电话号码"
);
vCard1.save(Asmackconniciton.connection);
|
获取好友头像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
final
VCard vcard =
new
VCard();
try
{
if
(tag.equals(
"my"
)) {
vcard.load(Asmackconniciton.connection);}
else
{
vcard.load(Asmackconniciton.connection, user+
"@linhuic99.vicp.cc"
);}
}
catch
(XMPPException e1) {}
if
(vcard ==
null
|| vcard.getAvatar() ==
null
) {
Log.i(
"xxx"
, vcard +
"是空的"
);
return
;
}
try
{
System.out.println(
"获取用户头像信息: "
+ user);
ByteArrayInputStream bais =
new
ByteArrayInputStream(
vcard.getAvatar());
byte
buf[] =
new
byte
[
1024
];
if
(tag.equals(
"my"
)) {
download =
new
File(Environment.getExternalStorageDirectory()
+
"/.IMTONG/Vcard/Head/my.png"
);
}
else
{
download =
new
File(Environment.getExternalStorageDirectory()
+
"/.IMTONG/Vcard/Head/"
+ filename +
".png"
);
}
FileOutputStream fos =
new
FileOutputStream(download);
do
{
// 循环读取
int
numread = bais.read(buf);
if
(numread == -
1
) {
break
;
}
fos.write(buf,
0
, numread);
}
while
(
true
);
bais.close();
fos.close();
|
补充内容三: 测试过程中openfire服务器返回401错误
错误log如下:
11-10 00:28:07.881: W/System.err(1418): not-authorized(401)
11-10 00:28:07.881: W/System.err(1418): at org.jivesoftware.smackx.ServiceDiscoveryManager.discoverItems(ServiceDiscoveryManager.java:686)
11-10 00:28:07.881: W/System.err(1418): at org.jivesoftware.smackx.ServiceDiscoveryManager.discoverItems(ServiceDiscoveryManager.java:647)
11-10 00:28:07.881: W/System.err(1418): at org.jivesoftware.smackx.muc.MultiUserChat.getHostedRooms(MultiUserChat.java:288)
11-10 00:28:07.881: W/System.err(1418): at com.example.wechatmaindemo.application.MyApplication.GetRoomsFromServer(MyApplication.java:302)
11-10 00:28:07.881: W/System.err(1418): at com.example.wechatmaindemo.FGAddActivity$4.run(FGAddActivity.java:140)
11-10 00:28:07.881: W/System.err(1418): at java.lang.Thread.run(Thread.java:841)
当返回401错误时,需要重启服务器,然后重新测试就没问题了!
补充内容4:解决aSmack不能自动重连
asmact自动重连要能进行,那么asmact必须要使用ReconnectionManager类。可是在asmact的ConnectionConfiguration源码中,没有任何加载ReconnectionManager类的代码,所以在客户端单独使用如下设置是不起作用的:
- configuration.setReconnectionAllowed(true);
还需在代码前静态加载ReconnectionManager,重连才能正常工作:
- static{
- try{
- Class.forName("org.jivesoftware.smack.ReconnectionManager");
- }catch(Exception e){
- e.printStackTrace();
- }
- }
完成后测试,不管是断网还是openfire服务器重启情况下,客户端都会自动重连(如果直接在服务器上关闭会话,是不会重连的),但是这个并不解决与服务器保持长链接的问题,而且目前并未找到如何与服务器保持长链接的解决方案!自动重连的时候,会自动登陆。所以所自己手动重连的代码全删掉吧
补充内容四:关于XMPP掉线的问题
在asmack的开发过程中,发现对应用程序进行测试,在长时间未操作的情况下,会出现自动断开连接的情况,应用程序相应的就会报错了而ANR了.所以这个内容重点解决的是长时间不操作而掉线的问题.
那么我自己想出解决的方法就是开一个服务,这个不用多说了,很简单.在服务中是这么操作的!代码如下:
package com.example.xmppconnection.services;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.pubsub.PresenceState;
import com.example.wechatmaindemo.application.MyApplication;
import com.example.wechatmaindemo.utils.SaveOrGetPassword;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class ConnectionService extends Service{
static {
// 提前加载这个包,设置断线自动重连
try {
Class.forName("org.jivesoftware.smack.ReconnectionManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 操作存储状态xml的类
private static SaveOrGetPassword sop;
private static Handler handler = new Handler();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(runnable).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
// 停止handler
handler.removeCallbacksAndMessages(null);
handler = null;
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
// 每一分钟发送一次包,确保连接
Presence presence = new Presence(Presence.Type.available);
MyApplication.xmppConnection.sendPacket(presence);
Log.d("TestApp", "已经发送包确认");
// 以指定的时间间隔执行
handler.postDelayed(this, 60*1000);
if(MyApplication.xmppConnection.isAuthenticated()&&MyApplication.xmppConnection.isSendPresence()){
Log.d("TestApp", "连接正常,发包正常!");
} else if(MyApplication.xmppConnection.isSocketClosed()){
Log.d("TestApp", "连接已经关闭|!!");
} else if(MyApplication.isOnline(sop.getUsername())){
Log.d("TestApp", "目标用户已经在线!");
}
// 以指定的时间执行
//handler.postAtTime(r, uptimeMillis);
// 监听状态
MyApplication.xmppConnection.addConnectionListener(new ConnectionListener() {
@Override
public void reconnectionSuccessful() {
// TODO Auto-generated method stub
Log.d("TestApp", "重新登陆成功!");
}
@Override
public void reconnectionFailed(Exception arg0) {
// TODO Auto-generated method stub
Log.d("TestApp", "重新登陆失败!");
}
@Override
public void reconnectingIn(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void connectionClosedOnError(Exception arg0) {
// TODO Auto-generated method stub
Log.d("TestApp", "连接已关闭!错误!");
}
@Override
public void connectionClosed() {
// TODO Auto-generated method stub
Log.d("TestApp", "连接已关闭!");
/* // 重新发送包!设置在线
Presence presence = new Presence(Presence.Type.available);
xmppConnection.sendPacket(presence);*/
}
});
}
};
}
重要的是使用了Thread+Handler机制,简单点,这里描述的主要是如何解决这个问题.需要的是Handler确定一个定时任务,设置任务执行的周期,然后不断的向服务器发送请求包,设置自己的在线状态,保持长链接,这样就解决了超时掉线的问题!
补充内容5:创建群聊房间时所遇到的问题!
附上创建群聊房间的代码,因为从网上找不到好的代码,所以这个是自己写的!
/**
* 创建群聊的房间
* 仅仅是临时房间!
* @param room 房间名称
* @param username 用户名
* @param password 密码
*/
public static boolean CreateMultiChatRoom(String room,String username,String password){
// 重新建一个MultiUserChat,后一个参数中的yourService需要替换成你的服务器的名字
MultiUserChat muc = new MultiUserChat(xmppConnection, room+"@conference.yourService");
// 保持最新的更新!
// multiUserChat = muc;
/**
* 从服务器获取所有房间的数据,
* 是否有重复
*/
boolean hasRoom = GetRoomsFromServer(room);
if(hasRoom == false){
// 创建房间
try {
muc.create(room);
Log.d("TestApp", "成功创建房间!");
} catch (XMPPException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Form form = null;
try {
// 获得聊天室的配置表单
form = muc.getConfigurationForm();
// 根据原始表单创建一个要提交的新表单。
Form submitForm = form.createAnswerForm();
// 向要提交的表单添加默认答复
for (Iterator<FormField> fields = form.getFields(); fields.hasNext();) {
FormField field = (FormField) fields.next();
if (!FormField.TYPE_HIDDEN.equals(field.getType())
&& field.getVariable() != null) {
// 设置默认值作为答复
submitForm.setDefaultAnswer(field.getVariable());
}
}
// 设置聊天室的新拥有者 //
List<String> owners = new ArrayList<String>();
owners.add(xmppConnection.getUser());
// 设置聊天室是持久聊天室,即将要被保存下来
submitForm.setAnswer("muc#roomconfig_persistentroom", true);
// 设置为公共房间
submitForm.setAnswer("muc#roomconfig_publicroom", true);
// 设置房主!
submitForm.setAnswer("muc#roomconfig_roomowners", owners);
// 房间仅对成员开放
submitForm.setAnswer("muc#roomconfig_membersonly", false);
// 允许占有者邀请其他人
submitForm.setAnswer("muc#roomconfig_allowinvites", true);
// 能够发现占有者真实 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);
// 进入是否需要密码
submitForm.setAnswer(
"muc#roomconfig_passwordprotectedroom", true);
// 设置进入密码
submitForm.setAnswer("muc#roomconfig_roomsecret", "123456");
// 提交表单使配置生效!
muc.sendConfigurationForm(submitForm);
Log.d("TestApp", "提交表单!");
/**
* 只有重新配置后,才能加入
*/
return true;
} catch (XMPPException e) {
e.printStackTrace();
}
} else {
// 房间名已经存在
return false;
}
return false;
}
我是这么写的,因为很多写法不是报401错误就是403和404错误,这样写完后服务器端就不会报错了.
补充内容6:关于openfire没有消息存储表的解决方法
今天本想开始数据库的设计和编写,却无奈的发现怎么找也找不到有关自己聊天消息的列表,于是百度了一下,发现openfire就是个坑啊,原生的服务器根本就没有相应的生成聊天记录的表格,幸好在google一下后,找到一个国人开发的openfire插件,csdn有下载的(地址是:http://download.csdn.net/download/newjueqi/6024521,不要积分的).然后需要的是注意那个表的名称是:ofMucConversationLog,这样在开发的时候就不怕聊天记录丢失了,顺手可以实现上划刷新聊天记录的功能,记录一下!