Open hatreact opened 10 months ago
@hatreact
I can't see how you pass a remoteStream after getting it in the onRemoteStreamListener
or how you pass a localStream to a screen where you want to display it.
I am not sure about the issue with the redux. On the last screen, you have the warning "Non-serializable values were found in the navigation state". Referring to this warning, I can assume that you are trying to transmit the media stream (local/remote) through the navigation state, could this be true?
const startCall = async (callType = "video") => {
CallService.getStore(store);
if (user.UserSetting.ccuid == null) {
showToast("User does not have a valid connectycube id");
return;
}
const selectedOpponentsIds = [user.UserSetting.ccuid];
const callSession = await CallService.startCall(
selectedOpponentsIds,
callType == "video"
? ConnectyCube.videochat.CallType.VIDEO
: ConnectyCube.videochat.CallType.AUDIO,
{ token, callType, userId: user.id }
);
const pushParams = {
message: `Incoming call from ${user.firstName}`,
ios_voip: 1,
handle: user.firstName,
initiatorId: callSession.initiatorID,
opponentsIds: selectedOpponentsIds.join(","),
uuid: callSession.ID,
callType,
};
PushNotificationsService.sendPushNotification(
selectedOpponentsIds,
pushParams
);
navigation.navigate("VideoScreen", {
initiatorName: user,
});
};
CallService.startCall
ran and streams is passed to action ADD_OR_UPDATE_STREAMS
. You can see in Caller's log, 2nd image right above ADD_OR_UPDATE_STREAMS[0]
. This stream is being accessed in VideoScreen
by using this selector
const streams = useSelector(store => store.ActiveCall.streams);
Even though startCall is running successfully without any error, when user navigates to VideoScreen
right after startCall
.
const callSession = useSelector(store => store.ActiveCall.session);
callSession
is still null. So I passed callSession
in VideoScreen
to confirm if session coming through. That's why it was showing warning for Non-serializable values.
_onCallListener
ran and session is dispatched.
_onRemoteStreamListener
is not triggering at all.
Can you display the localStream (a media stream from a device's camera)? Check this.
_onCallListener
ran and session is dispatched._onRemoteStreamListener
is not triggering at all.
Both users should get a remote stream in onRemoteStreamListener
after the receiver does session. accept(extension)
inside the onCallListener = (session, extension) => {...}
. Also, check this guide.
======================================
Your steps to set a call between users should look like this:
ConnectyCube.videochat.onRemoteStreamListener = function (session, userID, remoteStream) { /*use the remoteStream*/ }
Make sure you have remote streams, then you can dispatch them to Redux to be able to use them from Redux state on any screen. You can test Redux with a local stream first because it is created locally.
No I'm not able to see media stream from device's camera.
With my code
static MEDIA_OPTIONS_AUDIO = { audio: true };
async startCall(usersIds, callType, options = {}) {
const session = ConnectyCube.videochat.createNewSession(
usersIds,
callType,
options
);
store.dispatch(setCallSession(session));
await this.setMediaDevices();
// create local stream
// I write local stream logic like this for readability
const stream = await this.callSession.getUserMedia(
callType == 2
? CallService.MEDIA_OPTIONS_AUDIO
: CallService.MEDIA_OPTIONS
);
console.log("[START-STREAM][0]", stream);
// store streams
const streams = [{ userId: LOCAL_STREAM_USER_ID, stream: stream }];
for (let uId of usersIds) {
streams.push({ userId: parseInt(uId), stream: null });
}
console.log("streams", streams);
store.dispatch(addOrUpdateStreams(streams));
this.callSession.call({ options });
const userName = `${this.currentUser.firstName} ${this.currentUser.lastName}`;
const receivedNames = await getCallRecipientString(usersIds);
// report to CallKit (iOS only)
this.reportStartCall(
this.callSession.ID,
userName,
receivedNames,
"generic",
callType === "video"
);
this.playSound("outgoing");
return session;
}
With connectycube sample code
async startCall(usersIds, callType, options = {}) {
const session = ConnectyCube.videochat.createNewSession(
usersIds,
callType,
options
);
store.dispatch(setCallSession(session));
await this.setMediaDevices();
// create local stream
const mediaOptions = {...CallService.MEDIA_OPTIONS};
if (callType === ConnectyCube.videochat.CallType.AUDIO) {
mediaOptions.video = false;
}
const stream = await this.callSession.getUserMedia(mediaOptions);
console.log("[START-STREAM]", stream);
// store streams
const streams = [{ userId: LOCAL_STREAM_USER_ID, stream: stream }];
for (let uId of usersIds) {
streams.push({ userId: parseInt(uId), stream: null });
}
console.log("streams", streams);
store.dispatch(addOrUpdateStreams(streams));
this.callSession.call({ options });
const userName = `${this.currentUser.firstName} ${this.currentUser.lastName}`;
const receivedNames = await getCallRecipientString(usersIds);
// report to CallKit (iOS only)
this.reportStartCall(
this.callSession.ID,
userName,
receivedNames,
"generic",
callType === "video"
);
this.playSound("outgoing");
return session;
}
And localStream is shown in <VideoGrid streams={streams} />
in VideoScreen.
I tried to follow documentation and compare code with connectycube-reactnative-sdk multiple times. And there is no step I have missed.
_onCallListener
runs and nothing happens afterwards.My guess is it could be due to non-serialized values which could be session or streams being passed in redux. Maybe non-serialized values could be causing this unexpected behaviour. Do you think that it could cause serious problems?
Ensure you use a real device instead of an iOS simulator or Android emulator. Add the prop "video: true" like this. There isn't a video track in your stream. Only the audio track is present.
Sorry, previous logs were from audio call. I have tested on emulators/simulators and real devices.
Tested on following Devices. I got same behaviour. iPhone XS MAX ios 15 OnePluse 6t android 11 Galaxy A52 android 13
I added log in _createAndStoreSession
inside cubeWebRTCClient.js
I added log in _createAndStoreSession inside cubeWebRTCClient.js
You've gotten the log of the new session, it’s obvious that it’s empty.
From previous logs I see that you have a correct localStream and sent it. Check this call on a receiver side and accept the call session. You should get this stream as remote for the receiver (into the onRemoteStreamListener)
In _onCallListener
, value for isIcoming
is passed as true. But still it's not invoking IncomingCallScreen
. When I log isIcoming
value it is false which is very strange behaviour.
async _onCallListener(session, extension) {
this.token = extension.options.token;
this.otherUserId = extension.options.userId;
// if already on a call
if (this.callSession && !this.isDummySession) {
console.log("[CallService][_onCallListener] reject, already_on_call");
this.rejectCall(session, { already_on_call: true });
return;
}
this.playSound("incoming");
console.log("[CallService][_onCallListener]", {
isEarlyAccepted: this.isEarlyAccepted,
isAccepted: this.isAccepted,
});
if (this.isEarlyAccepted && !this.isAccepted) {
setTimeout(() => {
// wait until redux updated the data
this.acceptCall();
});
}
console.log("[_onCallListener][Session]", session);
store.dispatch(setCallSession(session, true));
}
Somewhere you also call the store.dispatch(setCallSession(session))
without the second argument or it is "false". In our RNVideoChat sample the store.dispatch(setCallSession(session, true))
calls in _onCallListener to mark a call as incoming (isIncoming = true). When the store.dispatch(setCallSession(session))
(with isIncoming = false) can be called only from the sender side due to the process of starting a new call (select callee/callees and press the call button).
It means that isIncoming === true
is possible on the receiver side and isIncoming === false
on the side. Check your code to block the unnecessary store.dispatch(setCallSession(...))
.
===========
Are you using our sample as is or did you change something in the code instead of configs?
Yeah I tried to integrate sample code as well but facing the same issue.
I created a repo with produceable behavior. It has the sample sdk code.
https://github.com/hatreact/RAApp.git
@ccvlad could you follow up?
Hey, @hatreact !
I've used your project (RAApp) to find the issue and prepared diff file with fixes - fix_redux_configurations.diff.zip
I think you can apply this file by the command git apply < path/to/fix_redux_configurations.diff
from the root of your project.
You made a lot of mistakes in setting up the redux lib, so I advise you to understand the redux documentation.
I haven't fixed other issues you might encounter later because you should figure it out for yourself.
Versions:
Issue:
Caller's logs:
Receiver's logs:
As you can see in receiver's logs, right above [VIDEO-SCREEN] log at the end of the line, you'll see true value. This is isIncoming value. In receiver's logs, [SET_CALL_SESSION] log run when _onCallListener function run on receiver's side. And in [VIDEO-SCREEN] log the session is null, which shouldn't be.
Why ActiveCall reducer behaving strangely despite actions being dispatched correctly?