前言:因为我所做的项目需求是,接到后端推送视频消息,APP端点击消息跳转到通话页面进行1对1通话,而后端已经进行账号好友等的处理,环信提供的demo很多功能前端暂时用不到了,以下就把我用到的罗列出来。

PS:本人并不是前端大神,第一次分享文章,有写不对的欢迎提出来哦,请大佬们多多包涵!

效果:

iOS 环信im UI sdk的集成 环信 uniapp_javascript

iOS 环信im UI sdk的集成 环信 uniapp_javascript_02

一、引入插件

  1. 首先,在插件市场https://ext.dcloud.net.cn/plugin?id=3507,按照官方文档集成参考说明,把所用到插件导入到你的项目中
  2. iOS 环信im UI sdk的集成 环信 uniapp_iOS 环信im UI sdk的集成_03

  3. 下载环信demo,以下是需要直接复制粘贴到你的项目中的sdk和组件以及你所用到的图片,图片暂不展示
  4. iOS 环信im UI sdk的集成 环信 uniapp_JSON_04


  5. iOS 环信im UI sdk的集成 环信 uniapp_uni-app_05

  6. 音视频SDK在emediaSDK/emedia_for_miniProgram.js里,引入SDK方法:在App.vue页面引入
let emedia = uni.emedia = require("./emediaSDK/emedia_for_miniProgram");
    emedia.config({useUniappPlugin: true}) // 设置使用uniapp插件

二、改造demo实现我的项目需求

  1. 项目只是单纯实现接听视频通话,所以思路大概如下:
    (1)项目需求直接用项目的账号进行登录,后端已处理环信的账号登录、好友绑定、创建群聊等,所以我这边登录项目的账号的时候已经跟后端的账号好友绑定了。现在展示一下环信登录的代码:
    (appKey是每个项目使用环信的唯一标识,就相当于微信小程序的appid)
// //接收环信多人视频
var options = {
	apiUrl: 'https://a1.easemob.com',
	user: XX,
	pwd: XX,
	appKey: XX
};
//环信登录
WebIM.conn.open(options);

(2)在App.vue入口页,通过onTextMessage()函数监听到后端传来的视频参数,接收到我的账号、发出视频邀请的账号、会议Id,接收到的参数直接传入groupChatRoom页面:
(这里只展示关键代码,后面附上groupChatRoom页面完整代码)

WebIM.conn.listen({
	onTextMessage(message) {
		console.log("onTextMessage", message);
		if (message) {
		   if (onMessageError(message)) {
		      msgStorage.saveReceiveMsg(message, msgType.TEXT);
		   }
		var my = uni.getStorageSync("myUsername");
		var nameList = {
			myName: my,
			your: message.from,
			groupId: message.ext.conferenceId
		};
		uni.navigateTo({
			url: "/pages/groupChatRoom/groupChatRoom?username=" + JSON.stringify(nameList)
		});
		calcUnReadSpot(message);
		ack(message);
	}
},

(3)groupChatRoom页面里展示的是接收群聊消息,因为后端已做好好友绑定、创建群聊,所以这里我只需列出后端传来的最新消息即可,以下是demo提供的处理数据的代码,有一些数据我的项目需求用不到,不过懒得整理了,处理最后得到的array数据,存入浏览器本地,之后需要调用到:

getChatList() {
    var array = [];
    var member = uni.getStorageSync("member");
    var myName = uni.getStorageSync("myUsername");
    var listGroups = uni.getStorageSync('listGroup') || [];

    for (let i = 0; i < member.length; i++) {
        let newChatMsgs = uni.getStorageSync(member[i].name + myName) || [];
        let historyChatMsgs = uni.getStorageSync("rendered_" + member[i].name + myName) || [];
        let curChatMsgs = historyChatMsgs.concat(newChatMsgs);

        if (curChatMsgs.length) {
            let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
            lastChatMsg.unReadCount = newChatMsgs.length;

            if (lastChatMsg.unReadCount > 99) {
                lastChatMsg.unReadCount = "99+";
            }

            let dateArr = lastChatMsg.time.split(' ')[0].split('-');
            let timeArr = lastChatMsg.time.split(' ')[1].split(':');
            let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2];
            lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
            lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}时${timeArr[1]}分`;
            array.push(lastChatMsg);
        }
    }

    for (let i = 0; i < listGroups.length; i++) {
        let newChatMsgs = uni.getStorageSync(listGroups[i].groupid + myName) || [];
        let historyChatMsgs = uni.getStorageSync("rendered_" + listGroups[i].groupid + myName) || [];
        let curChatMsgs = historyChatMsgs.concat(newChatMsgs);
        if (curChatMsgs.length) {
            let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
            lastChatMsg.unReadCount = newChatMsgs.length;
            if (lastChatMsg.unReadCount > 99) {
                lastChatMsg.unReadCount = "99+";
            }
            let dateArr = lastChatMsg.time.split(' ')[0].split('-') let timeArr = lastChatMsg.time.split(' ')[1].split(':') let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2] lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}时${timeArr[1]}分`
            lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`lastChatMsg.groupName = listGroups[i].groupname array.push(lastChatMsg);
        }
    }

    array.sort((a, b) = >{
        return b.dateTimeNum - a.dateTimeNum;
    });
    console.log('array:', array)
    //2021/02/01新加
    uni.setStorageSync("newChatMsg", array);
    return array;

},

array得到的数据格式:

[{
	"info": {
		"from": "nzXXXXXXfk", //对方的账号
		"to": "lXXXXXX5" //你的账号
	},
	"username": "nzXXXXXXfk",
	"yourname": "nzXXXXXXfk",
	"msg": {
		"type": "txt",
		"url": "",
		"data": [{
			"data": "快来加入会议 - LBJ13H055XXXXXXXXXXXXXC65666",
			"type": "txt"
		}],
		"ext": {
			"conferenceId": "LBJ13H05522QATI4O4DEXH00C65666", //会议id,后端每发一个视频流对应一个id
			"msg_extension": "{\"inviter\":\"nzXXXXXXfk\"}", //处理过的对方的账号
			"password": ""//会议密码
		}
	},
	"style": "",
	"time": "2月1日 15时41分",
	"mid": "txt835802715723401212",
	"chatType": "chat",
	"unReadCount": 10,
	"dateTimeNum": "201154124"
}]

上面的array将会传到comps/chat/chat.vue–comps/chat/msglist/msglist.vue组件里处理,这个组件放的就是群聊窗口,而msglist就是处理消息列表的。
chatMsg获取之前的array值,遍历出msgList消息列表值

let timer = setTimeout(function() {
    me.username = uni.username;
    let username = me.username;
    let myUsername = uni.getStorageSync("myUsername");
    let sessionKey = username.groupId ? username.groupId + myUsername: username.your + myUsername;
    // let chatMsg = uni.getStorageSync(sessionKey) || [];
    // 2021/02/01 新增  !!!!!
    let chatMsg = uni.getStorageSync("newChatMsg");  //更改了这里!!!
    console.log('chatMsg:', chatMsg) me.renderMsg(null, null, chatMsg, sessionKey);
    uni.setStorageSync(sessionKey, null);
    disp.on('em.error.sendMsgErr',
    function(err) {
        curMsgMid = err.data.mid;
        isFail = true;
        console.log('发送失败了');
        return;
        let msgList = me.chatMsg;
        msgList.map(item = >{
            if (item.mid.substring(item.mid.length - 10) == curMsgMid.substring(curMsgMid.length - 10)) {
                item.msg.data[0].isFail = true;
                item.isFail = true;
                me.setData({
                    chatMsg: msgList
                });
            }
        });
        console.log('msgList:', msgList)

        if (me.curChatMsg[0].mid == curMsgMid) {
            me.curChatMsg[0].msg.data[0].isShow = false;
            me.curChatMsg[0].isShow = false;
        }

        uni.setStorageSync("rendered_" + sessionKey, msgList);
    });
    msgStorage.on("newChatMsg", this.dispMsg);
},
1000);

(4)comps/chat/chat.vue页面里点击消息列表,引用父级页面groupChatRoom的onClickInviteMsg方法,并跳转到视频通话页面:emedia页面

comps/chat/chat.vue页面

clickMsg(msg) {
    this.$emit('onClickInviteMsg', msg) console.log('点击消息上一级', msg)
},

groupChatRoom页面

<chat 
	id="groupchat" 
	ref="chat" 
	:username="username" 
	:groupId="groupId" 
	chatType="chatRoom" 
	@onMakeVideoCall="makeVideoCall" 
	@onClickInviteMsg="onClickMsg">
</chat>
export default {
	methods: {
		onClickMsg(msg){
			msg.action = 'join'
			uni.navigateTo({
				url: "../emedia/index?srcData="+JSON.stringify(msg)
			});
		}
   }
}

(5)emedia页面
插件市场里所展示的代码就写在这个页面里边,此时效果已经出来了。

< emlive - player id = "livePlayer"ref = "livePlayer"objectFit = "fit"@bindstatechange = "playerStateChange"@bindnetstatus = "playerNetChange": data - streamId = "item.id": muted = "false": enableCamera = "true": openSpeaker = "openSpeaker"@callbackData = "onPlayerData"style = "width:170px;height:170px; margin: 5px" > </emlive-player>

三、附上groupChatRoom页面完整代码:

<template>
<chat 
	id="groupchat" 
	ref="chat" 
	:username="username" 
	:groupId="groupId" 
	chatType="chatRoom" 
	@onMakeVideoCall="makeVideoCall" 
	@onClickInviteMsg="onClickMsg">
</chat>
</template>

<script>
let disp = require("../../utils/broadcast");
import chat from "../../comps/chat/chat.vue";
var WebIM = require("../../utils/WebIM")["default"];
export default {
  data() {
    return {
      username: {
        your: ""
      },
			search_btn: true,
			search_chats: false,
			show_mask: false,
			yourname: "",
			unReadSpotNum: 0,
			unReadNoticeNum: 0,
			messageNum: 0,
			unReadTotalNotNum: 0,
			arr: [],
			show_clear: false,
			member: "",
			isIPX: false,
			gotop: false,
			input_code: ""
    };
  },

  components: {
    chat
  },

   props: {
    groupId:{
      type:String,
      default:''
    }
  },

  // options = 系统传入的 url 参数
  onLoad(options) {
		let me = this; 
    let username = JSON.parse(options.username);
    this.setData({
      username: username
    });
		uni.username = username;
    uni.setNavigationBarTitle({
      title: username.your
    });
		this.getRoster();
  },
	onShow: function () {
	  this.setData({
	    arr: this.getChatList()
	  });
		if (getApp().globalData.isIPX) {
		  this.setData({
		    isIPX: true
		  });
		}
	},
  onUnload() {
    disp.fire("em.chatroom.leave");
  },
  methods: {
		getRoster() {
		  let me = this;
		  let rosters = {
		    success(roster) {
		      var member = [];
		
		      for (let i = 0; i < roster.length; i++) {
		        if (roster[i].subscription == "both") {
		          member.push(roster[i]);
		        }
		      }
		
		      uni.setStorage({
		        key: "member",
		        data: member
		      });
		      me.setData({
		        member: member
		      });
		      me.listGroups(); //if(!systemReady){
		
		      disp.fire("em.main.ready"); //systemReady = true;
		      //}
		      // me.getChatList()
		      me.setData({
		        arr: me.getChatList(),
		        unReadSpotNum: getApp().globalData.unReadMessageNum > 99 ? '99+' : getApp().globalData.unReadMessageNum
		      });
		    },
		
		    error(err) {
		      console.log(err);
		    }
		
		  };
		  WebIM.conn.getRoster(rosters);
		},
		listGroups() {
		  var me = this;
		  return WebIM.conn.getGroup({
		    limit: 50,
		    success: function (res) {
		      uni.setStorage({
		        key: "listGroup",
		        data: res.data
		      });
		      me.getChatList();
		    },
		    error: function (err) {
		      console.log(err);
		    }
		  });
		},
		makeVideoCall(data){
			console.log('data:', data)
			 if(false){
				uni.showToast({
					title: '请输入会议Id',
					duration: 2000
				});
				return
			}
			uni.navigateTo({
				url: "../emedia/index?srcData="+JSON.stringify(data)
			});
		
		},
		// 不包含陌生人版本
		getChatList() {
		  var array = [];
		  var member = uni.getStorageSync("member");
		  var myName = uni.getStorageSync("myUsername");
		  var listGroups = uni.getStorageSync('listGroup') || [];
		
		  for (let i = 0; i < member.length; i++) {
		    let newChatMsgs = uni.getStorageSync(member[i].name + myName) || [];
		    let historyChatMsgs = uni.getStorageSync("rendered_" + member[i].name + myName) || [];
		    let curChatMsgs = historyChatMsgs.concat(newChatMsgs);
		
		    if (curChatMsgs.length) {
		      let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
		      lastChatMsg.unReadCount = newChatMsgs.length;
		
		      if (lastChatMsg.unReadCount > 99) {
		        lastChatMsg.unReadCount = "99+";
		      }
		
		      let dateArr = lastChatMsg.time.split(' ')[0].split('-');
		      let timeArr = lastChatMsg.time.split(' ')[1].split(':');
		      let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2];
		      lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
		      lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}时${timeArr[1]}分`;
		      array.push(lastChatMsg);
					console.log('array1:', array)
		    }
		  }
		
		  for(let i = 0; i < listGroups.length; i++){
			let newChatMsgs = uni.getStorageSync(listGroups[i].groupid + myName) || [];
			let historyChatMsgs = uni.getStorageSync("rendered_" + listGroups[i].groupid + myName) || [];
			let curChatMsgs = historyChatMsgs.concat(newChatMsgs);
			if(curChatMsgs.length){
				let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
				lastChatMsg.unReadCount = newChatMsgs.length;
				if(lastChatMsg.unReadCount > 99) {
					lastChatMsg.unReadCount = "99+";
				}
				let dateArr = lastChatMsg.time.split(' ')[0].split('-')
				let timeArr = lastChatMsg.time.split(' ')[1].split(':')
				let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2]
				lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}时${timeArr[1]}分`
				lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`
				lastChatMsg.groupName = listGroups[i].groupname
				array.push(lastChatMsg);
				console.log('array2:', array)
			}
		} 
		
		  array.sort((a, b) => {
		    return b.dateTimeNum - a.dateTimeNum;
		  });
			console.log('array3:', array)
			//2021/02/01新加
			uni.setStorageSync("newChatMsg" , array);
		  return array;
			
		},
		onClickMsg(msg){
			msg.action = 'join'
			uni.navigateTo({
				url: "../emedia/index?srcData="+JSON.stringify(msg)
			});
		}
  }
};
</script>
<style>
@import "./groupChatRoom.css";
</style>

四、总结与遇到的问题

  1. 重点!:遇到视频出不来或黑屏,很有可能是因为emedia/index.nvue文件里的getName方法没改成自己的appkey 的appname。 如你的appkey为:1101246581426371#chatdemoui,以下红框改成相应内容

iOS 环信im UI sdk的集成 环信 uniapp_uni-app_06



  1. (这里真的很坑,是问了环信客服才知道)
  2. 注意:groupChatRoom模块、emedia模块等建议不要放在自己新建的子目录里,而直接放在pages目录下,要不然会出现路径错误而无法正常运行。
  3. 要用自定义基座运行,公共测试证书就行,要不然视频会黑屏。
  4. 整理demo时因为很多参数被封装了,单独引入很容易出错,建议直接复制,然后再把不需要的代码删掉。