Android 即时通讯
在刚开始学习Android的时候,我特别想了解类似于QQ和微信这样的聊天软件是怎么实现的,相
信有很多小伙伴跟我一样很想去了解并自己实现一个聊天工具。那么下面我就来给大家介绍一下我是怎么实现即时通讯的。
首先我们要明白这篇文章是为了解决哪些问题,提出问题如下:
1. 什么是即时通讯?
2. 怎样实现即时通讯?
3. 即时通讯有什么作用?
什么是即时通讯?
在学习即时通讯之前,我们必须明白即时通讯的含义。如同字面上的意思一样就是两个手机即时性的响应进行消息的交互。举个栗子就如同QQ微信等聊天软件一般,在发送者发送消息后接受者很快的接收到消息。
怎样实现即时通讯?
去年的暑假我尝试了很多种方法让两个手机进行通讯。其中包括刷新云端数据库、TCP、UDP等方法。但这些方式都无法达到我想要的效果。下面我们分析一下这些方法的利弊。
刷新云端数据库
这种方式听起来的就很笨拙,由于那时候大一刚学习Android没多久,还不明白些什么,根据自己的想法就是不停的请求腾讯云上的数据库,并判断数据是否改变,改变的话就把新消息提取出来。虽然效果好像差不多,但是这种方式肯定是不能采纳的,首先这样对应用的稳定性有很大伤害,会大量消耗内存、cpu等资源。并且需要不断的连接数据库,当消息数量过多将大量的消耗用户的数据流量。是一种伪通讯手段。现实中并不好用。
TCP
学Android之前估计大家都学过Java,Java中就有对TCP通信中做过简介。它是一种通信方式。通过IP地址和端口号进行连接。其中需要一个服务器端和客户端,在客户端连接上服务器端后才能进行通讯。由于一般的个人开发者不具有服务器。所以,直接的思路就是一个手机作为服务器端,另一个手机作为客户端,让两者进行通讯。按照自己的思路,我也进行了一些尝试,我先是将一个手机的IP地址记录作为服务器端,再通过另一个手机去连接这个手机。在尝试中发现了如下现象
- 一般无法连接成功
- 偶尔可以连接成功
- 若两个手机不是处于同一个WiFi中则无法连接成功
-
手机的IP地址不停的在改变
综合这个问题,我一直没有想明白,到后面才开始有点一些自己的理解。首先连接服务器,是通过IP地址来连接的,手机的IP一般都是由网络*分配的,且不固定,还有就是自己设置的端口号,一些网络运营商可能不支持这种不安全的连接。所以综上所述手机是无法担任服务器。而连接不上服务器,就无法进行两者的信息交互。这种方式是错误的尝试
UDP
相对于TCP,UDP最大的特点就是可以直接发送消息,但是不会管其是否能发送到接收者。这种方式相对于TCP更不稳定。而且有时候可以收的到消息,有时候无法收到消息。若是两个手机处于不同的网络运营商。是无法互发消息的。我的猜测手机通过网络运营商与外界沟通时,需要通过很多设备的转化,而转化的过程中,IP地址就改变了,而使用其他运营商的手机是无法通过这种动态IP联系上接收者的手机。
什么方式更合适?
上面的分析明显的感觉到,网络传输中的复杂性,那么使用什么办法是可以实现通信的效果呢。这个想要了解原理的可以去看看XMPP长连接传输方式,不过这种需要你有一个服务器,并且需要自己去使用openfire去构建一下服务器,使其具备这种功能,由于我暂时还未尝试就简单说一下,要是有时间尝试成功后再分享给大家。
那么对于那些只是想快速的实现这种功能的人来说,可以使用第三方平台所提供的功能,其中有融云、bmob、声网IO,等即时通讯平台。我尝试过融云和bmob的。两者各有千秋,融云的功能相对更多,但封装的较多,bmob使用起来自定义的空间更大一点。
那么这篇文章就是来介绍一下如何使用bmob来实现这个即时通讯的效果。
相对于一些高手来说,直接看官方Demo完全就可以解决了,这个文章主要是针对bmob文档中一些不清晰的地方做解释。官方文档:http://docs.bmob.cn/im/faststart/index.html?menukey=fast_start&key=start_im
不过在此之前你肯定要注册一个开发者账号,并且需要创建一个应用,根据提供的官方文档,集成好sdk并添加相应权限,集成的方式没有什么特别。按照文档一步步就能完成,这里就不详细解释了。不过有个地方提示一下新手,一定要记得添加so文件等配置如果无法在gradle里面添加可以在main文件夹新建一个文件夹“jniLibs”然后将官方demo中的so文件全部复制进去效果如下图。要是可以直接在gradle里面添加就请忽略。里面提供多种消息的发送模式,但是仔细看最主要的还是文本消息的发送方式的微改,所以只要能明白基本的文本消息的交互,其他的就迎刃而解了。对于即时通讯你只需要了解三个点。
- 连接服务器
- 发送消息
-
接收消息
明白这三个,其他的就交给你们自己去扩展了,首先要明白的就是连接服务器,为什么要连接服务器?之前也介绍了,手机与手机之间很难直接通信,需要服务器作为一个介质,作为转发消息的平台。所以想要实现即时通讯,第一步就是连接服务器,下面是官方提供的文档。对于不了解bmob的我做下解释,每个用户都有一个特殊的ID,作为用户的标识,这里直接采用了bmob的用户管理sdk,其中User user = BmobUser.getCurrentUser(context,User.class);是bmob提供的sdk方法,作用就是获取当前登录用户的本地缓存信息。而服务器的连接必须要一个id作为通讯的标识,一般就采取用户的ID,此目的就是在私聊的时候可以通过这个id作为标识符进行两个的关联与通信。对于那些有自己只想自定义用户管理的伙伴来说,你只需要传入自己用户系统中的id作为连接的标识符也是可以达到相同效果的。
User user = BmobUser.getCurrentUser(context,User.class);
BmobIM.connect(user.getObjectId(), new ConnectListener() {
@Override
public void done(String uid, BmobException e) {
if (e == null) {
Logger.i("connect success");
} else {
Logger.e(e.getErrorCode() + "/" + e.getMessage());
}
}
});
要是看了上面连接方式还有不明白那个用户ID的小伙伴,别着急,这里就来讲讲那个id到底有什么作用。bmob中只提供私聊的sdk,那么私聊发消息的时候肯定你得先告诉服务器你这条消息是发给哪个用户的。用户id就能成为这种发送消息的标识。每个连接成功的用户id都会留在服务器上,而服务器就可以通过这个用户id作为标识把消息转发到相应的用户手机上。这么一说是不是就差不多明白了。那么再来看看怎么发送的
bmob提供了消息记录的保存,所以在发送消息之前必须要开启一个私聊会话,官方代码示例如下,看看传入的参数,第一个为bmobInfo,这个东西就是你要发送对象的用户信息,其中包括头像、昵称、id。其中id是必不可少的。但是需要注意:开启私聊会话必须在连接服务器成功的情况下调用,不然会抛出异常。那个跳转聊天界面是一个示例,也就是建议你在这里跳转到你聊天的那个activity里面。这个按照你们自己的需求来弄就行。
BmobIM.getInstance().startPrivateConversation(BmobImUserInfo info, new ConversationListener() {
@Override
public void done(BmobIMConversation c, BmobException e) {
if(e==null){
//在此跳转到聊天页面
Bundle bundle = new Bundle();
bundle.putSerializable("c", c);
startActivity(ChatActivity.class, bundle, false);
}else{
toast(e.getMessage()+"("+e.getErrorCode()+")");
}
}
});
开启私聊后就可以就行发消息了,但是还是有些地方需要注意的。
第一你开启会话后还需要进行一步转化后才能发送消息,这里面是示例代码,若没有进行跳转可直接将getBundle().getSerializable(“c”)替换为上一步的BmobIMConversation c对象。转化后即可发送消息
BmobIMConversation c;
//在聊天页面的onCreate方法中,通过如下方法创建新的会话实例,这个obtain方法才是真正创建一个管理消息发送的会话
c=BmobIMConversation.obtain(BmobIMClient.getInstance(),(BmobIMConversation)getBundle().getSerializable("c"));
这里示例一下文本消息的发送:
BmobIMTextMessage msg =new BmobIMTextMessage();
msg.setContent(text);
c.sendMessage(msg, new MessageSendListener() {
@Override
public void done(BmobIMMessage msg, BmobException e) {
if (e != null) {
toast("发送成功");
}else{
toast("发送失败");
}
}
});
这里面text对象即为你发送的文本内容,就这样消息就能发送过去了,其他的多种类的消息都是基于文本消息的,只要明白了文本消息,其他消息可以自行定义。
不过这个时候就算发送成功了,你也只能看见一个Toast而已。为了查看我们收到的消息,就需要继承一个bmob提供的接收类,这里面就两个方法,一个在线时服务器发来消息时调用,一个查询离线消息。 MessageEvent就是发送过来的信息类,里面包含了很多信息,想详细了解的可以去看文档,要是只想知道内容可以直接.getMessage().getContent(),便可以获取到接收信息的内容。
public class DemoMessageHandler extends BmobIMMessageHandler{
@Override
public void onMessageReceive(final MessageEvent event) {
//当接收到服务器发来的消息时,此方法被调用
}
@Override
public void onOfflineReceive(final OfflineMessageEvent event) {
//每次调用connect方法时会查询一次离线消息,如果有,此方法会被调用
}
}
就这些东西,就完成了一个简单的手机通信。这里给一些建议,因为这里的消息接收类,无法直接把信息传递到activity,如果需要将信息传递过去可以学一下EventBus的使用https://github.com/greenrobot/EventBus 这个可以把消息传送到你想要处理的地方。
即时通讯有什么作用
经过上面的讲解,要是没什么问题的话,应该就能知道实现简单的消息发送。这时候可以想想怎么把这个东西利用到你的项目中,即时通讯不一定只能作为聊天所用,相信很多学习Android的伙伴都有试过写过五子棋或者其他小游戏吧,但是如果只是单机游戏的话,那就显得比较无聊了,为何不把五子棋做成网络对战版呢,既然知道了即时通讯,那么这些就简单了,可以通过即时通讯把双方落棋的位置交互,达到对战的效果,当然这只是举例,有了即时铜须,很多东西都能做的更人性化,希望大家多多尝试。
上一篇: 触发器更改同一个表中的字段