android asmack 注册 登陆 聊天 多人聊天室 文件传输
2011-07-16 20:00
423 查看
XMPP协议简介
XMPP协议(ExtensibleMessagingandPresenceProtocol,可扩展消息处理现场协议)是一种基于XML的协议,目的是为了解决及时通信标准而提出来的,最早是在Jabber上实现的。它继承了在XML环境中灵活的发展性。因此,基于XMPP的应用具有超强的可扩展性。并且XML很易穿过防火墙,所以用XMPP构建的应用不易受到防火墙的阻碍。利用XMPP作为通用的传输机制,不同组织内的不同应用都可以进行有效的通信。这篇文章有基本的介绍,IM
InstantMessenger,及时通信软件,就是大家使用的QQ、MSNMessenger和Gtalk等等。其中Gtalk就是基于XMPP协议的一个实现,其他的则不是。当前IM几乎作为每个上网者必然使用的工具,在国外的大型企业中有一些企业级的IM应用,但是其商业价值还没完全发挥出来。设想既然XMPP协议是一个公开的协议,那么每个企业都可以利用它来开发适合本身企业工作,提高自身生产效率的IM;甚至,你还可以在网络游戏中集成这种通信软件,不但让你可以边游戏边聊天,也可以开发出适合游戏本身的IM应用,比如说一些游戏关键场景提醒功能,团队语音交流等等都可以基于IM来实现。本文主要讲解在android使用xmpp协议进行即时通信,所涉及3个主要的东西,它们是openfire、smack和spark,这个三个东东结合起来就是完整的xmppIM实现,这里简单介绍一下这3个东东在下文的作用:openfire主要是作为服务器,负责管理客户端的通信连接,以及提供客户端一些通信信息和连接信息。Smack主要是xmpp协议的实现,提供了一套很好的api,所以下面操作xmpp都是通过使用smack的api来实现,当然因为是在android里,所以使用的是asmack这个包,里面方法跟smack包差不多。Spark是IM客户端的实现,其实就是使用了smack的api实现的。下图展示了三者之间的关系:(很明显这个图是偷别人的,具体是哪里我忘了,因为资料都是复制到文档后慢慢研究看的)从图上可以了解到,client端和server端都可以通过插件的方式来进行扩展,smack是二者传递数据的媒介。
配置openfire服务器
具体步骤请移步:static{ XMPPConnection.DEBUG_ENABLED=true; finalConnectionConfigurationconnectionConfig=newConnectionConfiguration( host,5222,""); //Googletalk //ConnectionConfigurationconnectionConfig=new //ConnectionConfiguration( //"talk.google.com",5222,"gmail.com");
//connectionConfig.setSASLAuthenticationEnabled(false); ActivityMain.connection=newXMPPConnection(connectionConfig); ActivityMain.connection.DEBUG_ENABLED=true; ProviderManagerpm=ProviderManager.getInstance(); configure(pm); }
注册模块
注册有两种方法:一种是用createAccount,不过我测试了一下发现不能创建用户,具体原因不详,下面介绍第二种。如上图:注册成功后服务器将多了ggg用户。
具体实现如下:
Registrationreg=newRegistration(); reg.setType(IQ.Type.SET); reg.setTo(ConnectionSingleton.getInstance().getServiceName()); reg.setUsername(username.getText().toString()); reg.setPassword(password.getText().toString()); reg.addAttribute("android","geolo_createUser_android"); System.out.println("reg:"+reg); PacketFilterfilter=newAndFilter(newPacketIDFilter(reg .getPacketID()),newPacketTypeFilter(IQ.class)); PacketCollectorcollector=ConnectionSingleton.getInstance() .createPacketCollector(filter); ConnectionSingleton.getInstance().sendPacket(reg); result=(IQ)collector.nextResult(SmackConfiguration .getPacketReplyTimeout()); //Stopqueuingresults collector.cancel(); if(result==null){ Toast.makeText(getApplicationContext(),"服, Toast.LENGTH_SHORT).show(); }elseif(result.getType()==IQ.Type.ERROR){ if(result.getError().toString().equalsIgnoreCase( "conflict(409)")){ Toast.makeText(getApplicationContext(),"这, Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(getApplicationContext(),"注, Toast.LENGTH_SHORT).show(); } }elseif(result.getType()==IQ.Type.RESULT){ Toast.makeText(getApplicationContext(),"恭, Toast.LENGTH_SHORT).show(); }
使用注册类,设置好注册的用户名密码和一些属性字段,直接设置包过滤,根据这个过滤创建一个结果集合,发送注册信息包,等待获取结果,剩余就是判断结果内容.
登录模块
登录比较简单ConnectionSingleton.getInstance().connect();//connect Stringaccount=etUsername.getText().toString(); Stringpassword=etPassword.getText().toString(); //保存用户和密码
ActivityLogin.util.saveString(ACCOUNT_KEY,account); ActivityLogin.util.saveString(PASSWORD_KEY,password); ConnectionSingleton.getInstance().login(account,password);//login //loginsuccess System.out.println("loginsuccess"); ActivityLogin.mCurrentAccount=account; System.out.println(ConnectionSingleton.getInstance() .getUser()); //登录成功后发现在线状态
Presencepresence=newPresence(Presence.Type.available); ConnectionSingleton.getInstance().sendPacket(presence); //开始主界面
Intentintent=newIntent(ActivityLogin.this, ActivityMain.class); startActivity(intent);
获取联系人模块(ActivityMain主界面)
获取联系人并将相关信息保存到一个list数组里,最后通知listview更新界面
roster=ActivityMain.connection.getRoster();[code]publicvoidupdateRoster(){
Collection<RosterEntry>entries=roster.getEntries();
for(RosterEntryentry:entries){
System.out.print(entry.getName()+"-"+entry.getUser()+"-"
+entry.getType()+"-"+entry.getGroups().size());
Presencepresence=roster.getPresence(entry.getUser());
System.out.println("-"+presence.getStatus()+"-"
+presence.getFrom());
Useruser=newUser();
user.setName(entry.getName());
user.setUser(entry.getUser());
user.setType(entry.getType());
user.setSize(entry.getGroups().size());
user.setStatus(presence.getStatus());
user.setFrom(presence.getFrom());
userinfos.add(user);
}
rosterAdapter.notifyDataSetChanged();
}
单人聊天模块
第一次修改:在主界面点击选择一个用户,进入聊天Activity,ActivityChat先获取传过来的用户,创建聊天类并对该用户设置消息监听
ChatManagerchatmanager=ConnectionSingleton.getInstance()
.getChatManager();
//getuser
Intentintent=getIntent();
Stringuser=intent.getStringExtra("user");
System.out.println("user:"+user);
//newasession
newChat=chatmanager.createChat(user,null);
//监听聊天消息
chatmanager.addChatListener(newChatManagerListenerEx());
//sendmessage
try{
newChat.sendMessage("imbirdman");
}catch(XMPPExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
监听类
publicclassChatManagerListenerEximplementsChatManagerListener{
@Override
publicvoidchatCreated(Chatchat,booleanarg1){
//TODOAuto-generatedmethodstub
chat.addMessageListener(ml);
}
}
publicclassMessageListenerEximplementsMessageListener{
@Override
publicvoidprocessMessage(Chatarg0,Messagemessage){
Stringresult=message.getFrom()+":"+message.getBody();
System.out.println(result);
android.os.Messagemsg=newandroid.os.Message();
msg.what=0;
Bundlebd=newBundle();
bd.putString("msg",result);
msg.setData(bd);
handler.sendMessage(msg);
}
}