【发布时间】:2021-06-28 13:56:29
【问题描述】:
我正在使用 ReactNative 构建一个群视频聊天应用程序。对于视频通话,我使用 Agora for ReactNative,https://www.npmjs.com/package/react-native-agora。但它显示远程用户视频的黑块。
这是我的代码。
const agoraAppId = "xxx";
const channelName = "myChannel";
const cerfificateKey = "xxxxx";
const token = "xxxxx";
import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, Dimensions, PermissionsAndroid, Button, ScrollView } from 'react-native';
import RtcEngine, {RtcLocalView, RtcRemoteView, VideoRenderMode} from 'react-native-agora'
const dimensions = {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
}
//https://docs.agora.io/en/Video/start_call_react_native?platform=React%20Native
//TODO: pass the id from the previous screen
const AgoraVideoCall = (props) => {
let engine = null;
const userId = props.route.params.userId;
const [ initialised, setInitialised ] = useState(false);
const [ joinedChannel, setJoinedChannel ] = useState(false);
const [ engineInitialised, setEngineInitialised ] = useState(false);
const [ userIds, setUserIds ] = useState([ ]);
const requestCameraAndAudioPermission = async () => {
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.log(err);
}
}
const startCall = async () => {
try {
if (engine == null) {
await initialiseEngine()
}
await engine.joinChannel(token, channelName, null, userId)
console.log("StartCall is run")
} catch (err) {
console.log("StartCall throws error")
console.log(engine)
console.log(err)
}
}
const initialiseEngine = async () => {
try {
engine = await RtcEngine.create(agoraAppId);
console.log("Engine initiaised");
setEngineInitialised(true)
} catch (err) {
console.log("Unable to initialise engine");
console.log(err);
setEngineInitialised(false)
}
}
const setUpMeeting = async () => {
await engine.enableVideo();
engine.addListener("UserJoined", (uid, elapsed) => {
console.log(`User has joined, ${uid}`);
if (uid != userId && userIds.filter(id => id == uid).length < 1) {
let tempUserIds = [ ...userIds ]
tempUserIds.push(uid);
setUserIds(tempUserIds);
console.log(`User ids have been updated`);
}
})
engine.addListener("UserOffline", (uid, reason) => {
console.log("User has gone offline");
})
engine.addListener("JoinChannelSuccess", (channel, uid, elapsed) => {
console.log(`Successfully joined the channel, ${channel}, ${uid}`);
setJoinedChannel(true);
})
setInitialised(true)
}
useEffect(() => {
requestCameraAndAudioPermission()
.then(() => {
initialiseEngine()
.then(result => {
setUpMeeting()
})
})
}, [ ])
const renderVideos = () => {
if (! joinedChannel) {
return null
}
return (
<View style={styles.fullView}>
<RtcLocalView.SurfaceView
style={styles.max}
channelId={channelName}
renderMode={VideoRenderMode.Hidden} />
{renderRemoteVideos()}
</View>
)
}
const renderRemoteVideos = () => {
if (userIds.length < 1) {
return null;
}
return (
<ScrollView
style={styles.remoteContainer}
contentContainerStyle={{paddingHorizontal: 2.5}}
horizontal={true}
>
{userIds.map((id, index) => {
return (
<RtcRemoteView.SurfaceView
key={index}
style={styles.remote}
channelId={channelName}
renderMode={VideoRenderMode.Hidden}
uid={id}
zOrderMediaOverlay={true}
/>
)
})}
</ScrollView>
)
}
const renderStartCallButton = () => {
if (joinedChannel) {
return null;
}
return (
<View style={styles.actionButton}>
<Button
title={"Start Call"}
onPress={() => {
startCall()
}}
/>
</View>
)
}
const leaveChannel = async () => {
try {
if (engine ==null) {
await initialiseEngine()
}
await engine.leaveChannel()
setJoinedChannel(false)
} catch (err) {
console.log("Unable to leave the channel")
console.log(engine)
console.log(err)
}
}
const renderLeaveChannelButton = () => {
if (! joinedChannel) {
return null
}
return (
<View style={styles.actionButton}>
<Button
title={"Leave Channel"}
onPress={() => {
leaveChannel()
}}
/>
</View>
)
}
const renderContent = () => {
if (!engineInitialised) {
return <Text>Initializing the Agora engine</Text>
}
if (! initialised) {
return <Text>Initializing the meeting</Text>
}
if (joinedChannel) {
return (
<View style={styles.max}>
<View style={styles.actionButtonsContainer}>
{renderLeaveChannelButton()}
</View>
<View style={styles.max}>
{renderVideos()}
</View>
</View>
)
}
return (
<View>
<View style={styles.actionButtonsContainer}>
{renderStartCallButton()}
</View>
</View>
)
}
return (
<View style={styles.container}>
<ScrollView>
{renderContent()}
</ScrollView>
</View>
)
}
const styles = StyleSheet.create({
container: {
justifyContent: "center",
alignItems: "center",
flex: 1
},
actionButtonsContainer: {
flexDirection: "row"
},
actionButton: {
padding: 10
},
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',
},
})
export default AgoraVideoCall;
当远程视频视图被渲染时,它正在渲染后面的矩形块,如下所示。
我的代码有什么问题,我该如何解决?
【问题讨论】:
-
你能分享你的控制台日志吗?如果正确,我会说仔细检查传递给 remoteView 的远程 UID。
-
嗨,我发现了问题。每次用户加入时,uid 都是新的。但是当用户离开并使用新的 id 和令牌再次加入时,之前的会话会保留在那里,而那些块仍然存在。
标签: android react-native agora.io