Search code examples
ioscallkitpushkit

How to handle Voip Push when received incoming call already from websocket?


The question is getting from here and seem no one give a proper answer yet.

==================================

Hi Devs,

I'm developing a Social networking app which includes audio call feature. I integrated with SocketIO + WebRTC for this audio call. I'm receiving audio call by two ways. Socket call when socket is connected & active VoIP call by default irrespective of socket is connected or not.

FYI, Why i had two ways of receiving call as mentioned above,

  • Enabled VoIP by default, because sometimes socket call is unresponsive and never show call at that time.
  • Enabled socket when app is in foreground, to ensure that call is received in case of MissingDeviceToken/BadDeviceToken errors occurred for VoIP push.

Considering iOS 13 guidelines for VoIP usage, I followed below steps for integration.

  1. When app is killed or socket not connected, will get VoIP call and responding with provider.reportNewIncomingCall(). So here no issue for VoIP usage.

  2. When socket is connected, will get both socket call & VoIP call. But socket call will get instantly before getting VoIP call. So here's what i did:

    1. Responded socket call with provider.reportNewIncomingCall().
    2. After a little delay will get VoIP push for the same call which is already invoked by socket. Here, I should respond this VoIP push with CallKit. But i have already invoked the call. So, I used below code to handle.

provider.reportCall(with: call.uuid, updated: update) with same uuid & update used for socket call initiation. Hope, this VoIP call also responded with CallKit and there's no issue in VoIP blocking/app termination.

Question 1 : Is this a proper way of handling above issue ?

===========================================================================================================

As per my app requirement, there's should be one active call at a time from my app.

Consider, I'm in active call and one more incoming call is received via VoIP. So here, I don't want to show the additional call. So I'm ignoring the VoIP push for the additional call. But it leads to this crash "Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push callback."

Question 2 : How to handle above mentioned scenario ?

===========================================================================================================

What I try

For question 2, I try answer from this one.

Though it does not work in some case for example when user happen to answer a call fast enough, the second incoming call from push will result in Call Stacking screen.

This approach also create additional call in recent call list and a bar incoming call saying call ended during incoming screen for the first incoming event which is bad user experience.

I also found this one to look promising but it is very had known this will be fine.

Does anyone have any solution to this? Thanks


Solution

  • As an Apple engineer confirmed me in a technical support request, my answer in theory is correct. However, in practice, it’s basically impossible to do that without either reporting calls unnecessarily or crashing for failing to report calls, due to the asynchronous nature of PushKit and CallKit. So, it is highly discouraged.

    Therefore, for question 2, if for you this answer is not acceptable, the only solution I can see is to let the server handle it for you. So, the server should have a list of ongoing calls and avoid sending VoIP pushes to users that are already involved in a call.

    For question 1, the solution you've implemented is not really reliable: You cannot do any assumptions on the order of events in an asynchronous environment. It's possible to receive the VoIP push before the socket call and in this case you fail to report a new incoming call, because you just report a call update. Or, another more subtle example: you receive the push and the socket call roughly at the same time, you report the new incoming call as a consequence of the socket call, but (remember that CallKit is asynchronous) while the system is processing the new call request, you process your VoIP push without reporting a new incoming call.

    I believe that the simpler way to handle this situation is to have one and only one way to handle new incoming calls, which is through VoIP pushes. In this way, your app should work in any circumstance and you don't have to implement two different code paths for calls received when the app is terminated or when is already running.