在 React Native 的利用中,从头开始增加视频通话性能是很简单的。要保障低提早、负载平衡,还要留神治理用户事件状态,十分繁琐。除此之外,还必须保障跨平台的兼容性。
当然有个简略的办法能够做到这一点。在本次的教程中,咱们将应用 Agora Video SDK 来构建一个 React Native 视频通话 App。在深入探讨程序工作之前,咱们将介绍利用的构造、设置和执行。你能够在几分钟内,通过几个简略的步骤,让一个跨平台的视频通话利用运行起来。
咱们将应用 Agora RTC SDK for React Native 来做例子。在这篇文章中,我应用的版本是 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。
- 确保你有一个 Agora 账户,设置一个我的项目,并生成 App ID。
- 从主分支下载并解压 ZIP 文件。
- 运行
npm install
来装置解压目录中的 App 依赖项。 - 导航到
./App.tsx
,将咱们之前生成的 App ID 填入appId: "<YourAppId>"
- 如果你是为 iOS 构建,关上终端,执行
cd ios && pod install
- 连贯你的设施,并运行
npx react-native run-android
/npx react-native run-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<Props, State> { _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 }) }) }...
咱们定义了一个基于类的组件:变量 _engine
将存储从 Agora SDK 导入的 RtcEngine
类实例。这个实例提供了次要的办法,咱们的应用程序能够调用这些办法来应用SDK的性能。
在构造函数中,设置状态变量,并为 Android 上的摄像头和麦克风获取权限。(咱们应用了下文所述的 permission.ts
的帮忙函数)当组件被挂载时,咱们调用 init
函数 ,应用 App ID 初始化 RTC 引擎。它还能够通过调用 engine 实例上的 enableVideo
办法来启用视频。(如果省略这一步,SDK 能够在纯音频模式下工作。)
init函数还为视频调用中的各种事件增加了事件监听器。例如,UserJoined
事件为咱们提供了用户退出频道时的 UID。咱们将这个 UID 存储在咱们的状态中,以便在当前渲染他们的视频时应用。
留神:如果在咱们退出之前有用户连贯到频道,那么在他们退出频道之后,每个用户都会被触发一个 UserJoined
事件。
... /** * @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 ( <View style={styles.max}> <View style={styles.max}> <View style={styles.buttonHolder}> <TouchableOpacity onPress={this.startCall} style={styles.button}> <Text style={styles.buttonText}> Start Call </Text> </TouchableOpacity> <TouchableOpacity onPress={this.endCall} style={styles.button}> <Text style={styles.buttonText}> End Call </Text> </TouchableOpacity> </View> {this._renderVideos()} </View> </View> ) } _renderVideos = () => { const {joinSucceed} = this.state return joinSucceed ? ( <View style={styles.fullView}> <RtcLocalView.SurfaceView style={styles.max} channelId={this.state.channelName} renderMode={VideoRenderMode.Hidden}/> {this._renderRemoteVideos()} </View> ) : null } _renderRemoteVideos = () => { const {peerIds} = this.state return ( <ScrollView style={styles.remoteContainer} contentContainerStyle={{paddingHorizontal: 2.5}} horizontal={true}> {peerIds.map((value, index, array) => { return ( <RtcRemoteView.SurfaceView style={styles.remote} uid={value} channelId={this.state.channelName} renderMode={VideoRenderMode.Hidden} zOrderMediaOverlay={true}/> ) })} </ScrollView> ) }}
接下来,还有开始和完结视频聊天通话的办法。 joinChannel
办法接管 Token、频道名、其余可选信息和一个可选的 UID
(如果你将 UID
设置为 0,零碎会主动为本地用户调配 UID
)。
咱们还定义了渲染办法,用于显示开始和完结通话的按钮,以及显示本地视频源和近程用户的视频源。咱们定义了 _renderVideos
办法 来渲染咱们的视频源,应用 peerIds
数组在滚动视图中渲染。
为了显示本地用户的视频源,咱们应用 <RtcLocalView.SurfaceView>
组件,须要提供 channelId
和 renderMode
。连贯到同一 个 channelId
的用户能够互相通信 ,而 renderMode
用于将视频放入视图中或通过缩放来填充视图。
为了显示近程用户的视频源,咱们应用 SDK 中的 <RtcLocalView.SurfaceView>
组件,它能够获取近程用户的 UID
以及 channelId
和 renderMode
。
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', },})
Style.ts
文件蕴含了组件的 款式。
这就是疾速开发一个 React Native 视频聊天通话 App 的办法。你能够参考 Agora React Native API Reference 去查看能够帮忙你疾速增加更多功能的办法,比方将摄像头和麦克风静音,设置视频配置文件和音频混合等等。
获取更多文档、Demo、技术帮忙
- 获取 SDK 开发文档,可拜访声网文档核心。
- 如需参考各类场景 Demo,可拜访下载核心获取。
- 如遇开发疑难,可拜访论坛发帖发问。
- 理解更多教程、RTE 技术干货与技术流动,可拜访声网开发者社区。
- 欢送扫码关注咱们。