voximplant / react-native-voximplant

Voximplant mobile SDK for React Native (iOS/Android)
http://voximplant.com
205 stars 39 forks source link

Receiving call in android app in "killed" state #115

Closed sanjaypojo closed 3 years ago

sanjaypojo commented 4 years ago

Hi @YuliaGrigorieva,

Our incoming calls work successfully in the following conditions:

But it doesn't work in this case:

We use our own push notification (not voximplant push notification) to trigger the call. Since the app is killed, react-native-firebase processes the push notification using a headlessJS task. Everything occurs correctly, we display a custom notification successfully from the headlessJS task.

However, the call disconnects as soon as the app is launched by clicking the answer button. Would you have any inputs on why this happens? It seems like the Voximplant socket disconnects and reconnects when the app is launched. We never receive the incoming call, and the caller disconnects. The same code works successfully for foreground and background states, but not in killed state.

YuliaGrigorieva commented 4 years ago

Hello @sanjaypojo

The SDK (neigher native nor react-native part) does not handle the application state on android and is not reconnecting itself in any case. Connect operation can be done only by calling Client.connect API, disconnect may happen if the Client.disconnect is called from the app side or the connection is lost for some reason.

We cannot reproduce the issue on our side with the Voximplant push. The push originator should not matter in this case, moreover if the same module is used to handle push notification (react-native-firebase).

Can you please describe the order / steps, what happens when your application receives a push notification in killed state? When do you connect and log in to the Voximplant Cloud? As soon as you receive the push notification or when the user clicks "answer" call button?

However, the call disconnects as soon as the app is launched by clicking the answer button

It is not clear for me what is the call you mention since you said that you never receive incoming call event.

May it be that you recreate Client instance on application launch?

Best regards, Yulia Grigorieva

sanjaypojo commented 4 years ago

@YuliaGrigorieva thanks a lot for your info. I investigated this based on your comments and I'm not able to pinpoint the issue. I will try and setup detailed logs and share them with you soon!

maitzeth commented 4 years ago

Hello @YuliaGrigorieva and @sanjaypojo I'm having this same problem but im using VoxImplant Push Notification. When the app is killed ConnectionService display IncomingCall UI, but when I answer the call, nothing happens, the app stay killed and never wake up.

Im making my own code reimplement the code from the Demo:

"@react-native-firebase/messaging": "6.4.0", "react-native-voximplant": "1.18.0", "react-native": "0.61.5",

Any news about this?

sanjaypojo commented 4 years ago

Hi @YuliaGrigorieva I performed a detailed analysis of what happens. Steps to reproduce:

Here are the detailed client side logs:

// Push notification received and app is launched
// Client logs into voximplant
// 14:58:02.840

{type: "Voximplant", message: "VOXSDK: VoxAudioManager: updateAudioDeviceState done", level: "debug"}
{type: "Voximplant", message: "VOXSDK: Client [DISCONNECTED] getClientState: connectWasCalled: false, loginWasCalled: false", level: "info"}
{type: "Voximplant", message: "VOXSDK: Client [DISCONNECTED] connect: connectivity check: false", level: "info"}
{type: "Voximplant", message: "VOXSDK: Authenticator [REQUEST_TO_BALANCER] ", level: "info"}
{type: "Voximplant", message: "VOXSDK: Authenticator [REQUEST_TO_BALANCER] onResponse", level: "info"}
{type: "Voximplant", message: "VOXSDK: Authenticator [REQUEST_TO_BALANCER] onResponse: response code is successful", level: "info"}
{type: "Voximplant", message: "VOXSDK: Authenticator [WEB_SOCKET_CONNECTING] version: android-2.14.1_react-1.13.0", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: created web socket: okhttp3.int…cket@b74f6d5, for: web-gw-fr-02-95.voximplant.com", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: created web socket: okhttp3.int…cket@1b75db, for: web-gw-ca-01-166.voximplant.com", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: created web socket: okhttp3.int…ket@e9b2b51, for: web-gw-us-02-148.voximplant.com", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: created web socket: okhttp3.int…ket@4d194b7, for: web-gw-us-06-141.voximplant.com", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: created web socket: okhttp3.int…ket@b162b8d, for: web-gw-us-03-196.voximplant.com", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onOpen: okhttp3.internal.ws.RealWebSocket@e9b2b51", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onOpen: closing socket okhttp3.internal.ws.RealWebSocket@b74f6d5", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onOpen: closing socket okhttp3.internal.ws.RealWebSocket@1b75db", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onOpen: closing socket okhttp3.internal.ws.RealWebSocket@4d194b7", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onOpen: closing socket okhttp3.internal.ws.RealWebSocket@b162b8d", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onOpen: okhttp3.internal.ws.RealWebSocket@b162b8d", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onOpen: socket is already opened: okhttp3.internal.ws.RealWebSocket@e9b2b51", level: "warning"}
{type: "Voximplant", message: "VOXSDK: Signaling: onFailure: failed socket: okhtt…socket: okhttp3.internal.ws.RealWebSocket@e9b2b51", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onFailure: failed socket: okhtt…socket: okhttp3.internal.ws.RealWebSocket@e9b2b51", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onFailure: failed socket: okhtt…socket: okhttp3.internal.ws.RealWebSocket@e9b2b51", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onFailure: failed socket: okhtt…socket: okhttp3.internal.ws.RealWebSocket@e9b2b51", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onMessage: {"name" : "__createConnection" , "params" : []}", level: "info"}
{type: "Voximplant", message: "VOXSDK: Client [CONNECTED] onConnected", level: "info"}
{type: "Voximplant", message: "VOXSDK: VoxAudioManager: startHeadsetMonitoring", level: "info"}
{type: "Voximplant", message: "VOXSDK: Client [CONNECTED] getClientState: connectWasCalled: false, loginWasCalled: false", level: "info"}
{type: "Voximplant", message: "VOXSDK: Client [CONNECTED] login: user = launchpad-**@*****.voximplant.com", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: SEND: login launchpad-**@*****.voximplant.com", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onMessage: loginSuccessful", level: "info"}
{type: "Voximplant", message: "VOXSDK: MessengerManager: onMessage: client is logged in", level: "info"}
{type: "Voximplant", message: "VOXSDK: Invoke onLoginSuccessful", level: "info"}

// 14:58:05.234 (finish time)

// User presses the answer button
// App is moved to foreground
// 14:58:12.024

{type: "Voximplant", message: "VOXSDK: Client [LOGGED_IN] getClientState: connectWasCalled: false, loginWasCalled: false", level: "info"}
{type: "Voximplant", message: "VOXSDK: Client [LOGGED_IN] getClientState: connectWasCalled: false, loginWasCalled: false", level: "info"}
{type: "Voximplant", message: "VOXSDK: Client [LOGGED_IN] getClientState: connectWasCalled: false, loginWasCalled: false", level: "info"}

// App is awaiting the incoming call, but no call arrives
// 14:58:15.132

type: "Voximplant", message: "VOXSDK: Signaling: SEND: {"name":"__ping","params":[]}", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: SEND: {"name":"__ping","params":[]}", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: SEND: {"name":"__ping","params":[]}", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onMessage: {"name" : "__pong" , "params" : []}", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onMessage: {"name" : "__pong" , "params" : []}", level: "info"}
{type: "Voximplant", message: "VOXSDK: Signaling: onMessage: {"name" : "__pong" , "params" : []}", level: "info"}

// The call times out on the caller side and no call has been received
// 14:58:22.009

Here are the voximplant server side logs:

2020-06-24 22:26:32 Loading scenario rune_p2p_*********
2020-06-24 22:26:32 Sent event to JS onPhoneEvent with params [{accessSecureURL = https://www-us-03-163.voximplant.com:12093/request/32B3986F43F666B8.1593037592.4363942_173.0.146.163/F9D6B6539B344247 ;  accessURL = http://173.0.146.163:12092/request/32B3986F43F666B8.1593037592.4363942_173.0.146.163/F9D6B6539B344247 ;  accountId = 2490596 ;  applicationId = 4225157 ;  config = {acceptReInviteByDefault = true ;  } ;  initiatorCountry = US ;  logURL = https://storage-gw-us-01.voximplant.com/voxdata-us-logs/2020/06/24/NGQ1MDM3ZDJkMjJkN2RiOTg3OTEyNDE4NGRhNTg1NzQvaHR0cDovL3d3dy11cy0wMy0xNjMudm94aW1wbGFudC5jb20vbG9ncy8yMDIwLzA2LzI0LzIyMjYzMl8zMkIzOTg2RjQzRjY2NkI4LjE1OTMwMzc1OTIuNDM2Mzk0Ml8xNzMuMC4xNDYuMTYzLmxvZw--?sessionid=209143319 ;  name = Application.Started ;  sessionId = 209143319 ;  userId = 284466 ;  } ;  ]
2020-06-24 22:26:32 Sent event to JS onPhoneEvent with params [{callerid = *********-25 ;  destination = *********-21 ;  displayName = *********-25 ;  fromURI = sip:*********-25@*********.runeai.voximplant.com ;  headers = {VI-Authenticated-Caller = *********-25 ;  VI-Browser = voxmobile ;  VI-Client-Device = WebRTC ;  VI-Client-IP = 73.70.49.143 ;  VI-Client-Type = user ;  VI-ClientVersion = ios-2.23.0_react-1.13.0 ;  X-RUNE-CID = 2578 ;  } ;  id = 29E5729E7260B8F0.1593037592.4363941 ;  name = Application.CallAlerting ;  requestIP = 142.0.192.196:34007 ;  scheme = {"" : {"audio" : [{"codecs" : [114,9,100,0,8,101] , "direction" : "sendrecv" , "flows" : [{"cname" : "ge+WG3KKPtlSXOKR" , "uniq" : 0}] , "msid" : "- c9c873e6-e4d2-408b-b93a-6d817142545f" , "uniq" : 0}] , "place" : 0 , "type" : "call" , "video" : [{"ast" : true , "codecs" : [104,105,115,116,108,109,125] , "direction" : "recvonly" , "flows" : [{"uniq" : 0}] , "options" : {"115" : "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f"} , "trcc" : true , "uniq" : 0}] , "vox-params" : ["platform ios","clver ios-2.23.0_react-1.13.0"]}} ;  toURI = sip:*********-21@*********.runeai.voximplant.com ;  } ;  ]
2020-06-24 22:26:32 Executing JS command: EnableMediaStatistics with params [{id = 29E5729E7260B8F0.1593037592.4363941 ;  } ;  ]
2020-06-24 22:26:32 Enable media statistics for 29E5729E7260B8F0.1593037592.4363941 : https://storage-gw-us-01.voximplant.com/voxdata-us-logs/2020/06/24/MzE3YTQ3ODVkMzAxMDA3MjQ5NjEzOTgwYWRiZDFhYTAvaHR0cDovL3d3dy11cy0wMy0xNjMudm94aW1wbGFudC5jb20vbG9ncy8yMDIwLzA2LzI0LzMyQjM5ODZGNDNGNjY2QjguMTU5MzAzNzU5Mi40MzYzOTQyXzE3My4wLjE0Ni4xNjNfMjlFNTcyOUU3MjYwQjhGMC4xNTkzMDM3NTkyLjQzNjM5NDEuY3N2?sessionid=209143319
2020-06-24 22:26:32 Executing JS command: CallUserDirect with params [{id = Oov3bsWLTGyQW5FRtF4Fjs8lUzGMXkjFoGhQ1FR_EkM ;  } ;  {callerid = *********-25 ;  displayName = *********-25 ;  headers = {VI-Authenticated-Caller = *********-25 ;  VI-Browser = voxmobile ;  VI-Client-Device = WebRTC ;  VI-Client-IP = 73.70.49.143 ;  VI-Client-Type = user ;  VI-ClientVersion = ios-2.23.0_react-1.13.0 ;  X-RUNE-CID = 2578 ;  } ;  incomingCall = 29E5729E7260B8F0.1593037592.4363941 ;  proxyid = fPWMsQFdSNS2zvanaiKpqPGNGy2-RU8ejUy1uAIXz8M ;  sendWakeup = true ;  username = *********-21 ;  } ;  ]
2020-06-24 22:26:32 send push wakeup message:{"addr" : "173.0.146.163:5090" , "callid" : "fPWMsQFdSNS2zvanaiKpqPGNGy2-RU8ejUy1uAIXz8M" , "display_name" : "*********-25" , "sessionid" : "32B3986F43F666B8.1593037592.4363942_173.0.146.163" , "sipuri" : "sip:*********-25@*********.runeai.voximplant.com" , "userid" : "*********-21@*********.runeai.voximplant.com" , "video" : true}
2020-06-24 22:26:32 Sent event to JS onPhoneEvent with params [{id = fPWMsQFdSNS2zvanaiKpqPGNGy2-RU8ejUy1uAIXz8M ;  name = Call.PushSent ;  } ;  ]
2020-06-24 22:26:32 Executing JS command: EnableMediaStatistics with params [{id = Oov3bsWLTGyQW5FRtF4Fjs8lUzGMXkjFoGhQ1FR_EkM ;  } ;  ]
2020-06-24 22:26:32 Enable media statistics for Oov3bsWLTGyQW5FRtF4Fjs8lUzGMXkjFoGhQ1FR_EkM : https://storage-gw-us-01.voximplant.com/voxdata-us-logs/2020/06/24/Y2Y4ZTkxYTgwYmExMjJjNjAyZWRkMmU4ODMyYWNkMzgvaHR0cDovL3d3dy11cy0wMy0xNjMudm94aW1wbGFudC5jb20vbG9ncy8yMDIwLzA2LzI0LzMyQjM5ODZGNDNGNjY2QjguMTU5MzAzNzU5Mi40MzYzOTQyXzE3My4wLjE0Ni4xNjNfT292M2JzV0xUR3lRVzVGUnRGNEZqczhsVXpHTVhrakZvR2hRMUZSX0VrTS5jc3Y-?sessionid=209143319
2020-06-24 22:26:32 Executing JS command: SendMediaBetween with params [{id1 = 29E5729E7260B8F0.1593037592.4363941 ;  id2 = fPWMsQFdSNS2zvanaiKpqPGNGy2-RU8ejUy1uAIXz8M ;  } ;  ]
2020-06-24 22:26:33 Sent event to JS onPhoneEvent with params [{code = 480 ;  headers = {} ;  id = Oov3bsWLTGyQW5FRtF4Fjs8lUzGMXkjFoGhQ1FR_EkM ;  name = Call.Failed ;  reason = User offline ;  } ;  ]
2020-06-24 22:26:34 push wakeup result: *********-21@*********.runeai.voximplant.com > {web={result=no tokens found}, android={cMdBnEx-ang:APA91bG_6rYgdVaKXcTXIEmkpD8WJAchSMuq_ETcMCKGwFO1XgH3EuaSxjaXkVrW9nyzz-eYnUy7bNSM9ccpzLUvtZbPr57kWlpwDFLZO_bVtiuorA9XE-8ynUEBpscz6_pWCIOuiyoz={result=success}, c95sXz11JWQ:APA91bHoc9MT9b1s6o81tA0td4y7xj4q5sjMbSp1bk6aJkEs9zYpIqhW_Vxnij1LNDs6zRFlHQSy7zZ5cW6kgPoE8pEiXWEk_aO1Pffk8W1Osm6hsWm5l_SrZVf7ERDwlkp_6F6gaMWh={result=success}}, ios={error=Push certificate not found}}
2020-06-24 22:26:53 Sent event from JS onPhoneEvent with params [{code = 480 ;  headers = {} ;  id = fPWMsQFdSNS2zvanaiKpqPGNGy2-RU8ejUy1uAIXz8M ;  name = Call.Failed ;  reason = Destination number is unavailable ;  } ;  ]
2020-06-24 22:26:53 INFO: Session is stopping...
2020-06-24 22:26:53 Terminating (onClose)
2020-06-24 22:26:53 Executing JS command: close with params [{CpuMillis = 76 ;  } ;  ]
2020-06-24 22:26:53 Normal termination
2020-06-24 22:26:53 Session terminated
YuliaGrigorieva commented 4 years ago

Hello @sanjaypojo ,

In this case Voximplant expects that Client.handlePushNotification is called on the app side and provide the push notification data from Voximplant push. It is expected because your scenario seems to enable Voximplant push notifications by require(Modules.PushService) line.

If you use your own push notifications, you need to change the call establishment process. First, you need to disable Voximplant push notifications in the VoxEngine scenario. Then, I can suggest the following steps:

  1. Handle AppEvents.Stated event to get the accessURL
  2. Handle a new call in the VoxEngine scenario via AppEvents.CallAlerting event
  3. Make a HTTP request to notify your push notifications platform to send a push notification to the callee, insert accessURL from step 1 to the push notification
  4. Wait for callee to receive a push notification. Once the callee receives it, it is required to make HTTP request using accessURL from the callee client to notify the VoxEngine scenario that the callee is logged in and ready to receive the incoming call. You need to handle this HTTP request via AppEvents.HttpRequest in your VoxEngine scenario.
  5. Create a call for the callee by using VoxEngine.callUserDirect/VoxEngine.callUser (or any other VoxEngine API)
  6. Use VoxEngine.easyProcess API to send media between these calls (or other methods you have in the scenario to connect the calls)

Best regards, Yulia Grigorieva

sanjaypojo commented 4 years ago

Thanks @YuliaGrigorieva, I did not realize that the voximplant push needed to be processed for voximplant to recognize that the user has come online. I have an alternative approach, do you think this would work:

YuliaGrigorieva commented 4 years ago

Hello @sanjaypojo ,

It will work if you have the ability to get the information from both clients that they are logged in. And it seems that your approach does not require push notifications. :)

There can also be the cases when you have 2 clients logged in, but the connection is lost on one of them, while another is making a call. Also please consider that if you have an ios app, the connection is automatically closed when the application goes to the background.

Best regards, Yulia Grigorieva

sanjaypojo commented 4 years ago

That makes sense, thanks for the clarifications @YuliaGrigorieva :)

sanjaypojo commented 4 years ago

Also please consider that if you have an ios app, the connection is automatically closed when the application goes to the background.

@YuliaGrigorieva had a follow up question on this part. If CallKit has been started and a call has been registered before the app goes to background on iOS, is it safe to assume the connection won't close in that case? (even if the p2p call has not yet been actually connected)

YuliaGrigorieva commented 4 years ago

Hello @sanjaypojo ,

Generally, you can't assume that the connection won't close in any configuration, because it can be closed any time by OS.

As for SDK side, SDK on iOS won't close the connection in the background if there is an existing Call that is not failed or disconnected (it can be not connected or even answered). However, SDK does not check (not sure it can or should) if the CallKit is started and if any calls registered to it.

Best regards, Yulia Grigorieva