使用Agora SDK开发React Native视频通话App
在 React Native 的应用中,从头开始添加视频通话功能是很复杂的。要保证低延迟、负载平衡,还要注意管理用户事件状态,非常繁琐。除此之外,还必须保证跨平台的兼容性。
当然有个简单的方法可以做到这一点。在本次的教程中,我们将使用 Agora Video SDK 来构建一个 React Native 视频通话 App。在深入探讨程序工作之前,我们将介绍应用的结构、设置和执行。你可以在几分钟内,通过几个简单的步骤,让一个跨平台的视频通话应用运行起来。
我们将使用 来做例子。在这篇文章中,我使用的版本是 v3.1.6。
创建一个Agora账户

找到 "项目管理 "下的 "项目列表 "选项卡,点击蓝色的 "创建 "按钮,创建一个项目。(当提示使用 App ID+证书时,选择只使用 App ID。)记住你的 App ID,它将在开发App时用于授权你的请求。
注意:本文没有采用 Token 鉴权,建议在生产环境中运行的所有RTE App 都采用Token鉴权。有关Agora平台中基于Token的身份验证的更多信息,请在声网文档中心搜索关键词「Token」,参考相关文档。
示例项目结构
这就是我们正在构建的应用程序的结构:
.
├── android
├── components
│ └── Permission.ts
│ └── Style.ts
├── ios
├── App.tsx
.
让我们来运行这个应用
需要安装 LTS 版本的 Node.js 和 NPM。
从主分支下载并解压 ZIP 文件。
运行 来安装解压目录中的 App 依赖项。
导航到 ,将我们之前生成的 App ID 填入
如果你是为 iOS 构建,打开终端,执行
连接你的设备,并运行 / 来启动应用程序。等待几分钟来构建和启动应用程序。
一旦你看到手机(或模拟器)上的主屏幕,点击设备上的开始通话按钮。(iOS模拟器不支持摄像头,所以要用实体设备代替)。
通过以上操作,你应该可以在两个设备之间进行视频聊天通话。该应用默认使用 channel-x 作为频道名称。
应用工作原理
App.tsx
这个文件包含了 React Native 视频通话App中视频通话的所有核心逻辑。
import React, {Component} from 'react'
import {Platform, ScrollView, Text, TouchableOpacity, View} from 'react-native'
import RtcEngine, {RtcLocalView, RtcRemoteView, VideoRenderMode} from 'react-native-agora'
import requestCameraAndAudioPermission from './components/Permission'
import styles from './components/Style'
/**
* @property peerIds Array for storing connected peers
* @property appId
* @property channelName Channel Name for the current session
* @property joinSucceed State variable for storing success
*/
interface State {
appId: string,
token: string,
channelName: string,
joinSucceed: boolean,
peerIds: number[],
}
...
我们开始先写import声明。接下来,为应用状态定义一个接口,包含:
appId:Agora App ID
token:为加入频道而生成的Token。
channelName:频道名称(同一频道的用户可以通话)。
joinSucceed:存储是否连接成功的布尔值。
peerIds:一个数组,用于存储通道中其他用户的UID。
...
export default class App extends Component {
_engine?: RtcEngine
constructor(props) {
super(props)
this.state = {
appId: YourAppId,
token: YourToken,
channelName: 'channel-x',
joinSucceed: false,
peerIds: [],
}
if (Platform.OS === 'android') {
// Request required permissions from Android
requestCameraAndAudioPermission().then(() => {
console.log('requested!')
})
}
}
componentDidMount() {
this.init()
}
/**
* @name init
* @description Function to initialize the Rtc Engine, attach event listeners and actions
*/
init = async () => {
const {appId} = this.state
this._engine = await RtcEngine.create(appId)
await this._engine.enableVideo()
this._engine.addListener('Warning', (warn) => {
console.log('Warning', warn)
})
this._engine.addListener('Error', (err) => {
console.log('Error', err)
})
this._engine.addListener('UserJoined', (uid, elapsed) => {
console.log('UserJoined', uid, elapsed)
// Get current peer IDs
const {peerIds} = this.state
// If new user
if (peerIds.indexOf(uid) === -1) {
this.setState({
// Add peer ID to state array
peerIds: [...peerIds, uid]
})
}
})
this._engine.addListener('UserOffline', (uid, reason) => {
console.log('UserOffline', uid, reason)
const {peerIds} = this.state
this.setState({
// Remove peer ID from state array
peerIds: peerIds.filter(id => id !== uid)
})
})
// If Local user joins RTC channel
this._engine.addListener('JoinChannelSuccess', (channel, uid, elapsed) => {
console.log('JoinChannelSuccess', channel, uid, elapsed)
// Set state variable to true
this.setState({
joinSucceed: true
})
})
}
...
我们定义了一个基于类的组件:变量 将存储从 Agora SDK 导入的 类实例。这个实例提供了主要的方法,我们的应用程序可以调用这些方法来使用SDK的功能。
在构造函数中,设置状态变量,并为 Android 上的摄像头和麦克风获取权限。(我们使用了下文所述的 的帮助函数)当组件被挂载时,我们调用 函数 ,使用 App ID 初始化 RTC 引擎。它还可以通过调用 engine 实例上的 方法来启用视频。(如果省略这一步,SDK 可以在纯音频模式下工作。)
init函数还为视频调用中的各种事件添加了事件监听器。例如, 事件为我们提供了用户加入频道时的 UID。我们将这个 UID 存储在我们的状态中,以便在以后渲染他们的视频时使用。
注意:如果在我们加入之前有用户连接到频道,那么在他们加入频道之后,每个用户都会被触发一个 事件。
...
/**
* @name startCall
* @description Function to start the call
*/
startCall = async () => {
// Join Channel using null token and channel name
await this._engine?.joinChannel(this.state.token, this.state.channelName, null, 0)
}
/**
* @name endCall
* @description Function to end the call
*/
endCall = async () => {
await this._engine?.leaveChannel()
this.setState({peerIds: [], joinSucceed: false})
}
render() {
return (
Start Call
End Call
{this._renderVideos()}
)
}
_renderVideos = () => {
const {joinSucceed} = this.state
return joinSucceed ? (
{this._renderRemoteVideos()}
) : null
}
_renderRemoteVideos = () => {
const {peerIds} = this.state
return (
{peerIds.map((value, index, array) => {
return (
)
})}
)
}
}
接下来,还有开始和结束视频聊天通话的方法。 方法接收 Token、频道名、其他可选信息和一个可选的 (如果你将 设置为 0,系统会自动为本地用户分配 )。
我们还定义了渲染方法,用于显示开始和结束通话的按钮,以及显示本地视频源和远程用户的视频源。我们定义了 方法 来渲染我们的视频源,使用 数组在滚动视图中渲染。
为了显示本地用户的视频源,我们使用 组件,需要提供 和 。连接到同一 个 的用户可以相互通信 ,而 用于将视频放入视图中或通过缩放来填充视图。
为了显示远程用户的视频源,我们使用 SDK 中的 组件,它可以获取远程用户的 以及 和 。
Permission.ts
import {PermissionsAndroid} from 'react-native'
/**
* @name requestCameraAndAudioPermission
* @description Function to request permission for Audio and Camera
*/
export default async function requestCameraAndAudioPermission() {
try {
const granted = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.CAMERA,
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
])
if (
granted['android.permission.RECORD_AUDIO'] === PermissionsAndroid.RESULTS.GRANTED
&& granted['android.permission.CAMERA'] === PermissionsAndroid.RESULTS.GRANTED
) {
console.log('You can use the cameras & mic')
} else {
console.log('Permission denied')
}
} catch (err) {
console.warn(err)
}
}
导出一个函数,向Android上的操作系统申请摄像头和麦克风的权限。
Style.ts
import {Dimensions, StyleSheet} from 'react-native'
const dimensions = {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
}
export default StyleSheet.create({
max: {
flex: 1,
},
buttonHolder: {
height: 100,
alignItems: 'center',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-evenly',
},
button: {
paddingHorizontal: 20,
paddingVertical: 10,
backgroundColor: '#0093E9',
borderRadius: 25,
},
buttonText: {
color: '#fff',
},
fullView: {
width: dimensions.width,
height: dimensions.height - 100,
},
remoteContainer: {
width: '100%',
height: 150,
position: 'absolute',
top: 5
},
remote: {
width: 150,
height: 150,
marginHorizontal: 2.5
},
noUserText: {
paddingHorizontal: 10,
paddingVertical: 5,
color: '#0093E9',
},
})
文件包含了组件的 样式。
这就是快速开发一个 React Native 视频聊天通话 App 的方法。你可以参考 去查看可以帮助你快速添加更多功能的方法,比如将摄像头和麦克风静音,设置视频配置文件和音频混合等等。
获取更多文档、Demo、技术帮助
