The first time to write do not spray, civilization, friendship, welcome suggestions, let me progress, thank you big guy

For the video call SDKThe constitutiveThe,Uniapp plug-in market address

Push in theThe auroraThe,Uniapp plug-in market address

That is, audio and video SDK

Uniapp plug-in market seems to have some problems, import into the project, directly go to the official website to download, and then put under the projectnativepluginsDirectory, in the configuration file to construct the background appID and AppSign, and then you can start

Prepare two pages

Home page:/pages/index/index

// Create a new button
<button @click="sendVideo"</button>// Send events directly to the next page
sendVideo(){
    uni.navigateTo({
        url: '/pages/call/call'})}Copy the code

Talk page:pages/call/callThis page will be a little more complicated

Note that this page is fornvuepage

List all the code first, and then explain them

<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">The center on duty</text>
                    <text class="text" style="margin-top: 10rpx;">Is call</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">The center on duty</text>
                        <text class="text" style="margin-top: 10rpx;">You are invited to video chat</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;">Cut to voice answer</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">Cut to voice calls</text>
                                </view>
                                <view style="align-items: center;">
                                        <image src="/static/hang_up.png" class="img" @click="hangUp"></image>
                                        <text class="h-text">Hang up</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">Switching camera</text>
                                </view>
                        </view>
                </view>
        </view>
    </view>
</template>

<script>
	// #ifdef APP-PLUS
	var 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);
	// #endif
	export default {
		data() {
			return {
				status: 1.// 1: active call; 2: called
				pageH: ' '.// Page height
				innerAudioContext: null.// Music object
				streamList: [].msg_id: ' '.// Push message ID
				msg_cid: ' './ / push cid
				roomID: 'dfmily110001'.publishStreamID: uni.getStorageSync('userinfo').nickname,
				userID: uni.getStorageSync('userinfo').nickname, 
				userName: uni.getStorageSync('userinfo').nickname, 
				camera_dir: 'before'.// Camera before front, after rear
			};
		},
		destroyed: () = > {
			console.log('destroyed');
			ZegoExpressEngine.destroyEngine();
		},
		mounted() {
			var client = uni.getSystemInfoSync()
			if (client.platform == 'android') {
				// Android requests camera and microphone permissions in advance
				var nativeEngine = uni.requireNativePlugin('zego-ZegoExpressUniAppSDK_ZegoExpressUniAppEngine'); nativeEngine.requestCameraAndAudioPermission(); }},onLoad(opt) {
			this.getSysInfo();
			this.playAudio();
			
			if(opt.status == 2) {// If status=2, a call is made
				this.status = parseInt(opt.status)
			}
			if(! opt.status){// Active call, need to send push message
				this.getPushCid();
			}
			this.initZegoExpress();
		},
		onBackPress() {
			// return true;
			this.innerAudioContext.stop();
			this.logout();
		},
		methods: {
			getSysInfo() { // Get mobile phone information
				let sys = uni.getSystemInfoSync()
				this.pageH = sys.windowHeight
			},
			playAudio() { // Play music
				this.innerAudioContext = uni.createInnerAudioContext();
				this.innerAudioContext.autoplay = true;
				this.innerAudioContext.src = '/static/message.mp3';
				this.innerAudioContext.onPlay(() = > {
					console.log('Start playing');
				});
			},
			stopAudio(){		// Stop playing music
				if (this.innerAudioContext) {
					this.innerAudioContext.stop()
				}
			},
			hangUp() { / / hang up
				this.stopAudio();
				this.sendCustomCommand(500)
				this.revocationPushMsg();
				this.logout();
				uni.navigateBack({
					delta:1})},switchOn() { / / connected
				this.stopAudio();
				this.status = 3
				this.sendCustomCommand(200)},changeCamera() { // Switch the camera
				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){		// Sends the customized signaling
				var instance = ZegoExpressEngine.getInstance();
				instance.sendCustomCommand(this.roomID, msg, [{
					"userID": this.userID,
					"userName": this.userName
				}], res= > {
					console.log(res)
				});
			},
			getPushCid(){			// Aurora push CID get
				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(){		// Undo push
				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": "Invite call"."android": {},
							"ios": {
								"extras": {
									"newsid": 321}}}},success: (res) = > {
						this.msg_id = res.data.msg_id
					}
				})
			},
			initZegoExpress(){		/ / initialization
				// instance.startPreview();
				instance.on('roomStateUpdate'.result= > {
					console.log('From Native roomStateUpdate:' + JSON.stringify(result));
					if (result['state'] = =0) {
						console.log('Room disconnected')}else if (result['state'] = =1) {
						console.log('Room connection')}else if (result['state'] = =2) {
						console.log('Room connection successful')}}); instance.on('engineStateUpdate'.result= > {
					if (result == 0) {
						console.log('Engine start')}else if (result['state'] = =1) {
						console.log('Engine stop')}}); 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;
							varinstance = 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].userID
						this.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(' received ${fromuser. userID} message :${json.stringify (result)} ')
					if(result.command == 200) {console.log('Answering a Video call')
						this.status = 3
						this.stopAudio();
					}else if(result.command == 500) {console.log('Call denied')
						uni.navigateBack({
							delta: 1}}}));this.login();
				this.publish();
			},
			login() {		// Log in to the room
				var instance = ZegoExpressEngine.getInstance();
				instance.loginRoom(this.roomID, {
					'userID': this.userID,
					'userName': this.userName
				});
			},
			logout() {		// Exit the room
				var instance = ZegoExpressEngine.getInstance();
				instance.logoutRoom(this.roomID);
				this.destroyEngine();
			},
			publish() {		/ / push flow
				var instance = ZegoExpressEngine.getInstance();
				instance.startPublishingStream(this.publishStreamID);
				instance.setVideoConfig({
					encodeWidth: 375.encodeHeight: 336})},destroyEngine() {
				ZegoExpressEngine.destroyEngine(boolResult= > {
					this.streamList = [];
				});
			},
			removeStreams(removedStreams) {		/ / delete the flow
				let leg = this.streamList.length
				for (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; // End the current cycle and start a new cycle}}}}},encode: function(str) {
				// Encode the string
				var encode = encodeURI(str);
				// Convert the encoded string to base64
				var base64 = btoa(encode);
				returnbase64; }}},</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>

Copy the code

Description:

The masterSecret in the code needs to be changed to aurora masterSecret and appKey needs to be changed to Aurora appKey

viewParts:

status=1The incoming page for the active caller is the initial display of content, most importantlyhangUpMethod to hang up the current invitation

status=2Is the initial display of the page for the invitee, there are two buttons, onehangUpHang up, oneswitchOnanswer

status=3Is the content to be displayed after answering the phone (display video screen of oneself and the other party)

scriptParts:

The first five lines introduced the related SDK. Aurora push, namely, sound and video

inonLoadThere is a judgment statement, this is used to determine when entering the page is active call or passive answer, display different content

if(opt.status == 2) {// If status=2, a call is made
    this.status = parseInt(opt.status)
}
if(! opt.status){// Active call, need to send push message
    this.getPushCid();
}
Copy the code

sendCustomCommandIs used to send custom signaling across the room to inform another person whether to answer or hang up a call

getPushCidGet aurora push CID to avoid duplicate push messages (aurora push)

changeCameraSwitching cameras

revocationPushMsgUndo push (active caller hangs up the call)

sendPushMsgSend push messages

initZegoExpressInitialization is related to the audio and video SDK, and the official website demo, here I made a small change

loginLogin is the establishment of the room

logoutExit the room

publishPush the flow

destroyEngineDestroy audio and video instances

removeStreamsDelete the flow

encodeBase64 transcoding

The aurora push is initialized in app.vue

onLaunch: function() {
    console.log('App Launch')
    // #ifdef APP-PLUS
    if (uni.getSystemInfoSync().platform == "ios") {
        // Request location permission
        let locationServicesEnabled = jpushModule.locationServicesEnabled()
        let locationAuthorizationStatus = jpushModule.getLocationAuthorizationStatus()
        console.log('locationAuthorizationStatus', locationAuthorizationStatus)
        if (locationServicesEnabled == true && locationAuthorizationStatus < 3) {
            jpushModule.requestLocationAuthorization((result) = > {
                console.log('Location permission', result.status)
            })
        }


        jpushModule.requestNotificationAuthorization((result) = > {
            let status = result.status
            if (status < 2) {
                uni.showToast({
                    icon: 'none'.title: 'You have not enabled notification privileges'.duration: 3000
                })
            }
        })

        jpushModule.addGeofenceListener(result= > {
            let code = result.code
            let type = result.type
            let geofenceId = result.geofenceId
            let userInfo = result.userInfo
            uni.showToast({
                icon: 'none'.title: 'Trigger geo-fencing'.duration: 3000
            })
        })

        jpushModule.setIsAllowedInMessagePop(true)
        jpushModule.pullInMessage(result= > {
            let code = result.code
            console.log(code)
        })

        jpushModule.addInMessageListener(result= > {
            let eventType = result.eventType
            let messageType = result.messageType
            let content = result.content
            console.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.connectEnable
        uni.$emit('connectStatusChange', connectEnable)
    });

    jpushModule.addNotificationListener(result= > {
        let notificationEventType = result.notificationEventType
        let messageID = result.messageID
        let title = result.title
        let content = result.content
        let extras = result.extras
        console.log(result)
        this.$util.router(`/pages/public/answer? status=2`)}); jpushModule.addCustomMessageListener(result= > {
        let type = result.type
        let messageType = result.messageType
        let content = result.content
        console.log(result)
        uni.showToast({
            icon: 'none'.title: JSON.stringify(result),
            duration: 3000
        })
    })

    jpushModule.addLocalNotificationListener(result= > {
        let messageID = result.messageID
        let title = result.title
        let content = result.content
        let extras = result.extras
        console.log(result)
        uni.showToast({
            icon: 'none'.title: JSON.stringify(result),
            duration: 3000})})// #endif
},
Copy the code

Don’t forget to introduce the aurora push plugin in the beginning

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

Official demo code, straight here.

The most important one is the following paragraph, which is used to monitor and obtain push messages. Here, if you receive push messages, it will automatically jump to the call page, that is, the status=2 above

jpushModule.addNotificationListener(result= > {
    let notificationEventType = result.notificationEventType
    let messageID = result.messageID
    let title = result.title
    let content = result.content
    let extras = result.extras
    console.log(result)
    this.$util.router(`/pages/call/call? status=2`)});Copy the code