Getting issue on accepting video call from VOIP notification when app is in terminated state/ Force Quit.
When i accept the call from VOIP notification, the video call is getting failed for the first time,
when i call again its getting accepted.
Hi @Android_MR_Firebase , thanks for the report.
I’m guessing that there might be an error with authenticating the user when the first push notification is received. Can you make sure that the user is authenticated before call.accept()
is called? It would also help if you could provide the code snippet where you handle the received push notification.
Thanks
Hi @mininny
i followed this link
i am calling the call.accept() here :
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
guard let call = SendBirdCall.getCall(forUUID: action.callUUID),
SendBirdCall.currentUser != nil else {
action.fail()
return
}
let callOptions = CallOptions(isAudioEnabled: true, isVideoEnabled: call.isVideoCall, useFrontCamera: true)
let acceptParams = AcceptParams(callOptions: callOptions)
call.accept(with: acceptParams)
UIApplication.shared.showCallController(with: call)
action.fulfill()
}
Here is the code for handling received VOIP push notification:
import UIKit
import CallKit
import PushKit
import SendBirdCalls
extension AppDelegate: PKPushRegistryDelegate {
func voipRegistration() {
self.voipRegistry = PKPushRegistry(queue: DispatchQueue.main)
self.voipRegistry?.delegate = self
self.voipRegistry?.desiredPushTypes = [.voIP]
}
func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
tokenVoip = pushCredentials.token
UserDefaults.standard.voipPushToken = pushCredentials.token
}
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
SendBirdCall.pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type, completionHandler: nil)
}
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
SendBirdCall.pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type) { uuid in
guard uuid != nil else {
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .generic, value: "invalid")
let randomUUID = UUID()
CXCallManager.shared.reportIncomingCall(with: randomUUID, update: update) { _ in
CXCallManager.shared.endCall(for: randomUUID, endedAt: Date(), reason: .acceptFailed)
}
completion()
return
}
completion()
}
}
}
Here is the didStartRinging function :
func didStartRinging(_ call: DirectCall) {
call.delegate = self
guard let uuid = call.callUUID else { return }
guard CXCallManager.shared.shouldProcessCall(for: uuid) else { return }
print(call.caller)
let name = call.caller?.nickname ?? "Unknown"
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .generic, value: name)
update.hasVideo = call.isVideoCall
update.localizedCallerName = name
if SendBirdCall.currentUser == nil {
CXCallManager.shared.reportIncomingCall(with: uuid, update: update) { _ in
// CXCallManager.shared.endCall(for: uuid, endedAt: Date(), reason: .acceptFailed)
}
// call.end()
}
else if SendBirdCall.getOngoingCallCount() > 1 {
CXCallManager.shared.reportIncomingCall(with: uuid, update: update) { _ in
CXCallManager.shared.endCall(for: uuid, endedAt: Date(), reason: .declined)
}
call.end()
}
else {
CXCallManager.shared.reportIncomingCall(with: uuid, update: update)
}
}
Hi @mininny Sharing another video of issue, when app is forced quit or terminated, and device is locked.
Hi @mininny
Any update on this will be appreciated.
The project is held up and we cant go live with this issue coming up.
Hi @Android_MR_Firebase, sorry for the delayed response. It seems like you are not authenticating the user before calling DirectCall.accept()
. Can you please refer to the following code? quickstart-calls-directcall-ios/CXCallManager.swift at 650d93bd6e5cdf73c63ea7e3c2412c2734d4635d · sendbird/quickstart-calls-directcall-ios · GitHub
What you should do is call SendBirdCall.authenticate
in provider(_ provider: CXProvider, perform action: CXAnswerCallAction)
before calling call.accept(with: AcceptParams)
Please let me know if this resolves your issue after trying this.
Hi @mininny
i tried the above, but still its not working,
the authenticateIfneeded is not available in the version of SendBird i am using (installed via Cocoapods),
now, i am authenticating the user as shared in code snippet, Please let me know if i am doing it right, or i have to use the SendBirdCall.currentUser!.userId at the place of userId in AuthenticateParams as
let authenticateParams = AuthenticateParams(userId: SendBirdCall.currentUser!.userId)
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
guard let call = SendBirdCall.getCall(forUUID: action.callUUID),
SendBirdCall.currentUser != nil else {
action.fail()
return
}
let userId = self.appDelegate.dictInfo["idToAuth"]
let authenticateParams = AuthenticateParams(userId: userId)
SendBirdCall.authenticate(with: authenticateParams) { (user, error) in
guard let user = user, error == nil else { return }
print("Successfully Authenticated: \(user.userId)")
}
let callOptions = CallOptions(isAudioEnabled: true, isVideoEnabled: call.isVideoCall, useFrontCamera: true)
let acceptParams = AcceptParams(callOptions: callOptions)
call.accept(with: acceptParams)
UIApplication.shared.showCallController(with: call)
action.fulfill()
}