如何在后台/已终止状态下为QuickBlox实现CallKit?需额外配置吗?
Great question—you’re absolutely right that additional VOIP-specific configuration is required to get CallKit working for QuickBlox when your app is in the background or terminated. Unlike regular push notifications, VOIP pushes are designed to wake up your app even when it’s not running, which is essential for triggering the CallKit incoming call UI. Here’s a detailed breakdown of the steps you need to implement:
1. Enable VOIP Push Capabilities in Apple Developer Portal
- Navigate to your app’s identifier in the Apple Developer Portal, select the Voice over IP capability, and save changes.
- Generate a dedicated VOIP push certificate (separate from your regular APNS certificate). Download and install it in your keychain, then export it as a
.p12file to upload to QuickBlox’s dashboard under your app’s push settings.
2. Configure Xcode Project Settings
- Open your project in Xcode, go to the Signing & Capabilities tab for your target.
- Add the Voice over IP capability (this will automatically enable related background modes).
- Ensure the Background Modes capability is enabled, with both Voice over IP and Remote notifications checked.
3. Register for VOIP Push Tokens
Instead of using regular APNS tokens, you need to register for VOIP push tokens using PKPushRegistry:
import PushKit class VOIPPushManager: NSObject, PKPushRegistryDelegate { static let shared = VOIPPushManager() private override init() {} func registerForVOIPPush() { let registry = PKPushRegistry(queue: DispatchQueue.main) registry.delegate = self registry.desiredPushTypes = [.voIP] } func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { let token = credentials.token.map { String(format: "%02x", $0) }.joined() // Send VOIP token to QuickBlox server let pushToken = QBMPushToken() pushToken.token = token pushToken.environment = .production // Switch to .development for debug builds pushToken.type = .voIP QBMessages.tokens.create(pushToken) { result in switch result { case .success(_): print("VOIP token registered successfully with QuickBlox") case .failure(let error): print("Failed to register VOIP token: \(error.localizedDescription)") } } } func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { // Handle token invalidation (e.g., unregister from QuickBlox) } }
Call VOIPPushManager.shared.registerForVOIPPush() in your app’s didFinishLaunchingWithOptions method—this runs even if the app is launched from a terminated state.
4. Handle Incoming VOIP Pushes & Trigger CallKit
When a VOIP push is received, your app will wake up (even if terminated) to process it. Implement the delegate method to extract call details and report the incoming call to CallKit:
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { guard type == .voIP else { return } // Extract call data from QuickBlox's push payload let callData = payload.dictionaryPayload let callerID = callData["caller_id"] as? String ?? "" let callerName = callData["caller_name"] as? String ?? "Unknown" let callUUID = UUID(uuidString: callData["call_uuid"] as? String ?? "") ?? UUID() let isVideoCall = callData["is_video_call"] as? Bool ?? false // Create CallKit update let update = CXCallUpdate() update.remoteHandle = CXHandle(type: .generic, value: callerName) update.hasVideo = isVideoCall update.localizedCallerName = callerName // Report incoming call to CallKit let callController = CXCallController() callController.request(CXStartCallAction(call: callUUID, handle: update.remoteHandle!)) { error in if let error = error { print("Failed to report incoming call: \(error.localizedDescription)") } else { print("Incoming call reported successfully") } completion() } }
Refer to QuickBlox’s docs for the exact payload keys used for call metadata.
5. Verify QuickBlox Call Initiation Setup
When starting a call, ensure you specify the VOIP push type in your call settings:
let callSettings = QBCCallSettings() callSettings.pushType = .voIP // Ensures a VOIP push is sent to the receiver // Add other settings (video enabled, session duration, etc.) QBRequest.createSession(with: callSettings) { result in // Handle session creation and initiate the call }
Common Pitfalls to Avoid
- Using regular push tokens: VOIP pushes require a unique token—sending a regular APNS token won’t trigger background wakeup.
- Missing background modes: Forgetting to enable "Voice over IP" and "Remote notifications" will block VOIP pushes when the app is inactive.
- Incorrect push handling: The
didReceiveIncomingPushWithmethod is critical for terminated state wakeups—make sure it’s implemented correctly.
Test your setup using Xcode’s Simulate VOIP Push feature (under Debug > Simulate VOIP Push) or a third-party tool to send test VOIP pushes, and verify the CallKit UI appears even when the app is terminated.
内容的提问来源于stack exchange,提问作者dharmik webmigrates

