前言

  之前写了一系列的文章,是关于使用ASP.NET SignalR技术实现LayIM的功能对接,有兴趣的同学移步:http://www.cnblogs.com/panzi/p/5767095.html

  此篇会从头到尾详细介绍开发流程,和对接方法。文章会比较长,准备点小零食,细细品读吧,如果只能够跟着实践最好。

  本篇文章主要讲解内容如下:

  • 融云服务WebSDK的对接
  • LayIM接口的对接
  • 如何将外网js模块化,使其符合layui标准
  • 其他细节等

准备工作

  首先,LayIM不多介绍了,想了解的同学移步:http://www.layui.com/doc/modules/layim.html 。已经了解过的同学可以忽略。因为这次用的是第三方融云服务实现,所以,我们先去官网注册一个账号吧。融云官网地址:http://rongcloud.cn.先注册一个账号,然后选择创建应用。创建应用之后,不用上线,我们选择测试环境即可。我们要的就是拿到appkeyappsecret

js模块化

  为什么叫js模块化呢,一般正常情况下,我们直接按照融云所给的文档里面那么调用即可。文档地址,如果不想去看融云文档的话,可以直接看开发完成后的源代码即可。融云Web开发文档地址:http://www.rongcloud.cn/docs/web.html 。文档中的调用方式如下:

  其实如上图调用也完全没问题,但是我们要开发layui组件的话,就必须要改一下了。因为我们最终想使用 layui.use的方式,而不是直接像上图那样引用js。看一下文档结构:

  

  首先,rmlib对应RongIMLib-2.2.4.min.js,protobuf对应protobuf.2.1.5.min.js,socket 就是业务封装层了。

  rmlib的改造比较简单,直接将js内容粘贴下来,然后根据layui语法exports即可。

  

  为什么要加protobuf这个js呢,说一下原因,首先在原生的融云js调用的时候,会加载一个protobuf.min.js

  

  而由于公司网络不好的原因,经常会出现加载该js卡住的情况,而导致通讯失败,那么我们将他同样复制粘贴下来,改造一下。同样:

  

  当我们美滋滋的执行程序的时候,会发现,这玩意还是会被加载,就会导致出现加载两次的情况,当然这是由于rmlib.js中某段代码加载了该js,我们要做的就是找到那段代码,然后不让它加载就可以了。如下图:

  

  当我们取查代码的时候,哇,忘记了,是压缩过的代码。从何查起呢,查找protobuf,不起作用,后来我就查找了2.1.5,就找到如下这段代码

j=e.1o.iq(s,{a5:r+"5b.4e.2Z/a5-2.1.5.9n.js","ds":r+"5b.4e.2Z/sg.js"

  可以分析一下,r应该是http或者https,而5b.4e.2z对应cdn.ronghub.com,a5应该就是protobuf了,刚开始我是直接把a5删掉,后来发现会出现请求undefined的情况,后来将代码中的,a5改成空值。即 a5:''.大功告成,终于不用再加载cdn的代码了。如下图,只会加载我们自己定义的protobuf.js

  

  最后一个js,socket.由于它是直接封装业务的,所以,我们将依赖加上,然后暴漏socket。到这里的我们的基本准备工作就算结束了,下面就是业务开发了。

  

核心业务-连接服务器

  由于这里呢,我不想把太多.NET的东西带进来,所以,LayIM的对接后台这次就不在阐述了,主要目的是让大家拿到这个东西直接运行通讯功能。主要是前端的开发工作。首先呢,我们知道,既然使用了融云,那就有必要了解一下它是怎么工作的。直接进入代码阶段。(里面内容不懂得可以看融云官方文档,下文中的lib即官网中的RongIMLib)

  很简单,先来一段 init,初始化,很简单吧,这里用到了我们之前拿到的 appkey。

 lib.RongIMClient.init(conf.key);
this.initListener();
this.defineMessage();

  下面呢,我们要监听融云的连接状况,就用到了initListener,详细代码如下,直接从官网文档copy即可。里面会监听到各种状态,包括监听消息接收。

       // 设置连接监听状态 ( status 标识当前连接状态 )
// 连接状态监听器
log('注册服务连接监听事件');
var code = im.code.errorUnKnown;
RongIMClient.setConnectionStatusListener({
onChanged: function (status) {
switch (status) {
case lib.ConnectionStatus.CONNECTED:
break;
case lib.ConnectionStatus.CONNECTING:
break;
case lib.ConnectionStatus.DISCONNECTED:
break;
case lib.ConnectionStatus.KICKED_OFFLINE_BY_OTHER_CLIENT:
break;
case lib.ConnectionStatus.DOMAIN_INCORRECT:
break;
case lib.ConnectionStatus.NETWORK_UNAVAILABLE:
break;
}
listener(code);
}
}); // 消息监听器
RongIMClient.setOnReceiveMessageListener({
// 接收到的消息
onReceived: function (message) {
log(message);
// 判断消息类型
switch (message.messageType) { }
}
});

  最后一个defineMessage,这个有点意思,就是说,融云给我们提供了多种数据类型,但是都不满足我们的需求,所以我们就要自己定义消息类型了。这里呢,我们需要的消息类型是什么呢?先不要看下文,想一下,这里接受消息要定义什么样的类型,根据什么来定义?

  想到了没有?当然是layim想要的消息格式。根据文档可知,就是如下消息类型:

layim.getMessage({
username: "纸飞机" //消息来源用户名
,avatar: "http://tp1.sinaimg.cn/1571889140/180/40030060651/1" //消息来源用户头像
,id: "100000" //消息的来源ID(如果是私聊,则是用户id,如果是群聊,则是群组id)
,type: "friend" //聊天窗口来源类型,从发送消息传递的to里面获取
,content: "嗨,你好!本消息系离线消息。" //消息内容
,cid: 0 //消息id,可不传。除非你要对消息进行一些操作(如撤回)
,mine: false //是否我发送的消息,如果为true,则会显示在右方
,fromid: "100000" //消息的发送者id(比如群组中的某个消息发送者),可用于自动解决浏览器多窗口时的一些问题
,timestamp: 1467475443306 //服务端动态时间戳
});

  为了方便,我只加了其中几个必要的属性。注册自定义消息方法如下:

       var defineMsg = function (obj) {
RongIMClient.registerMessageType(obj.msgName, obj.objName, obj.msgTag, obj.msgProperties);
}
//注册普通消息
var textMsg = {
msgName: 'LAYIM_TEXT_MESSAGE',//自己定义的名称
objName: 'LAYIM:CHAT',
msgTag: new lib.MessageTag(false, false),
msgProperties: ["username", "avatar", "id", "type", "content"]
};
//注册
defineMsg(textMsg);

  init完了之后我们要做什么呢,就需要用户连接服务器了,那么融云连接服务器是需要根据用户id生成一个token的,涉及到服务端的东西。这里怎么避免先不用服务端的呢,我们可以在融云接口调试里面自己根据用户id生成token,因为token是永久性的(可以设置),所以,我们如果想做测试,可以直接生成两个token即可,不过,因为后台我已经完成了token的生成功能,所以,自己生成token需要大家自行去官网找一下。找到API调试,输入用户id得到token复制即可。

  

  当我们拿到token之后呢,我们连接一下服务器:

  

         RongIMClient.connect(token, {
onSuccess: function (userId) {
  //连接成功
},
onTokenIncorrect: function () {
              //token错误,如果出现token错误,我们重新生成一个即可
},
onError: function (errorCode) {
var info = '';
var code = im.code.errorUnKnown;
switch (errorCode) {
case RongIMLib.ErrorCode.TIMEOUT:
//超时break;
case RongIMLib.ErrorCode.UNKNOWN_ERROR:
//未知错误break;
case RongIMLib.ErrorCode.UNACCEPTABLE_PaROTOCOL_VERSION:
//版本不正确break;
case RongIMLib.ErrorCode.IDENTIFIER_REJECTED:
//被拒绝break;
case RongIMLib.ErrorCode.SERVER_UNAVAILABLE:
//服务不可用break;
}
}
});

  我们连接之后呢,打开调试看一下network,可以看到,websocket连接,已经成功了。

  

  看一下日志打印:

  

核心业务-发送消息

  那么上一步已经连接成功了,下一步,我们就要发送消息了。之前已经定义好了消息类型,根据融云文档提供的方法,我们将消息组织好,发送即可。首先呢,这里要用到layim的 sendMessage监听方法了。

                layim.on('sendMessage', function (data) {
//调用socket方法,发送消息
im.sendMsg(data);
});

  是不是很简单,先看一下 layim提供的data是神马东东:

  

  里面的内容不用我多解释了吧,我们只要将mine和to解析一下,然后转换成我们想要的格式即可,这里要注意,group 和 friend 有些区别。请看代码:

sendMsg: function (data) {
//根据layim提供的data数据,进行解析
var mine = data.mine;
var to = data.to;
var id = conf.uid || mine.id;//当前用户id
var group = to.type == 'group';
if (group) {
id = to.id;//如果是group类型,id就是当前groupid,切记不可写成 mine.id否则会出现一些问题。
}
//构造消息
var msg = {
username: mine.username
, avatar: mine.avatar
, id: id
, type: to.type
, content: mine.content
}
//这里要判断消息类型
var conversationType = group ? lib.ConversationType.GROUP : lib.ConversationType.PRIVATE; //私聊,其他会话选择相应的消息类型即可。
var targetId = to.id;
//构造消息体,这里就是我们刚才已经注册过的自定义消息
var detail = new RongIMClient.RegisterMessage.LAYIM_TEXT_MESSAGE(msg);
//发送消息
RongIMClient.getInstance().sendMessage(conversationType, targetId, detail, {
onSuccess: function (message) {
log('发送消息成功');
},
onError: function (errorCode) {
}
});
},

  当我们发送消息之后,对方肯定会收到。(除了初始化有问题之外可能收不到,第三方还是比较稳定的,消息都能送达)我们看一下接收到的消息格式,一大堆,其实对我们有用的有timestamp和content里面的内容。

  

  因为之前我们已经初始化了消息接收监听事件。所以,后边我们简单的一句调用就可以了。

   layim.getMessage(message.content);

效果预览

  

  效果虽然有了,但是和真正的应用还有很大的差距,不过,那些都可以在修改socket.js来满足需求,同样,新手可以引用此组件轻松实现聊天功能对接,而且不用写很多代码。下面看一下最终的代码编写方式:

  

  现在你无需关心layim是怎么接收消息的,以及他的消息格式类型是什么,你只要引入相应的组件,然后做一下简单的配置,即可完成通讯功能,对于想快速开发并且,不需要保存消息历史记录的需求,这个东西就很方便了。对接起来也容易,因为并不是他简单,而是核心内容已经给封装好了,做一个简单的配置即可使用。

细节补充

  日志打印是否开放:

  //记录日志
var log = function (msg) {
conf.log && console.log(msg);
}

  监听方法的实现,抄袭layim 嘿嘿。

 //事件监听
var listener = function (code) {
code && (call['status'] ? call['status'](code) : log(code)); }

  如果初始化比较慢,为了不影响消息发送,采用临时数组保存。

  sendMsgWithQueue: function (data) {
if (!im.connected) {
log('当前服务器未连接,将消息加入到未发送队列');
msgQueue.push(data);
} else {
this.sendMsg(data);
}
},

  连接成功之后,消息发送

 connectSuccess: function (uid) {
im.code.usuccess.uid = uid;
im.connected = true;//连接成功 listener(im.code.usuccess);
if (msgQueue.length) {
//队列中有消息,发送出去
for (var i = 0; i < msgQueue.length; i++) {
im.sendMsg(msgQueue[i]);
}
msgQueue = [];
}
},

  其他细节有兴趣的同学可以看看代码,并给出修改意见,谢谢大家。请注意,本文依赖于Layim3.0+版本。

总结

  写一篇文章比我开发时间都多了,不过总结一下也是好的,希望能帮到一些需要的同学。同时,完整开发版我会继续开发下去,由于使用了第三方,所以通讯逻辑我就不会在去关心,重点放在项目的架构上,以及其他东西的研究。如果你读到了这里,非常感谢。

  github地址:https://github.com/fanpan26/LayIM_NetClient/blob/master/LayIM_RongCloud_Chat/Scripts/im/rc/socket.js

干货!手把手教你如何使用第三方通讯服务实现LayIM Socket组件开发。的更多相关文章

  1. 周一干货~手把手教你安装 Visual Studio 安卓模拟器

    干货~手把手教你安装 Visual Studio 安卓模拟器 转 http://mini.eastday.com/mobile/171107134734194.html# 今天软妹为大家带来一篇来自M ...

  2. 手把手教Android商业项目-即时通讯-i美聊

    [课程概况] 手把手教你从无到有的完整实现一个Android商业项目,是目前整个市场上所没有的课程,废话不多说,请往下看. [项目概况] 项目名称:i美聊 所属领域:移动社交 即时通讯   代码行数: ...

  3. 干货 | 手把手教你搭建一套OpenStack云平台

    1 前言 今天我们为一位朋友搭建一套OpenStack云平台. 我们使用Kolla部署stein版本的OpenStack云平台. kolla是用于自动化部署OpenStack的一个项目,它基于dock ...

  4. 手把手教你使用“谷歌云消息服务(GCM)"

    原文: http://android.eoe.cn/topic/summary GCM结构概述-GCM Architectural Overview 快速预览* 一个状态通知允许应用程序通知用户一个事 ...

  5. 25、手把手教你Extjs5(二十五)Extjs5常用组件--form的基本用法

    Extjs Form是一个比较常用的控件,主要用来显示和编辑数据的,今天这篇文章将介绍Extjs Form控件的详细用法,包括创建Form.添加子项.加载和更新数据.验证等. Form和Form Ba ...

  6. [手把手教你] 用Swoft 搭建微服务(TCP RPC)

    序言 Swoft Framework 基于 Swoole 原生协程的新时代 PHP 全栈式协程框架 Swoft 是什么? Swoft 框架是首个基于Swoole 原生协程的新时代 PHP高性能协程全栈 ...

  7. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  8. 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  9. 自已开发IM有那么难吗?手把手教你自撸一个Andriod版简易IM (有源码)

    本文由作者FreddyChen原创分享,为了更好的体现文章价值,引用时有少许改动,感谢原作者. 1.写在前面 一直想写一篇关于im即时通讯分享的文章,无奈工作太忙,很难抽出时间.今天终于从公司离职了, ...

随机推荐

  1. STM32开发指南-DMA

    DMA,直接存储器访问.传输数据时,外设通过DMA控制器直接访问内存,不经过cpu直接控制传输数据.不需要像中断处理方式需要保留和恢复现场的过程.通过硬件为内存和I/O设备开辟一条直接传送数据的通道, ...

  2. Python+Selenium使用Page Object实现页面自动化测试

    Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通 ...

  3. java 单元测试 注入

    ApplicationContext appContext = new ClassPathXmlApplicationContext("appContext.xml"); MySQ ...

  4. js 截取字符串里的ip

    var ip_reg = /([\d\.]*)/ig; ip = ip_reg.exec(str); return ip; ip_reg会截取 '(' 开始的字符串,中间包含数字和 '.' .

  5. javascript(3)

    使用javascript改进链接 摘自<javascript基础教程> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans ...

  6. kvm下Windows激活方式小计

    使用kvm创建widnwos镜像模板,镜像模板默认是已经激活的正版系统,但是使用程序拷贝部署到不同的机器后发现已经激活的系统变成未激活状态,我们需求就是需要拷贝到不同的机器也能显示是正版系统 网上找了 ...

  7. Android线程之异步消息处理机制(二)——Message、Handler、MessageQueue和Looper

    异步消息处理机制解析 Android中的异步消息处理主要有四个部分组成,Message.Handler.MessageQueue和Looper. 1.Message Message是在线程之间传递的消 ...

  8. VS2010 中 error 2732: 链接规范与的早期规范冲突 的解决

    在实验室做项目的时候遇到了这个问题,终于整明白了. 一般来说这个错误出现在类似以下的语句中 extern "C" int yylex(void); extern "C&q ...

  9. STM32驱动MPU6050

    轴 MEMS轴 MEMS 加速度计,以及一个可扩展的数字运动处理器 DMP(Digital Motion Processor),可用 I2C 接口连接一个第三方的数字传感器,比如磁力计.扩展之后就可以 ...

  10. [转]配置 VIM 的 Go 语言开发环境

    本文是针对像我这样的 VIM 小白而写的,所使用的 VIM-GO 插件虽然步骤简单但不够详细,特写此文以做记录和分享.欢迎各位大神纠正补充! 特别说明 本博文不是 Go 语言环境搭建教程,只是 VIM ...