这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

视频通话SDK用的即构的,uniapp插件市场地址

推送用的极光的,uniapp插件市场地址

即构音视频SDK

uniapp插件市场的貌似是有些问题,导入不进项目,直接去官网下载,然后放到项目下的 nativeplugins 目录下,在配置文件中填入即构后台的appID和AppSign,接下来就可以开干了

准备两个页面

首页:/pages/index/index

// 新建一个按钮
<button @click="sendVideo">发送视频邀请</button>// 发送事件,主动发送直接进入下一个页面即可
sendVideo(){uni.navigateTo({url: '/pages/call/call'})
}

通话页:pages/call/call 这个页面会复杂一点

注意这个页面为 nvue 页面

先把所有代码都列出来,再一一做说明

<template><view><view v-if="status === 1" class="switch-bg" :style="{'height': pageH + 'px'}"><view class="top-info u-flex" style="flex-direction: row;"><image src="http://cdn.u2.huluxia.com/g3/M02/32/81/wKgBOVwN9CiARK1lAAFT4MSyQ3863.jpeg" class="avatar"></image><view class="info u-flex u-flex-col u-col-top"><text class="text">值班中心</text><text class="text" style="margin-top: 10rpx;">正在呼叫</text></view></view><view class="switch-handle u-flex u-row-center" style="flex-direction: row; justify-content: center;"><image src="/static/hang_up.png" class="img" @click="hangUp"></image></view></view><view v-if="status === 2" class="switch-bg" :style="{'height': pageH + 'px'}"><view class="top-info u-flex" style="flex-direction: row;"><image src="http://cdn.u2.huluxia.com/g3/M02/32/81/wKgBOVwN9CiARK1lAAFT4MSyQ3863.jpeg" class="avatar"></image><view class="info u-flex u-flex-col u-col-top"><text class="text">值班中心</text><text class="text" style="margin-top: 10rpx;">邀请您视频聊天</text></view></view><view class="switch-handle"><view class="u-flex" style="justify-content: flex-end; flex-direction: row; padding-right: 10rpx; padding-bottom: 30rpx;"><text style="font-size: 26rpx; color: #fff; margin: 10rpx;">切到语音接听</text><image src="/static/notice.png" style="width: 64rpx; height: 52rpx;"></image></view><view class="u-flex u-row-center u-row-between" style="flex-direction: row; justify-content: space-between;"><image src="/static/hang_up.png" class="img" @click="hangUp"></image><image src="/static/switch_on.png" class="img" @click="switchOn"></image></view></view></view><view v-if="status === 3" style="background-color: #232323;" :style="{'height': pageH + 'px'}"><view style="flex-direction: row; flex-wrap: wrap;"><zego-preview-view class="face" style="width: 375rpx; height: 335rpx;"></zego-preview-view><view v-for="(stream, index) in streamList" :key="index" style="flex-direction: row; flex-wrap: wrap;"><zego-view :streamID="stream.streamID" style="width: 375rpx; height: 335rpx;"></zego-view></view></view><view class="switch-handle"><view style="flex-direction: row; justify-content: center; padding-bottom: 30rpx;"><text style="font-size: 26rpx; color: #fff; margin: 10rpx;">{{minute}}:{{seconds}}</text></view><view style="flex-direction: row; justify-content: space-between;"><view style="align-items: center;"><view class="icon-round"><image src="/static/notice.png" class="icon1" mode=""></image></view><text class="h-text">切到语音通话</text></view><view style="align-items: center;"><image src="/static/hang_up.png" class="img" @click="hangUp"></image><text class="h-text">挂断</text></view><view style="align-items: center;"><view class="icon-round" @click="changeCamera"><image src="/static/change_camera.png" class="icon2" mode=""></image></view><text class="h-text">转换摄像头</text></view></view></view></view></view>
</template><script>// #ifdef APP-PLUSvar jpushModule = uni.requireNativePlugin("JG-JPush")import ZegoExpressEngine from '../../zego-express-video-uniapp/ZegoExpressEngine';import {ZegoScenario} from '../../zego-express-video-uniapp/impl/ZegoExpressDefines'import {AppID,AppSign} from '../../zegoKey.js'var instance = ZegoExpressEngine.createEngine(AppID, AppSign, true, 0);// #endifexport default {data() {return {status: 1, // 1: 主动呼叫;2: 被呼叫pageH: '', // 页面高度innerAudioContext: null, //  音乐对象streamList: [],msg_id: '',        // 推送消息idmsg_cid: '',     // 推送cidroomID: 'dfmily110001',publishStreamID: uni.getStorageSync('userinfo').nickname,userID: uni.getStorageSync('userinfo').nickname, userName: uni.getStorageSync('userinfo').nickname, camera_dir: 'before', // 摄像头 before 前置,after 后置};},destroyed: () => {console.log('destroyed');ZegoExpressEngine.destroyEngine();},mounted() {var client = uni.getSystemInfoSync()if (client.platform == 'android') {//安卓事先请求摄像头、麦克风权限var nativeEngine = uni.requireNativePlugin('zego-ZegoExpressUniAppSDK_ZegoExpressUniAppEngine');nativeEngine.requestCameraAndAudioPermission();}},onLoad(opt) {this.getSysInfo();this.playAudio();if(opt.status == 2){        // 带参数 status=2时代表被呼叫this.status = parseInt(opt.status)}if(!opt.status){          // 主动呼叫、需要发推送消息this.getPushCid();}this.initZegoExpress();},onBackPress() {// return true;this.innerAudioContext.stop();this.logout();},methods: {getSysInfo() { // 获取手机信息let sys = uni.getSystemInfoSync()this.pageH = sys.windowHeight},playAudio() { // 播放音乐this.innerAudioContext = uni.createInnerAudioContext();this.innerAudioContext.autoplay = true;this.innerAudioContext.src = '/static/message.mp3';this.innerAudioContext.onPlay(() => {console.log('开始播放');});},stopAudio(){      // 停止播放音乐if (this.innerAudioContext) {this.innerAudioContext.stop()}},hangUp() { // 挂断this.stopAudio();this.sendCustomCommand(500)this.revocationPushMsg();this.logout();uni.navigateBack({delta:1})},switchOn() { // 接通this.stopAudio();this.status = 3this.sendCustomCommand(200)},changeCamera() { // 切换摄像头var instance = ZegoExpressEngine.getInstance();if (this.camera_dir == 'before') {instance.useFrontCamera(false)this.camera_dir = 'after'} else if (this.camera_dir == 'after') {instance.useFrontCamera(true)this.camera_dir = 'before'}},sendCustomCommand(msg){     // 发送自定义信令var instance = ZegoExpressEngine.getInstance();instance.sendCustomCommand(this.roomID, msg, [{"userID": this.userID,"userName": this.userName}], res => {console.log(res)});},getPushCid(){          // 极光推送cid获取uni.request({url: 'https://api.jpush.cn/v3/push/cid',header: {'Authorization': 'Basic ' + this.encode('appKey:masterSecret')},success: (res) => {this.msg_cid = res.data.cidlist[0]this.sendPushMsg();}})},revocationPushMsg(){       // 撤销推送uni.request({url: 'https://api.jpush.cn/v3/push/' + this.msg_id,method: 'DELETE',header: {'Authorization': 'Basic ' + this.encode('appKey:masterSecret')},success: (res) => {console.log(res)}})},sendPushMsg(idArr) {uni.request({url: 'https://api.jpush.cn/v3/push',method: 'POST',header: {'Authorization': 'Basic ' + this.encode('appKey:masterSecret')},data: {"cid": this.msg_cid,"platform": "all","audience": {"registration_id": ['160a3797c8ae473a331']},"notification": {"alert": "邀请通话","android": {},"ios": {"extras": {"newsid": 321}}}},success: (res) => {this.msg_id = res.data.msg_id}})},initZegoExpress(){       // 初始化// instance.startPreview();instance.on('roomStateUpdate', result => {console.log('From Native roomStateUpdate:' + JSON.stringify(result));if (result['state'] == 0) {console.log('房间断开')} else if (result['state'] == 1) {console.log('房间连接中')} else if (result['state'] == 2) {console.log('房间连接成功')}});instance.on('engineStateUpdate', result => {if (result == 0) {console.log('引擎启动')} else if (result['state'] == 1) {console.log('引擎停止')}});instance.on('roomStreamUpdate', result => {var updateType = result['updateType'];if (updateType === 0) {var addedStreamList = result['streamList'];this.streamList = this.streamList.concat(addedStreamList);for (let i = 0; i < addedStreamList.length; i++) {console.log('***********&&&&', addedStreamList[i].streamID)var streamID = addedStreamList[i].streamID;var instance = ZegoExpressEngine.getInstance();instance.startPlayingStream(streamID);}} else if (updateType === 1) {this.removeStreams(result['streamList']);}});instance.on('roomUserUpdate', result => {var updateType = result['updateType'];if (updateType === 0) {this.userID = result.userList[0].userIDthis.userName = result.userList[0].userName// this.userList = this.userList.concat(result['userList']);} else if (updateType === 1) {// this.removeUsers(result['userList']);}});instance.on('IMRecvCustomCommand', result => {var fromUser = result['fromUser'];var command = result['command'];// console.log(`收到${fromUser.userID}的消息:${JSON.stringify(result)}`)if(result.command == 200){console.log('接听视频通话')this.status = 3this.stopAudio();}else if(result.command == 500){console.log('拒绝通话')uni.navigateBack({delta: 1})}});this.login();this.publish();},login() {        // 登录房间var instance = ZegoExpressEngine.getInstance();instance.loginRoom(this.roomID, {'userID': this.userID,'userName': this.userName});},logout() {      // 退出房间var instance = ZegoExpressEngine.getInstance();instance.logoutRoom(this.roomID);this.destroyEngine();},publish() {      // 推流var instance = ZegoExpressEngine.getInstance();instance.startPublishingStream(this.publishStreamID);instance.setVideoConfig({encodeWidth: 375,encodeHeight: 336})},destroyEngine() {ZegoExpressEngine.destroyEngine(boolResult => {this.streamList = [];});},removeStreams(removedStreams) {     // 删除流let leg = this.streamList.lengthfor (let i = leg - 1; i >= 0; i--) {for (let j = 0; j < removedStreams.length; j++) {if (this.streamList[i]) {if (this.streamList[i].streamID === removedStreams[j].streamID) {this.streamList.splice(i, 1)continue; //结束当前本轮循环,开始新的一轮循环}}}}},encode: function(str) {// 对字符串进行编码var encode = encodeURI(str);// 对编码的字符串转化base64var base64 = btoa(encode);return base64;},}}
</script><style lang="scss">.switch-bg {position: relative;background-color: #6B6B6B;}.top-info {padding: 150rpx 35rpx;flex-direction: row;align-items: center;.avatar {width: 150rpx;height: 150rpx;border-radius: 10rpx;}.info {padding-left: 18rpx;.text {color: #fff;font-size: 26rpx;}}}.switch-handle {position: absolute;bottom: 100rpx;left: 0;right: 0;padding: 0 85rpx;.img {width: 136rpx;height: 136rpx;}.icon-round {align-items: center;justify-content: center;width: 136rpx;height: 136rpx;border: 1rpx solid #fff;border-radius: 50%;.icon1 {width: 64rpx;height: 52rpx;}.icon2 {width: 60rpx;height: 60rpx;}}.h-text {margin-top: 10rpx;font-size: 26rpx;color: #fff;}}
</style>

说明:

代码中的masterSecret需要修改为极光后台的masterSecretappKey需要修改为极光后台的appKey

view 部分:

status=1 中的为主动呼叫方进入页面是初始显示内容,最重要的是 hangUp 方法,用来挂断当前邀请

status=2 中的为被邀请者进入页面初始显示的内容,有两个按钮,一个hangUp挂断,一个switchOn 接听

status=3中为接听后显示的内容(显示自己与对方视频画面)

script 部分:

最开始五行是引入相关SDK的。极光推送、即构音视频

onLoad 中有一个判断语句,这个就是用于判断进入页面时是主动呼叫方还是被动答应方的,显示不同内容

if(opt.status == 2){        // 带参数 status=2时代表被呼叫this.status = parseInt(opt.status)
}
if(!opt.status){            // 主动呼叫、需要发推送消息this.getPushCid();
}

sendCustomCommand 是用来在房间内发送自定义信令的,用于通知另一个人是接听了还是挂断了通话

getPushCid 是获取极光推送的cid,避免重复发送推送消息(极光推送)

changeCamera 切换摄像头

revocationPushMsg 撤销推送(主动呼叫方挂断通话)

sendPushMsg 发推送消息

initZegoExpress 初始化即构音视频SDK相关,与官网demo,此处我做了小改动

login 登录即构房间

logout 退出即构房间

publish 推流

destroyEngine 销毁音视频实例

removeStreams 删除流

encode base64转码

在App.vue中进行极光推送的初始化

onLaunch: function() {console.log('App Launch')// #ifdef APP-PLUSif (uni.getSystemInfoSync().platform == "ios") {// 请求定位权限let locationServicesEnabled = jpushModule.locationServicesEnabled()let locationAuthorizationStatus = jpushModule.getLocationAuthorizationStatus()console.log('locationAuthorizationStatus', locationAuthorizationStatus)if (locationServicesEnabled == true && locationAuthorizationStatus < 3) {jpushModule.requestLocationAuthorization((result) => {console.log('定位权限', result.status)})}jpushModule.requestNotificationAuthorization((result) => {let status = result.statusif (status < 2) {uni.showToast({icon: 'none',title: '您还没有打开通知权限',duration: 3000})}})jpushModule.addGeofenceListener(result => {let code = result.codelet type = result.typelet geofenceId = result.geofenceIdlet userInfo = result.userInfouni.showToast({icon: 'none',title: '触发地理围栏',duration: 3000})})jpushModule.setIsAllowedInMessagePop(true)jpushModule.pullInMessage(result => {let code = result.codeconsole.log(code)})jpushModule.addInMessageListener(result => {let eventType = result.eventTypelet messageType = result.messageTypelet content = result.contentconsole.log('inMessageListener', eventType, messageType, content)uni.showToast({icon: 'none',title: JSON.stringify(result),duration: 3000})})}jpushModule.initJPushService();jpushModule.setLoggerEnable(true);jpushModule.addConnectEventListener(result => {let connectEnable = result.connectEnableuni.$emit('connectStatusChange', connectEnable)});jpushModule.addNotificationListener(result => {let notificationEventType = result.notificationEventTypelet messageID = result.messageIDlet title = result.titlelet content = result.contentlet extras = result.extrasconsole.log(result)this.$util.router(`/pages/public/answer?status=2`)});jpushModule.addCustomMessageListener(result => {let type = result.typelet messageType = result.messageTypelet content = result.contentconsole.log(result)uni.showToast({icon: 'none',title: JSON.stringify(result),duration: 3000})})jpushModule.addLocalNotificationListener(result => {let messageID = result.messageIDlet title = result.titlelet content = result.contentlet extras = result.extrasconsole.log(result)uni.showToast({icon: 'none',title: JSON.stringify(result),duration: 3000})})// #endif
},

不要忘了在最开始引入极光推送的插件

var jpushModule = uni.requireNativePlugin("JG-JPush")

官方demo的代码,直接拿过来了。。

其中最重要的就是下面这段,用来监听获取推送消息的,这里如果收到推送消息自动跳转至通话页面,也就是上面status=2的状态下

jpushModule.addNotificationListener(result => {let notificationEventType = result.notificationEventTypelet messageID = result.messageIDlet title = result.titlelet content = result.contentlet extras = result.extrasconsole.log(result)this.$util.router(`/pages/call/call?status=2`)
});

https://juejin.cn/post/6954172658195906567

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--uniapp开发安卓APP视频通话模块初实践相关推荐

  1. uniapp 开发安卓App实现高德地图路线规划导航

    文章目录 技术概述 技术详述 问题与解决 我的总结 参考文献 技术概述 描述这个技术是做什么的/什么情况下会使用到这个技术,学习该技术的原因,技术的难点在哪里.控制在50-100字内. uniapp的 ...

  2. uniApp开发安卓App调试与打包

    总结一下auniapp开发安卓app的调试方式及打包; 代码编程查看文档即可.; 1通过vue-cli方式初始化项目 参考地址: https://uniapp.dcloud.io/quickstart ...

  3. uni-app开发安卓APP运行到真机,未检测到手机或模拟器

    本文以 EMUI10 手机系统为例(华为.荣耀手机) 问题 在开发安卓应用时,因为安卓模拟器性能较差,uni-app官方不推荐使用,所以选择真机运行的方式调试. 上手就踩了一个小坑,在 HBuilde ...

  4. uniapp开发安卓APP测试实现微信支付(初学者都能轻松get)

    前提条件 上代码 打包运行 注意bug!! 这里我们是前后端各一个人测试,这里分享一点前端的代码知识以及我们在测试过程中遇到的bug 前提条件 首先我们要去微信开放平台申请微信开放APP的应用包名和应 ...

  5. uni-app 开发安卓app踩坑记录

    uni-app离线打包android -- 官方文档 Android studio打包apk后弹窗提示"打包时未添加ui模块" 在工程应用目录的build.gradle文件中bui ...

  6. uniapp开发安卓app 实现nfc读卡功能

    <template><view class="content"><view class="box"><view cla ...

  7. 安卓上比较好的python开发软件-手机随时随地写Python,还可以开发安卓APP,太厉害了!...

    python, 近五年最为火爆的编程语言,语法优雅,类库丰富,一行代码即可完成 Java 十行代码量. 本次,舞剑来推荐一款手机端使用 Python 的APP. QPython QPython是安卓上 ...

  8. python安卓版汉化版-手机随时随地写Python,还可以开发安卓APP,太厉害了!

    python, 近五年最为火爆的编程语言,语法优雅,类库丰富,一行代码即可完成 Java 十行代码量. 本次,舞剑来推荐一款手机端使用 Python 的APP. QPython QPython是安卓上 ...

  9. python手机版安卓-手机随时随地写Python,还可以开发安卓APP,太厉害了!

    python, 近五年最为火爆的编程语言,语法优雅,类库丰富,一行代码即可完成 Java 十行代码量. 本次,舞剑来推荐一款手机端使用 Python 的APP. QPython QPython是安卓上 ...

最新文章

  1. Python:SQLMap源码精读—基于错误的盲注(error-based blind)
  2. Linux常用命令——paste
  3. MVC学习笔记1 MVC概述
  4. 梦中女孩,不知还能不能再见你一面
  5. 升级openssh版本
  6. Oracle9i数据库DataGuard实施及维护手册3
  7. 编译使用CEF2623遇到的错误解决办法
  8. 注意力(Attention)
  9. MATLAB中.m文件命名规则
  10. JS之获取银行卡信息
  11. SafeArea的使用
  12. 为什么使用VO,DTO,BO
  13. 亲历医院蹩脚程序(项目)的糟糕
  14. 如何使用光盘启动计算机,如何从光驱启动?从光驱启动方法介绍【图文详解】...
  15. contiki之list(1)
  16. mysql:列类型之float、double
  17. 数据结构c语言进制转换八进制,C语言数据结构中数制转换实例代码
  18. 杰理-手表-AC701-watch-马达振动一次
  19. 如何实现小投资大回报?
  20. 光电二极管放大电路的应用

热门文章

  1. 比我们优秀的人比我们还努力,你有什么资格不去奋斗
  2. Ural 1998 The old Padawan(二分)
  3. lms算法的matlab实现,LMS算法的MATLAB实现
  4. 北邮复试 | 北邮机试往年题汇总 | 计算机院 | 网研院 | 网安院 | 软院
  5. 揭秘:网赚圈很红的“小说项目”!月入十万的裂变套路
  6. Unity3d游戏制作 建模与蒙皮
  7. 300M无线路由器 TL-WR842N - TP-LINK官方网站
  8. matlab-diary函数用法之一
  9. 《电商网络营销理论与实战》
  10. 无人机从零到一(组装、校准到起飞)