sidslog
sidslog

Reputation: 654

No sound after connecting to WebRTC when app is launched in background using PushKit and CallKit on the lock screen

Everything works fine if we launch the app in the foreground. But there is an issue when the app is previously killed and is restarted by receiving a PushKit notification on the lock screen.

When the app receives a PushKit notification we display the CallKit UI. This works correctly. The user is able to answer the call and establish a connection via WebRTC. But there is no audio at all.

The strange thing is that if the user opens the app from CallKit screen by tapping on the application icon, the audio starts and works as expected. So it looks like the problem is with the audio session configuration. Maybe for some reason, iOS doesn't allow our audio session to be activated.

We're using Google's WebRTC library:

pod 'GoogleWebRTC',             '1.1.26115'

We tried different approaches:

  1. Enabling/disabling audio background mode.

  2. Configuring audio session before and after the didActivate callback is received from CallKit delegate.

  3. Configuring audio session manually and using RTCAudioSession.sharedInstance from WebRTC library.

  4. Enabling and disabling RTCAudioSession.useManualAudio.

This is the scenario where we encounter the issue:

  1. Kill the app. Lock the phone.

  2. Call this user from another phone.

  3. PushKit launches the app, the app presents CallKit screen, the user answers the call.

  4. The connection establishes correctly. The call is active but there is no sound on both ends.

  5. Tap on the app icon (most bottom right) on the CallKit screen and unlock the phone. The audio starts.

Any help is appreciated.

Upvotes: 4

Views: 4021

Answers (2)

sbca68
sbca68

Reputation: 25

I have a similar problem with linphone-sdk and CallKit. And the problem in my case was a missing audio key in Info.plist. You need to have these keys, if you want you app works with AVAudioSession in background mode.

<key>UIBackgroundModes</key>
<array>
        <string>voip</string>
        <string>audio</string>
</array> 

Upvotes: 0

Miki
Miki

Reputation: 921

There is a specific issue with the audio I/O and CallKit. When you are about to receive an incoming call, you must configure audio session for VoIP calls then, but do not activate it, just set category, mode and buffer.

Example for configuring Audio Session for CallKit incoming call:

func configureAudioSession() {
    let sharedSession = AVAudioSession.sharedInstance()
    do {
        try sharedSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
        try sharedSession.setMode(AVAudioSessionModeVoiceChat)
        try sharedSession.setPreferredIOBufferDuration(TimeInterval(0.005))
        try sharedSession.setPreferredSampleRate(44100.0)
    } catch {
        debugPrint("Failed to configure `AVAudioSession`")
    }
}

Then, when you answer the incoming Call, CallKit will activate the audio session for you, and you will receive a callback from CXProvider:

func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
    // Start call audio I/O here
}

In that delegate callback, you should start your call audio, not before. If WebRTC call audio I/O was started before, the CallKit will terminate it and there will be no sound.

Upvotes: 3

Related Questions