如何使用Expo在React Native中实现视频通话功能
在Expo React Native应用中实现视频通话功能
作为Expo新手,推荐两种实现路径:基于WebRTC原生实现(适合自定义需求)或使用第三方视频通话服务(快速上手,降低复杂度)。
方案一:使用Expo WebRTC(原生WebRTC实现)
WebRTC是实时音视频通信的标准协议,Expo提供expo-webrtc库直接支持该能力。
步骤1:安装依赖
npx expo install expo-webrtc expo-permissions
注:
expo-permissions已标记为弃用,也可使用Expo新权限API(如expo-camera的权限方法),上述命令兼容现有项目。
步骤2:配置权限
在app.json的expo字段中添加摄像头和麦克风权限:
"expo": { // ...其他配置 "permissions": [ "CAMERA", "RECORD_AUDIO" ] }
步骤3:实现基础通话逻辑
WebRTC需要信令服务器交换双方的SDP会话描述和ICE候选网络地址,你可以用WebSocket搭建简单信令服务,或使用开源服务。核心代码示例:
import React, { useState, useEffect, useRef } from 'react'; import { View, Button, StyleSheet } from 'react-native'; import { RTCPeerConnection, RTCView, mediaDevices } from 'expo-webrtc'; import * as Permissions from 'expo-permissions'; const VideoCall = () => { const [localStream, setLocalStream] = useState(null); const [remoteStream, setRemoteStream] = useState(null); const peerConnectionRef = useRef(null); // 请求权限并初始化本地流 useEffect(() => { async function setupLocalStream() { const { status } = await Permissions.askAsync(Permissions.CAMERA, Permissions.RECORD_AUDIO); if (status !== 'granted') return; const stream = await mediaDevices.getUserMedia({ video: true, audio: true }); setLocalStream(stream); // 创建PeerConnection实例 const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }); peerConnectionRef.current = pc; // 添加本地流到PeerConnection stream.getTracks().forEach(track => pc.addTrack(track, stream)); // 监听远程流 pc.ontrack = (event) => { setRemoteStream(event.streams[0]); }; // 监听ICE候选,通过信令通道发送给对方 pc.onicecandidate = (event) => { if (event.candidate) { // 示例:socket.emit('ice-candidate', event.candidate); } }; } setupLocalStream(); return () => { localStream?.getTracks().forEach(track => track.stop()); peerConnectionRef.current?.close(); }; }, []); // 创建通话Offer并发送给对方 const createOffer = async () => { const pc = peerConnectionRef.current; const offer = await pc.createOffer(); await pc.setLocalDescription(offer); // 示例:socket.emit('offer', offer); }; return ( <View style={styles.container}> {/* 本地视频画面 */} {localStream && ( <RTCView streamURL={localStream.toURL()} style={styles.video} /> )} {/* 远程视频画面 */} {remoteStream && ( <RTCView streamURL={remoteStream.toURL()} style={styles.video} /> )} <Button title="发起通话" onPress={createOffer} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, alignItems: 'center', }, video: { width: 300, height: 400, marginVertical: 10, backgroundColor: '#000', }, }); export default VideoCall;
方案二:使用第三方视频通话服务(快速上手)
如果不想处理复杂的WebRTC信令和服务器,推荐用成熟的第三方服务(如Agora、Twilio),它们提供Expo专用SDK,开箱即用。
以Agora为例:
步骤1:安装依赖
npx expo install expo-agora
步骤2:获取App ID
去Agora控制台创建项目,获取专属App ID(直接官网注册即可)。
步骤3:实现通话功能
import React, { useState, useEffect } from 'react'; import { View, Button, StyleSheet } from 'react-native'; import { AgoraRtcEngine, AgoraVideoView } from 'expo-agora'; const APP_ID = '你的Agora App ID'; const VideoCallScreen = () => { const [engine, setEngine] = useState(null); const [isJoined, setIsJoined] = useState(false); // 初始化Agora引擎 useEffect(() => { async function initEngine() { const agoraEngine = await AgoraRtcEngine.create(APP_ID); await agoraEngine.enableVideo(); setEngine(agoraEngine); } initEngine(); return () => { engine?.destroy(); }; }, []); // 加入通话频道 const joinChannel = async () => { await engine?.joinChannel(null, 'test-call-channel', null, 0); setIsJoined(true); }; // 离开通话频道 const leaveChannel = async () => { await engine?.leaveChannel(); setIsJoined(false); }; return ( <View style={styles.container}> {isJoined && ( <AgoraVideoView style={styles.video} videoId={0} // 本地视频流ID mode="rtc" channelId="test-call-channel" /> )} <Button title={isJoined ? '结束通话' : '加入通话'} onPress={isJoined ? leaveChannel : joinChannel} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, video: { width: 300, height: 400, marginBottom: 20, backgroundColor: '#000', }, }); export default VideoCallScreen;
新手提示
- 优先选第三方服务:自己搭建WebRTC信令服务器需要后端知识,第三方服务能让你快速完成功能,专注业务逻辑。
- 测试用真机:Expo Go在模拟器上可能无法调用摄像头,建议用两台真机测试通话。
- 处理权限拒绝:一定要捕获用户拒绝权限的情况,避免应用崩溃。
- 自定义开发客户端:如果Expo Go不满足需求,可使用
npx expo run:android/ios构建自定义开发客户端。
内容的提问来源于stack exchange,提问作者Itay Lador
相关产品推荐
相关产品推荐

