I got the AWS Chime SDK Demo for React Native working and two people can join a video call on mobile. The local device has its video camera shown in a small tile at the bottom of the screen while the remote device takes up the whole screen and the local tile sits on top of it. However, I have noticed that on Android when you start local video and then start local video from the other device the video from the remote device covers the Android local tile. The local tile can be brought back by the Android device stopping and starting their video again but it shouldn't disappear in the first place.
Here are my listeners for the video tile state change events:
const [localDevice, setLocalDevice] = useState({
videoEnabled: false,
videoTileId: null
})
const [remoteDevice, setRemoteDevice] = useState({
videoEnabled: false,
videoTileId: null
})
// ---------- ON ATTENDEE START VIDEO ----------
useEffect(()=>{
onAddVideoTileSubscription.current = getSDKEventEmitter().addListener(
MobileSDKEvent.OnAddVideoTile,
tileState => {
if(tileState.isLocal){
setLocalDevice({
videoEnabled: true,
videoTileId: tileState.tileId
})
}else if(!tileState.isLocal){
setRemoteDevice({
videoEnabled: true,
videoTileId: tileState.tileId
})
}
},
);
return () => {
if (onAddVideoTileSubscription.current) {
onAddVideoTileSubscription.current.remove();
}
};
},[])
// ---------- ON ATTENDEE END VIDEO ----------
useEffect(()=>{
onRemoveVideoTileSubscription.current = getSDKEventEmitter().addListener(
MobileSDKEvent.OnRemoveVideoTile,
tileState => {
if(tileState.isLocal){
setLocalDevice({
videoEnabled: false,
videoTileId: tileState.tileId
})
}else if(!tileState.isLocal){
setRemoteDevice({
videoEnabled: false,
videoTileId: tileState.tileId
})
}
},
);
return () => {
if (onRemoveVideoTileSubscription.current) {
onRemoveVideoTileSubscription.current.remove();
}
};
},[])
And here is my render logic:
return (
<View style={styles.callContainer}>
{remoteDevice.videoEnabled ? (
<View style={styles.remoteDeviceVideoContainer}>
<RNVideoRenderView
style={styles.remoteDeviceVideo}
key={remoteDevice.videoTileId}
tileId={remoteDevice.videoTileId}
/>
</View>
): (
null
)}
{localDevice.videoEnabled ? (
<View style={styles.localDeviceVideoContainer}>
<RNVideoRenderView
style={styles.localDeviceVideo}
key={localDevice.videoTileId}
tileId={localDevice.videoTileId}
/>
</View>
): (
null
)}
<FlatList
style={styles.attendeeList}
data={state.attendees}
renderItem={({item}) => (
<AttendeeItem
attendeeName={
attendeeNameMap[item] ? attendeeNameMap[item] : item
}
muted={state.mutedAttendee.includes(item)}
/>
)}
ItemSeparatorComponent={() => <View style={styles.separator} />}
keyExtractor={item => item}
/>
<View style={styles.buttonContainer}>
<MuteButton
muted={currentMuted}
onPress={() => NativeFunction.setMute(!currentMuted)}
/>
<CameraButton
disabled={localDevice.videoEnabled}
onPress={() =>
NativeFunction.setCameraOn(!localDevice.videoEnabled)
}
/>
<View style={styles.hangOffButtonContainer}>
<HangOffButton onPress={() => NativeFunction.stopMeeting()} />
</View>
</View>
</View>
);
And here are my Styles:
callContainer:{
backgroundColor: '#1D1D1D',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
justifyContent: 'flex-start'
},
localDeviceVideoContainer:{
position: 'absolute',
bottom: 100,
right: 15,
height: 175,
width: 132,
zIndex: 1,
elevation: 1,
},
localDeviceVideo:{
height: '100%',
width: '100%'
},
remoteDeviceVideoContainer:{
height: '100%',
width: '100%',
backgroundColor:'pink',
},
remoteDeviceVideo:{
width: '100%',
height: '100%',
},
I have tried swapping the position of the remote render and the local render with no change. I have tried using elevation and zIndex with no change. I know for certain the tile is appearing behind the fullscreen video because I set the opacity of the fullscreen video to 0 and saw the component behind it. I know it works perfectly fine across iOS devices and the small tiles stay in the foreground. I have tried so many things to get this to work but have no clue what is happening. Has anyone dealt with this AWS Chime SDK issue before?
Thought I would answer my own question for anyone else who may be having issues with Chime SDK RNVideoViews not behaving as expected when they are overlapping.
Discovered that even though I set the remote tiles opacity to 0 and saw the other tile, it was actually not behind but on top of the remote tile. It appeared to have disappeared but actually was as if there was a hole being punched through the local tile which was showing the video feed of the remote device camera. Turns out that SurfaceView which is the underlying view that was being used by AWS DefaultVideoRenderView doesn't play nicely with other SurfaceViews unless you set "setZOrderOnTop(true)"
on the SurfaceView you want to always be on top. support-for-multiple-active-overlapping-surface-views-in-android
After setting that as well as zindex to 1, the views behaved as expected. Small local device tile is displaying over the fullscreen remote device video tile on Android and iOS.