當前位置:網站首頁>uni-app技術分享| uni-app轉小程序-實時消息

uni-app技術分享| uni-app轉小程序-實時消息

2022-05-14 04:20:46anyRTC

微信小程序 實現實時消息與 uniapp 轉碼成微信小程序 實現實時消息兩者是一樣的,區別僅僅是一個是原生小程序一個是 uniapp 轉碼成小程序。
本文主要簡單實現點對點消息與呼叫邀請等相關功能實現。
uniapp轉碼成小程序邏輯與小程序邏輯基本一致。

引入 RTM SDK

使用 web RTM-SDK 即可,小程序的實時消息與 WEB 的實時消息共用 SDK。

使用 1.0.5 版本,否則轉成小程序時可能會無法正常使用

npm i ar-rtm-[email protected]1.0.5
// 引入 anyRTM 
import ArRTM from "ar-rtm-sdk"

代碼封裝

你可以在頁面裏邊直接調用,也可單獨封裝成一個 js。
本人喜歡將 RTM 封裝成一個 js 文件。

本地存放

const Store = {
    
	// RTM 客戶端
	rtmClient: null,

	// 主叫邀請實例
	localInvitation: null,
	// 被叫收到的邀請實例
	remoteInvitation: null,
}

回調封裝

本文僅進行簡單封裝,如需更複雜邏輯請自行更改。

// RTM 監聽事件
const rtmEvent = {
    
	// 主叫:被叫已收到呼叫邀請
	localInvitationReceivedByPeer: () => {
    
		uni.hideToast();
		uni.showToast({
    
			title: '被叫已收到呼叫邀請',
			icon: 'none',
			duration: 2000,
			mask: true,
		});

	},
	// 主叫:被叫已接受呼叫邀請
	localInvitationAccepted: async (response) => {
    
		console.log("主叫:被叫已接受呼叫邀請", response);
		uni.hideToast();
		uni.showToast({
    
			title: '被叫接受呼叫邀請',
			icon: 'none',
			duration: 2000,
			mask: true,
		});

	},
	// 主叫:被叫拒絕了你的呼叫邀請
	localInvitationRefused: (response) => {
    
		console.log("主叫:被叫拒絕了你的呼叫邀請", response);
		uni.hideToast();
		uni.showToast({
    
			title: '被叫拒絕呼叫邀請',
			icon: 'none',
			duration: 2000,
			mask: true,
		});
	},
	// 主叫:呼叫邀請進程失敗
	localInvitationFailure: (response) => {
    
		console.log("主叫:呼叫邀請進程失敗", response);
		uni.hideToast();
		uni.showToast({
    
			title: '呼叫邀請失敗',
			icon: 'error',
			duration: 2000,
			mask: true,
		});
	},
	// 主叫:呼叫邀請已被成功取消 (主動掛斷)
	localInvitationCanceled: () => {
    
		console.log("主叫:呼叫邀請已被成功取消 (主動掛斷)");
	},

	// 被叫:監聽收到來自主叫的呼叫邀請
	RemoteInvitationReceived: async (remoteInvitation) => {
    
		console.log("監聽收到來自主叫的呼叫邀請", remoteInvitation);
		// 監聽回調
		rtmInternal.inviteProcessing(remoteInvitation)
		// 顯示模態彈窗
		uni.showModal({
    
			title: '提示',
			content: '收到來自主叫的呼叫邀請',
			cancelText: '拒絕',
			confirmText: '接聽',
			success: function(res) {
    
				if (res.confirm) {
    
					console.log('用戶點擊確定');
					remoteInvitation.accept();
				} else if (res.cancel) {
    
					console.log('用戶點擊取消');
					remoteInvitation.refuse();
				}
			}
		});
	},
	// 被叫:監聽接受呼叫邀請
	RemoteInvitationAccepted: async () => {
    
		console.log("被叫 接受呼叫邀請");
		uni.hideToast();
		uni.showToast({
    
			title: '接受呼叫邀請',
			icon: 'success',
			duration: 2000,
			mask: true,
		});
	},
	// 被叫:監聽拒絕呼叫邀請
	RemoteInvitationRefused: () => {
    
		console.log("被叫 拒絕呼叫邀請");
		uni.hideToast();
		uni.showToast({
    
			title: '拒絕呼叫邀請',
			icon: 'success',
			duration: 2000,
			mask: true,
		});
	},
	// 被叫:監聽主叫取消呼叫邀請
	RemoteInvitationCanceled: () => {
    
		console.log("主叫 取消呼叫邀請");
		uni.hideToast();
		uni.showToast({
    
			title: '主叫取消呼叫',
			icon: 'success',
			duration: 2000,
			mask: true,
		});
	},
	// 被叫:監聽呼叫邀請進程失敗
	RemoteInvitationFailure: () => {
    
		console.log("被叫 呼叫邀請進程失敗");
		uni.hideToast();
		uni.showToast({
    
			title: '呼叫邀請失敗',
			icon: 'error',
			duration: 2000,
			mask: true,
		});
	},


	// 收到來自對端的點對點消息
	MessageFromPeer: (message, peerId) => {
    
		console.log("收到來自對端的點對點消息", message, peerId);
		uni.showToast({
    
			title: '收到' + peerId + '的點對點消息:' + message.text,
			icon: 'none',
			duration: 1000 * 5
		})

	},
	// 通知 SDK 與 RTM 系統的連接狀態發生了改變
	ConnectionStateChanged: (newState, reason) => {
    
		console.log("系統的連接狀態發生了改變", newState);

		switch (newState) {
    
			case "CONNECTED":
				uni.hideLoading();
				// SDK 已登錄 RTM 系統
				uni.showToast({
    
					title: 'RTM 連接成功',
					icon: 'success',
					mask: true,
				})
				break;
			case "ABORTED":
				uni.showToast({
    
					title: 'RTM 停止登錄',
					icon: 'error',
					mask: true,
				});
				console.log("RTM 停止登錄,重新登錄");

				break;
			default:
				wx.showLoading({
    
					title: 'RTM 連接中',
					mask: true,
				})
				break;
		}
	}
}

登錄 RTM 系統

所有與 rtm 相關操作都需要登錄後才可正常使用
成功登錄後即可監聽相關回調

// 初始化
export const InItRtm = async (Config) => {
    
	// 創建 RTM 客戶端
	Store.rtmClient = await ArRTM.createInstance(Config.AppID);

	// RTM 版本
	console.log("RTM 版本", ArRTM.VERSION);

	uni.showLoading({
    
		title: '登錄中',
		mask: true
	})

	// 登錄 RTM
	await Store.rtmClient.login({
    
		token: "",
		uid: Config.userId
	}).then(() => {
    
		uni.hideLoading();
		uni.showToast({
    
			title: '登錄成功',
			icon: 'success',
			duration: 2000
		})
		console.log("登錄成功");

		// 監聽收到來自主叫的呼叫邀請
		Store.rtmClient.on(
			"RemoteInvitationReceived",
			rtmEvent.RemoteInvitationReceived
		);
		// 監聽收到來自對端的點對點消息
		Store.rtmClient.on("MessageFromPeer", rtmEvent.MessageFromPeer);
		// 通知 SDK 與 RTM 系統的連接狀態發生了改變
		Store.rtmClient.on(
			"ConnectionStateChanged",
			rtmEvent.ConnectionStateChanged
		);

	}).catch((err) => {
    
		Store.userId = "";
		uni.hideLoading();
		uni.showToast({
    
			icon: 'error',
			title: 'RTM 登錄失敗',
			mask: true,
			duration: 2000
		});
		console.log("RTM 登錄失敗", err);
	});



}

邏輯方法封裝

// RTM 內部邏輯
export const rtmInternal = {
    
...
}

查詢呼叫用戶是否在線

// 查詢呼叫用戶是否在線
	peerUserQuery: async (uid) => {
    
		const oUserStatus = await Store.rtmClient.queryPeersOnlineStatus([uid]);
		if (!oUserStatus[uid]) {
    
			uni.showToast({
    
				title: '用戶不在線',
				icon: 'error',
				duration: 2000,
				mask: true,
			});
			return false;
		}
		return true;
	},

發起呼叫

// 主叫發起呼叫
	inviteSend: async (peerUserId) => {

		Store.localInvitation = await Store.rtmClient.createLocalInvitation(
			peerUserId
		)
		// 設置邀請內容
		// Store.localInvitation.content = JSON.stringify({});

		// 事件監聽
		// 監聽被叫已收到呼叫邀請
		Store.localInvitation.on(
			"LocalInvitationReceivedByPeer",
			rtmEvent.localInvitationReceivedByPeer
		);
		// 監聽被叫已接受呼叫邀請
		Store.localInvitation.on(
			"LocalInvitationAccepted",
			rtmEvent.localInvitationAccepted
		);
		// 監聽被叫拒絕了你的呼叫邀請
		Store.localInvitation.on(
			"LocalInvitationRefused",
			rtmEvent.localInvitationRefused
		);
		// 監聽呼叫邀請進程失敗
		Store.localInvitation.on(
			"LocalInvitationFailure",
			rtmEvent.localInvitationFailure
		);
		// 監聽呼叫邀請已被成功取消
		Store.localInvitation.on(
			"LocalInvitationCanceled",
			rtmEvent.localInvitationCanceled
		);

		// 發送邀請
		Store.localInvitation.send();
	},

取消呼叫

發起者主動取消呼叫邀請

callCancel: () => {
		if (Store.localInvitation) {
			Store.localInvitation.cancel()
		}
	},

被叫邀請回調綁定

// 被叫收到呼叫邀請處理(給收到的邀請實例綁定事件)
	inviteProcessing: async (remoteInvitation) => {
		// 監聽接受呼叫邀請
		remoteInvitation.on(
			"RemoteInvitationAccepted",
			rtmEvent.RemoteInvitationAccepted
		);
		// 監聽拒絕呼叫邀請
		remoteInvitation.on(
			"RemoteInvitationRefused",
			rtmEvent.RemoteInvitationRefused
		);
		// 監聽主叫取消呼叫邀請
		remoteInvitation.on(
			"RemoteInvitationCanceled",
			rtmEvent.RemoteInvitationCanceled
		);
		// 監聽呼叫邀請進程失敗
		remoteInvitation.on(
			"RemoteInvitationFailure",
			rtmEvent.RemoteInvitationFailure
		);
	},

點對點消息發送

// 發送消息
	sendMessage: (uid, message) => {
		console.log("發送消息", uid, message);
		Store.rtmClient && Store.rtmClient.sendMessageToPeer({
			text: JSON.stringify(message)
		}, uid).catch(err => {
			console.log("發送消息失敗", err);
		});
	},

簡單頁面

html

<view class="content">
		<view class="">
			<text>用戶 ID:{
   {userId}}</text>
		</view>
		<view class="">
			<!-- 登錄 RTM 系統 -->
			<button v-if="page === 0" type="primary" @click="loginRTM">登錄 RTM 系統</button>
			<!-- -->
			<view v-else-if="page === 1" class="">
				<button type="primary" @click="page=2">呼叫邀請</button>
				<button type="primary" @click="page=3">發送消息</button>
			</view>
			<!-- 呼叫邀請 -->
			<view v-else-if="page === 2" class="">
				<!-- 遠端用戶 -->
				<input class="input_automatic" v-model="peerId" type="text" placeholder="請輸入遠端用戶" />
				<button type="primary" @click="invitationCall">發起呼叫</button>
				<button type="primary" @click="invitationCallOff">取消呼叫</button>
			</view>
			<!-- 發送消息 -->
			<view v-else class="">
				<input type="text" class="input_automatic" v-model="peerId" placeholder="請輸入遠端用戶" />
				<input type="text" class="input_automatic" v-model="sendText" placeholder="請輸入消息" />
				<button type="primary" @click="sendMessage">發送</button>
			</view>
		</view>
	</view>

js

	import {
    
		generateNumber
	} from "../../until/until.js"; // 生成隨機數
	import {
    
		InItRtm,
		rtmInternal
	} from "../../until/rtm.js"
	export default {
    
		data() {
    
			return {
    
				page: 0,
				// 本地用戶
				userId: '',
				// 遠端用戶
				peerId: '',
				// 發送的信息
				sendText: ''
			}
		},
		created() {
    
			// 用戶 UID
			this.userId = generateNumber(4) + ''
		},
		methods: {
    
			/** 登錄 RTM 系統 */
			async loginRTM() {
    
				const info = {
    
					/** * 必填 anyRTC 為 App 開發者簽發的 App ID。每個項目都應該有一個獨一無二的 App ID。 * 如果你的開發包裏沒有 App ID,請從anyRTC官網(https://www.anyrtc.io)申請一個新的 App ID */
					AppID: '',
					userId: this.userId
				}
				await InItRtm(info);
				this.page = 1
			},

			/** 呼叫邀請 */
			async invitationCall() {
    
				if (this.peerId === '') return uni.showToast({
    
					title: '請輸入遠端用戶',
					icon: 'error',
				});
				if (this.peerId === this.userId) return uni.showToast({
    
					title: '禁止遠端用戶與本地用戶一致',
					icon: 'none',
				});

				// 查詢用戶是否在線
				const state = await rtmInternal.peerUserQuery(this.peerId);
				if (state) {
    
					rtmInternal.inviteSend(this.peerId)
				} else {
    
					return uni.showToast({
    
						title: '用戶不在線',
						icon: 'error',
					});
				}
			},
			invitationCallOff() {
    
				rtmInternal.callCancel()
			},

			/** 發送消息 */
			async sendMessage() {
    
				if (this.peerId === '') return uni.showToast({
    
					title: '請輸入遠端用戶',
					icon: 'error',
				});
				if (this.peerId === this.userId) return uni.showToast({
    
					title: '禁止遠端用戶與本地用戶一致',
					icon: 'none',
				});
				if (this.sendText === '') return uni.showToast({
    
					title: '請輸入發送信息',
					icon: 'error',
				});
				// 查詢用戶是否在線
				const state = await rtmInternal.peerUserQuery(this.peerId);
				if (state) {
    
					rtmInternal.sendMessage(this.peerId, this.sendText)
				} else {
    
					return uni.showToast({
    
						title: '用戶不在線',
						icon: 'error',
					});
				}
			}
		}
	}

style

.input_automatic {
    
		border: 1px solid;
		height: 40px;
		border-radius: 4px;
		padding: 0 12px;

	}

在這裏插入圖片描述

版權聲明
本文為[anyRTC]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/134/202205140419439117.html

隨機推薦