uniapp使用環信外掛實現視訊通話
技術標籤:uni-app學習javascriptuni-app
前言:因為我所做的專案需求是,接到後端推送視訊訊息,APP端點選訊息跳轉到通話頁面進行1對1通話,而後端已經進行賬號好友等的處理,環信提供的demo很多功能前端暫時用不到了,以下就把我用到的羅列出來。
PS:本人並不是前端大神,第一次分享文章,有寫不對的歡迎提出來哦,請大佬們多多包涵!
效果:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210201172544716.png
一、引入外掛
-
首先,在外掛市場https://ext.dcloud.net.cn/plugin?id=3507,按照官方文件整合參考說明,把所用到外掛匯入到你的專案中
-
下載環信demo,以下是需要直接複製貼上到你的專案中的sdk和元件以及你所用到的圖片,圖片暫不展示
-
音視訊SDK在emediaSDK/emedia_for_miniProgram.js裡,引入SDK方法:在App.vue頁面引入
let emedia = uni.emedia = require("./emediaSDK/emedia_for_miniProgram");
emedia.config({useUniappPlugin: true}) // 設定使用uniapp外掛
二、改造demo實現我的專案需求
- 專案只是單純實現接聽視訊通話,所以思路大概如下:
(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頁面:
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>
四、總結與遇到的問題
- 整理demo時因為很多引數被封裝了,單獨引入很容易出錯,建議直接複製,然後再把不需要的程式碼刪掉。
- 注意:groupChatRoom模組、emedia模組等建議不要放在自己新建的子目錄裡,而直接放在pages目錄下,要不然會出現路徑錯誤而無法正常執行。