Display the system-calling UI for your app’s VoIP services and coordinate your calling services with other apps and the system using CallKit.

Posts under CallKit tag

124 Posts

Post

Replies

Boosts

Views

Activity

Call log
I read online that there is no way to extract the call log from an iPhone. I want to develop an app to help people remember to call their mom, and if they did, the "nagging" would disappear automatically. I'm looking for any workaround to know when a user called someone, without having them log it manually.
1
0
445
Dec ’25
CallKit VoIP → App launch → Auto WebRTC/MobileRTC connection: Does Apple allow this flow?
Our app receives a CallKit VoIP call. When the user taps “Answer”, the app launches and automatically connects to a real-time audio session using WebRTC or MobileRTC. We would like to confirm whether the following flow (“CallKit Answer → app opens → automatic WebRTC or MobileRTC audio session connection”) complies with Apple’s VoIP Push / CallKit policy. In addition, our service also provides real-time video-class functionality using the Zoom Meeting SDK (MobileRTC). When an incoming CallKit VoIP call is answered, the app launches and the user is automatically taken to the Zoom-based video lesson flow: the app opens → the user is landed on the Zoom Meeting pre-meeting room → MobileRTC initializes immediately. In the pre-meeting room, audio and video streams can already be active and MobileRTC establishes a connection, but the actual meeting screen is not joined until the user explicitly taps “Join”. We would like to confirm whether this flow for video lessons (“CallKit Answer → app opens → pre-meeting room (audio/video active) → user taps ‘Join’ → enter actual meeting”) is also compliant with Apple’s VoIP Push and CallKit policy.
1
0
126
Dec ’25
Are notification pushes not being received when in Picture-in-Picture mode?
Hello, I recently had an unusual experience, and I’m wondering if this is related to Apple’s policies, so I wanted to ask. While a call is in Picture-in-Picture (PIP) mode, notification pushes from the same app do not appear. The API is being triggered, but the notification banner does not show on the device. Once PIP is closed, the notifications start appearing normally again. Is this behavior enforced by Apple’s policies? What’s interesting is that banners from other apps do appear — only the banners from the app currently in PIP are not shown.
1
0
222
Dec ’25
CallKit issue
In iOS 26.1, after my app answers a VoIP call on the lock screen, tapping the bottom-left "More" button doesn't bring up the app icon to jump to the app. The same scenario works normally on iOS 26. How can I resolve this issue?
1
1
132
Dec ’25
VoIP Push Notifications Not Delivered in Background/Killed State (Using AppDelegate)
Hello, colleagues. I am reaching out to the community with an issue that is likely quite common. Unfortunately, I have not been able to resolve it independently and would like to confirm if my approach is correct. Core Problem: VoIP push notifications are not delivered to the application when it is in the background or terminated. After reviewing existing discussions on the forum, I concluded that the cause might be related to CallKit not having enough time to register. However, in my case, I am using AppDelegate, and in theory, CallKit registration should occur quickly enough. Nevertheless, the issue persists. Additional Question: I would also like to clarify the possibility of customizing the CallKit interface. Specifically, I am interested in adding custom buttons (for example, to open a door). Please advise if such functionality is supported by CallKit itself, or if a different approach is required for its implementation. Thank you in advance for your time and attention to my questions. For a more detailed analysis, I have attached a fragment of my code below. I hope this will help clarify the situation. Main File @main struct smartappApp: App { @UIApplicationDelegateAdaptor private var delegate: AppDelegate @StateObject private var navigationManager = NavigationManager() init() { print("Xct") if !isRunningTests() { DILocator.instance .registerModules([ ConfigModule(), SipModule(), AuthModule(), NetworkModule(), CoreDataModule(), RepositoryModule(), DataUseCaseModule(), SipUseCaseModule() ]) } } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { print("Axtest") completionHandler(.newData) } var body: some Scene { App Delegate File class AppDelegate: UIResponder, UIApplicationDelegate { private let voipRegistry = PKPushRegistry(queue: .main) private var provider: CXProvider? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { setupPushKit() setupCallKit() return true } public func regist(){ setupPushKit() setupCallKit() } private func setupPushKit() { voipRegistry.delegate = self voipRegistry.desiredPushTypes = [.voIP] DispatchQueue.main.async { self.voipRegistry.pushToken(for: .voIP) } } // MARK: - CallKit Setup private func setupCallKit() { let configuration = CXProviderConfiguration(localizedName: "MyApp") configuration.maximumCallGroups = 1 configuration.maximumCallsPerCallGroup = 1 configuration.supportsVideo = true configuration.iconTemplateImageData = UIImage(named: "callIcon")?.pngData() provider = CXProvider(configuration: configuration) provider?.setDelegate(self, queue: .main) } // MARK: - Background Launch Handling func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { print("Axtest") completionHandler(.newData) } } extension AppDelegate: PKPushRegistryDelegate { func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { APNsImpl().registerToken(token: pushCredentials.token.map { String(format: "%02.2hhx", $0) }.joined()) } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) { guard type == .voIP else { return } print("call kit") let payloadDict = payload.dictionaryPayload let update = CXCallUpdate() update.remoteHandle = CXHandle(type: .phoneNumber, value: "dsfsdfddsf") update.hasVideo = payloadDict["hasVideo"] as? Bool ?? false provider?.reportNewIncomingCall(with: UUID(), update: update, completion: { error in if let error = error { print("Failed to report incoming call: \(error.localizedDescription)") } else { print("Successfully reported incoming call") } }) } }
1
0
226
Dec ’25
Critical CallKit Issue: Audio Route Flapping due to reason: 3 (CategoryChange) after User Toggle
I am facing a severe audio routing instability issue when using CallKit and the Zego Express SDK on iOS. The problem is that the audio route immediately reverts from the Speaker back to the Earpiece, effectively disabling the Speaker button functionality.📝 Observed BehaviorWhen the user taps the native CallKit Speaker Button, the audio route is correctly changed to the Speaker, but then instantly flips back to the Receiver (Earpiece), as shown in the system log captured via AVAudioSession.routeChangeNotification monitoring.🧾 Log Evidence (Flapping Occurs in 0.4 seconds)The following log snippet clearly illustrates the system overriding the user's action (reason: 4) with an unexpected CategoryChange (reason: 3) event: TimestampComponentReason CodeDescriptionRouteIs Speaker16:31:18.009[CallKitManager]4Override (CallKit/ControlCenter)Loa ngoài (Speaker)true16:31:18.411[CallKitManager]3CategoryChangeThiết bị nhận (Receiver)false
1
0
263
Dec ’25
iOS 26: Unable to Transition from CallKit Screen to App when remoteHandle is nil or empty string
Hello, I am developing an internal phone application using CallKit. I am experiencing an issue with the behavior of remoteHandle settings in iOS 26 and would appreciate any insights you can provide towards a solution. 1. Problem Description When an iPhone running iOS 26 is in a sleep state and receives a VoIP incoming call where remoteHandle is set to nil or an empty string (@""), we are unable to transition to our application (the UIExtension provided by the provider) from the CallKit UI's "More" (…) button after answering the call. 2. Conditions and Symptoms OS Version: iOS 26 Initial State: iPhone is in a sleep state Call Type: An unsolicited(unknown number) VoIP incoming call where the CXCallUpdate's remoteHandle is set to either nil or [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:@""] Symptoms: After answering the VoIP call by sliding the button, selecting the "More" (…) button displayed on the CallKit screen does not launch our application's UIExtension (custom UI), and the iPhone instead stay to the CallKit screen. 3. Previous Behavior (Up to iOS 18) Up to iOS 18, even when remoteHandle was set to an empty string using the following code, the application would transition normally from "More" after answering an incoming call from a sleep state. CXCallUpdate *update = [[CXCallUpdate alloc] init]; update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:@""]; [provider reportNewIncomingCallWithUUID:uuid update:update completion:completion]; 4. Unsuccessful Attempts to Resolve The issue remained unresolved after changing the handling for unsolicited(unknown number) incoming calls as follows: CXCallUpdate *update = [[CXCallUpdate alloc] init]; update.remoteHandle = nil; // Set remoteHandle to nil [provider reportNewIncomingCallWithUUID:uuid update:update completion:completion]; 5. Workaround (Temporary) The problem can be resolved, and the application can transition successfully, by setting a dummy numerical value (e.g., "0") for the value in remoteHandle using the following code: CXCallUpdate *update = [[CXCallUpdate alloc] init]; update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:@"0"]; // Set a dummy numerical value [provider reportNewIncomingCallWithUUID:uuid update:update completion:completion]; 6. Additional Information If remoteHandle is correctly set with the caller's number (i.e., not an unsolicited(unknown number) call; e.g., value:@"1234567890"), the application transitions normally from the "More" button after answering an incoming call from a sleep state, even in iOS 26. The above issue does not occur when answering incoming calls while the iPhone is in an active state (not sleeping). 7. Questions Have there been any other reports of similar behavior? Should this be considered a bug in CallKit for iOS 26? Should I make file a new Feedback report? Is there a suitable method to resolve this issue when the caller ID is unsolicited (nil or an empty string)? This problem significantly impacts user operations as end-users are unable to perform essential in-app actions such as hold or transfer after answering an unsolicited(unknown number) call from a sleep state. We are eager to find an urgent solution and would appreciate any information or advice you can provide. Thank you for your assistance.
5
0
485
Feb ’26
Is there a way to prevent the app from coming to the foreground when accepting a call with a banner-type call kit in a VoIP app?
I'm developing a VoIP app. Currently, I'm using CallKit to control call acceptance, and end-of-call processing. When a call comes in while using the phone, CallKit appears as a banner at the top of the screen. When I click "Accept" on the banner, the app opens and the call is received. (For OEMs, clicking the "Accept" button in the banner will accept the call as is.) The reason this feature is needed is, for example, when a call comes in as a banner call while using a navigation app, accepting the call causes the navigation app to go to the back and the VoIP app to come to the foreground, causing inconvenience to customers. This needs to be improved. Please advise.
1
0
119
Dec ’25
CXCallDirectoryProvider – Numbers added but blocking not working
Hi all, I'm working on a Call Directory Extension using CXCallDirectoryExtensionContext. I want to add a list of numbers to be blocked. Here's the function I use: override func beginRequest(with context: CXCallDirectoryExtensionContext) { context.delegate = self let blockedNumbers = loadNumberEntries(forKey: blockedKey) let identifiedNumbers = loadNumberEntries(forKey: identifiedKey) addAllBlocking(blockedNumbers, to: context) addAllIdentification(identifiedNumbers, to: context) context.completeRequest() } private func addAllBlocking(_ entries: [NumberEntry], to context: CXCallDirectoryExtensionContext) { let numbers: [Int64] = entries.compactMap { Int64($0.countryCode + $0.phone) }.sorted() for number in numbers { context.addBlockingEntry(withNextSequentialPhoneNumber: number) print("# Added blocking entry: \(number)") } } When I run this, I see in the console: # Added blocking entry: (*my number with country code*) So it seems the number is added correctly. However, in practice, the number is not blocked on the device. I’ve made sure that: The number is stored with the country code prefix. The extension is enabled in Settings → Phone → Call Blocking & Identification. The extension is reloaded after adding numbers. The array of numbers is sorted in ascending order before calling addBlockingEntry. Despite all this, the number still isn’t blocked. Does anyone know why the print shows the number added, but it doesn’t actually block the call? Am I missing something in the way CXCallDirectoryExtensionContext works? Thanks for any advice!
1
0
919
Jan ’26
CallKit automatically shows a system top toast after iOS 26, how to dismiss it?
I’m developing an iOS app that integrates with CallKit. Starting from iOS 26, I’ve noticed that the system automatically presents a top banner / toast-style UI when a CallKit call becomes active (see attached screenshot). This UI appears to be fully managed by the system. On iOS versions prior to iOS 26, this UI did not appear under the same CallKit configuration. What I’ve observed The banner is displayed automatically by the system It appears at the top of the screen, similar to a toast or call status banner It is not a view created by my app I could not find any public API or CallKit configuration related to dismissing or controlling it My questions: Is this top banner an intended system behavior change in newer iOS versions? Is there any public API to dismiss, hide, or customize this UI? If not, is this UI considered non-dismissible by design? Any clarification on the expected behavior or recommended approach would be greatly appreciated.
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
284
Jan ’26
long wait time for usernotifications.filtering entitlement
Hi, happy new year, I'm a Product Manager for a communications app that's currently in testflight. We requested the com.apple.developer.usernotifications.filtering entitlement on December 3rd, and have yet to receive a response from Apple. I understand that the holiday break may have gotten in the way, however it feels like we were lost in the queue as it's been 6 weeks with no response. Our app owner has checked-in inside appstoreconnect but has not received anything back. Is this common? Is there any process for getting a status update? Are we doing something wrong? Without this entitlement we cannot make the device ring in the background. The app is a voice and video messaging platform.
1
2
376
Jan ’26
What are the image requirements for the logo for Live Caller ID?
When Live Caller ID first came out I experimented with it and got it working using the Example PIR database. All my links from that time are now out of date and no longer work, however I seem to have found where the PIR database example and documentation has moved to (https://swiftpackageindex.com/apple/pir-service-example/main/documentation/pirservice/testinginstructionslivecalleridlookup) But what I can't find is an exact definition of the the logo size/max size/dimensions/format should be. My memory from that time is that it was very pernickety, and if things weren't exactly right, the logo wasn't displayed. I can remember the format had to be HEIC to get it to work. Looking through the documentation however, I can't see exact requirements specified. My question is - for the Live Caller ID logo what are the exact image requirements, and where are they documented?
0
0
93
Feb ’26
About audio playback panel after call end.
Dear Apple Support Team, Thank you for your continued support. I would like to inquire about the behavior of CallKit. Our company provides an office PBX extension phone application (iPhone app). When the iPhone is placed into sleep mode (screen off) and our app receives an incoming call, the following sequence sometimes results in an audio playback panel appearing at the bottom of the lock screen for a few seconds after the call ends(See attachment file for detail). Sequence to reproduce the issue: Put the iPhone into sleep mode (screen off). Receive an incoming call to our extension phone app. CallKit incoming call screen appears. Answer the call. Conduct the call. End the call from the peer. iOS versions with confirmed behavior: iOS 26.0: Not observed. iOS 26.2: Observed. iOS 26.3: Not observed. This behavior does not affect the call functionality itself; however, some users report that the temporary appearance of the audio playback panel feels unusual. If there is any known reason for this behavior or any recommended workaround, we would greatly appreciate your guidance. Additionally, if this is a known issue that was addressed in iOS 26.3, we would appreciate any information you can provide regarding that as well. Thank you very much for your assistance.
2
0
166
Feb ’26
New PushKit delegate in iOS 26.4
Starting in iOS 26.4, PushKit has introduced a new "didReceiveIncomingVoIPPushWithPayload" delegate, making it explicit whether or not an app is required to report a call for any given push. The new delegate passes in a PKVoIPPushMetadata object which includes a "mustReport" property. We have not documented the exact criteria that will cause a mustReport to return false, but those criteria currently include: The app being in the foreground at the point the push is received. The app being on an active call at the point the push is received. The system determines that delivery delays have made the call old enough that it may no longer be viable. When mustReport is false, apps should call the PushKit completion handler (as they previously have) but are otherwise not required to take any other action. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
0
0
233
Feb ’26
iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call
iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call Description I have successfully implemented VoIP pushes for the Killed state, where CallKit triggers correctly. However, when the app is in the Background state (suspended), it consistently crashes with an NSInternalInconsistencyException. The app process is killed by the iOS Watchdog because it fails to satisfy the requirement of posting an incoming call in the same run loop as the push receipt, or the completion handler is not being released fast enough by the JS bridge. Environment React Native Version: .78 React Native CallKeep Version: 4.3.14 React Native VoIP Push Notification Version: 3.3.3 iOS Version: 18.x Device: Physical iPhone [iphone 13 pro] The Issue When a VoIP push arrives while the app is in the Background: pushRegistry:didReceiveIncomingPushWithPayload: is called. RNCallKeep.reportNewIncomingCall is triggered on the Main Thread. The app is terminated by the system before the CallKit UI is fully established or before the completion() closure is executed. Current Implementation (AppDelegate.swift) func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { let payloadDict = payload.dictionaryPayload let callerName = payloadDict["callerName"] as? String ?? "Unknown Caller" let callUUIDString = payloadDict["uuid"] as? String ?? UUID().uuidString let userGUID = payloadDict["guid"] as? String ?? "0" RNCallKeep.reportNewIncomingCall( callUUIDString, handle: userGUID, handleType: "generic", hasVideo: false, localizedCallerName: callerName, supportsHolding: true, supportsDTMF: true, supportsGrouping: true, supportsUngrouping: true, fromPushKit: true, payload: ["userGuid": userGUID], withCompletionHandler: { } ) RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue) completion() } Logs Exception Type: EXC_CRASH (SIGKILL) Exception Note: EXC_CORPSE_NOTIFY Termination Reason: TCC 1 | [CoreFoundation] Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push. Observed Behavior Killed State: Works perfectly. Foreground State: Works perfectly. Background State: The phone may vibrate once, but the app process is killed before the CallKit UI appears. Questions/Suspected Causes Is RNVoipPushNotificationManager.addCompletionHandler causing a delay in the background run loop that triggers the Watchdog? Should completion() be called immediately in Swift for the Background state, rather than waiting for VoipPushNotification.onVoipNotificationCompleted in JS? Is there a known issue with RNCallKeep not being able to present the UI while the app is in a suspended background state?
3
0
189
Feb ’26
Frequent providerDidReset Callbacks in Production
Hello, We're seeing a high rate of providerDidReset callbacks in production across a large user base (iOS 16, 17, 18, and 26). I'd like to understand both the correct way to handle this delegate method and strategies to reduce its frequency. Background The callback occurs across all iOS versions we support and is not isolated to a specific device or region. The callback can occur in any app state (foreground, background, inactive), however it is most dominant in the background state — particularly during VoIP push notification handling. The callback is more prevalent during long app sessions — for example, when the app has been running continuously for a day or overnight. We do not call CXProvider.invalidate() anywhere in our codebase explicitly. After providerDidReset fires, subsequent transactions fail with CXErrorCodeRequestTransactionErrorUnknownCallUUID (error code 4). Re-initializing the provider via initializeProvider() resolves this error. Our Implementation We use a singleton proxy class (CallKitProxy) that owns the CXProvider. Below is a simplified version — some logging and non-essential parts have been removed for brevity. @objcMembers public final class CallKitProxy: NSObject { private var cxProvider: CXProvider? private let cxCallController: CXCallController private let cxCallObserver: CXCallObserver private override init() { cxCallObserver = CXCallObserver() cxCallController = CXCallController() super.init() initializeProvider() cxCallObserver.setDelegate(self, queue: nil) } private func initializeProvider() { let configuration = providerConfiguration() cxProvider = CXProvider(configuration: configuration) cxProvider?.setDelegate(self, queue: nil) } private func providerConfiguration() -> CXProviderConfiguration { let soundName = SharedUDHelper.shared.string(forKey: .pushNotificationSoundNameForCall) let sound = CallNotificationSounds(name: soundName ?? "ringtoneDefault") let configuration = CXProviderConfiguration() configuration.supportsVideo = true configuration.maximumCallsPerCallGroup = 1 configuration.maximumCallGroups = 1 configuration.supportedHandleTypes = [.phoneNumber, .generic] configuration.iconTemplateImageData = UIImage( named: "callkit_mask", in: .main, compatibleWith: nil )?.pngData() configuration.ringtoneSound = sound.name return configuration } public func requestTransaction( action: CXCallAction, completion: @escaping (Error?) -> Void ) { let transaction = CXTransaction(action: action) cxCallController.request(transaction) { error in completion(error) } } } extension CallKitProxy: CXProviderDelegate { public func providerDidReset(_ provider: CXProvider) { // End any active calls, then re-initialize the provider initializeProvider() } } Questions 1. Is re-initializing the provider inside providerDidReset the correct approach? The documentation states that providerDidReset signals the provider has been reset and all calls should be considered terminated. Should we be calling CXProvider.invalidate() on the old instance before creating a new one? Or is assigning a new CXProvider to cxProvider (which releases the old instance) sufficient? 2. What could be causing providerDidReset to fire so frequently, and how can we reduce it? We're particularly concerned about cases triggered during VoIP push handling in the background and inactive states. Are there known conditions — such as provider configuration changes, app lifecycle events, or system memory pressure — that commonly trigger this callback? And are there any recommended patterns to make the provider more resilient in these scenarios? Thank you.
1
0
146
4w
Live Caller ID Lookup: does iOS call /queries even when the number is in Contacts?
Hi! We’ve had Live Caller ID Lookup in production for a while. We’re seeing backend RPS on our /queries endpoint much higher than our expected incoming call volume. While testing with Console.app during an incoming call, it looks like iOS may still hit our service even when the caller number is already in the user’s Contacts - but I’m not 100% sure from logs alone. Can you confirm: Does iOS invoke Live Caller ID Lookup (i.e. call /queries) for every incoming call, including calls from saved Contacts? If yes, is this simply expected framework behavior? Thanks!
0
0
95
4w
Questions about VoIP Push compliance rules and CallKit handling
Hello everyone, I’m an iOS developer working on a real-time communication app that supports VoIP calls using CallKit. The app has been in production for more than 5 years. Over the years, some users have occasionally reported that they do not receive incoming call pushes. We have tried multiple optimizations on both the client and server side, but the improvement has been limited. From Apple documentation and discussions online, I understand that iOS may restrict VoIP pushes if the system detects violations of VoIP push usage rules (for example, not presenting a CallKit call after receiving a VoIP push). However, the exact rules and thresholds for these violations are not clearly documented, so I’d like to ask a few questions to better understand the expected behavior. Below is a simplified description of our current call flow. Call Flow Caller When the user initiates a call: We do not use CallKit The call is handled entirely using a custom in-app call UI Callee When the user receives a call: Device locked or app in background A VoIP push wakes the app The app presents the CallKit incoming call UI App in foreground The server still sends a VoIP push The app first reports the call to CallKit After a very short delay, the app programmatically ends the CallKit call Then a custom in-app call UI is presented via the app's long connection The reason we always send a VoIP push (even when the app is in the foreground) is that we want to maximize call delivery reliability.
5
0
285
3w
Clarification on Allowed Uses of VoIP Push Notifications for Ending/Updating CallKit State
Hello, I’m implementing VoIP calling in an iOS application using PushKit (VoIP pushes) together with CallKit. The standard call flow works correctly: Happy scenario User A initiates a call. Server sends a VoIP push to User B. User B’s device receives the push and reports the incoming call using CallKit. User B answers the call. However, I would like clarification about non-happy scenarios and when it is acceptable to use VoIP pushes to update or stop a CallKit ringing state. Apple documentation warns that VoIP pushes must be used only when they result in a call-related action, so I want to ensure the following cases are compliant. Scenario A — Caller Cancels Before Answer User A calls User B. Server sends a VoIP push to User B. User B’s device starts ringing via CallKit. Before User B answers, User A cancels the call. Question: Is it acceptable to send another VoIP push to User B indicating that the call has been cancelled so the device can: stop the CallKit ringing UI end the call optionally mark it as missed or cancelled Or should this state change be handled using a regular remote push or another signaling mechanism instead of VoIP push? Scenario B — Callee Rejects the Call User B rejects the call from CallKit. The server must inform User A that the call was rejected. Question: Is it acceptable to send a VoIP push to User A to update the CallKit state and terminate the outgoing call UI? Scenario C — Multiple Devices per User User B may be logged in on multiple devices. User A calls User B. VoIP push is sent to all devices of User B. One device answers. Question: Is it acceptable to send a VoIP push to the remaining devices instructing them to: stop ringing end the CallKit incoming call UI Or is there a recommended alternative pattern for this case? Main Question Aside from the initial incoming call VoIP push, in which situations is it considered acceptable to send additional VoIP pushes to terminate or update CallKit state (cancelled, rejected, answered on another device)? The goal is to remain compliant with PushKit policies, particularly the guidance that VoIP pushes should only be used when they result in a call-related user action. Any guidance on the recommended architecture for these cases would be greatly appreciated. Thank you.
1
0
129
3w
LiveCommunicationKit on watchOS: Displaying visual content during active call?
Our watchOS app is exploring adding audio VOIP calling capability using our in-home platform. We are using LiveCommunicationKit for this and have that all hooked up nicely in a proof of concept implementation. Our use case is primarily based around supporting end-users through various tasks with assistance from a remotely based expert. We would like for our platform to be able to display visual content on the watch's screen during the call – in other words, we would like to be able to treat this as a video call. LiveCommunicationKit fully supports all video-related flags on watchOS and doesn't appear to have any different symbol availability versus its iOS version. This high-quality thread (https://developer.apple.com/forums/thread/798090) from a DTS engineer suggests that our use case should be valid (i.e. whiteboarding apps) and that the system's response to an accepted income video call is to dismiss the LCK's incoming call screen and bring the target app to the foreground, allowing it to render its custom content. Unfortunately, on watchOS the system doesn't seem to treat a video call any differently from an audio call, and won't dismiss the system UI once it's answered. We fully realize that Apple Watch doesn't have a camera for outbound video, doesn't support VideoToolbox or other low-level video convenience libraries for simplified rendering and decoding, etc. That's not what we're worried about (yet). The documentation is at best unclear about whether LCK (or CallKit, for that matter) can hand off calls flagged as video-compatible according to how we think they should, which is passing foreground UI over to the app once the call has been accepted by the user. Can any Apple people shed some light on this? I recognize we are probably trying to do something not many people have before.
2
0
87
3w
Call log
I read online that there is no way to extract the call log from an iPhone. I want to develop an app to help people remember to call their mom, and if they did, the "nagging" would disappear automatically. I'm looking for any workaround to know when a user called someone, without having them log it manually.
Replies
1
Boosts
0
Views
445
Activity
Dec ’25
CallKit VoIP → App launch → Auto WebRTC/MobileRTC connection: Does Apple allow this flow?
Our app receives a CallKit VoIP call. When the user taps “Answer”, the app launches and automatically connects to a real-time audio session using WebRTC or MobileRTC. We would like to confirm whether the following flow (“CallKit Answer → app opens → automatic WebRTC or MobileRTC audio session connection”) complies with Apple’s VoIP Push / CallKit policy. In addition, our service also provides real-time video-class functionality using the Zoom Meeting SDK (MobileRTC). When an incoming CallKit VoIP call is answered, the app launches and the user is automatically taken to the Zoom-based video lesson flow: the app opens → the user is landed on the Zoom Meeting pre-meeting room → MobileRTC initializes immediately. In the pre-meeting room, audio and video streams can already be active and MobileRTC establishes a connection, but the actual meeting screen is not joined until the user explicitly taps “Join”. We would like to confirm whether this flow for video lessons (“CallKit Answer → app opens → pre-meeting room (audio/video active) → user taps ‘Join’ → enter actual meeting”) is also compliant with Apple’s VoIP Push and CallKit policy.
Replies
1
Boosts
0
Views
126
Activity
Dec ’25
Are notification pushes not being received when in Picture-in-Picture mode?
Hello, I recently had an unusual experience, and I’m wondering if this is related to Apple’s policies, so I wanted to ask. While a call is in Picture-in-Picture (PIP) mode, notification pushes from the same app do not appear. The API is being triggered, but the notification banner does not show on the device. Once PIP is closed, the notifications start appearing normally again. Is this behavior enforced by Apple’s policies? What’s interesting is that banners from other apps do appear — only the banners from the app currently in PIP are not shown.
Replies
1
Boosts
0
Views
222
Activity
Dec ’25
CallKit issue
In iOS 26.1, after my app answers a VoIP call on the lock screen, tapping the bottom-left "More" button doesn't bring up the app icon to jump to the app. The same scenario works normally on iOS 26. How can I resolve this issue?
Replies
1
Boosts
1
Views
132
Activity
Dec ’25
VoIP Push Notifications Not Delivered in Background/Killed State (Using AppDelegate)
Hello, colleagues. I am reaching out to the community with an issue that is likely quite common. Unfortunately, I have not been able to resolve it independently and would like to confirm if my approach is correct. Core Problem: VoIP push notifications are not delivered to the application when it is in the background or terminated. After reviewing existing discussions on the forum, I concluded that the cause might be related to CallKit not having enough time to register. However, in my case, I am using AppDelegate, and in theory, CallKit registration should occur quickly enough. Nevertheless, the issue persists. Additional Question: I would also like to clarify the possibility of customizing the CallKit interface. Specifically, I am interested in adding custom buttons (for example, to open a door). Please advise if such functionality is supported by CallKit itself, or if a different approach is required for its implementation. Thank you in advance for your time and attention to my questions. For a more detailed analysis, I have attached a fragment of my code below. I hope this will help clarify the situation. Main File @main struct smartappApp: App { @UIApplicationDelegateAdaptor private var delegate: AppDelegate @StateObject private var navigationManager = NavigationManager() init() { print("Xct") if !isRunningTests() { DILocator.instance .registerModules([ ConfigModule(), SipModule(), AuthModule(), NetworkModule(), CoreDataModule(), RepositoryModule(), DataUseCaseModule(), SipUseCaseModule() ]) } } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { print("Axtest") completionHandler(.newData) } var body: some Scene { App Delegate File class AppDelegate: UIResponder, UIApplicationDelegate { private let voipRegistry = PKPushRegistry(queue: .main) private var provider: CXProvider? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { setupPushKit() setupCallKit() return true } public func regist(){ setupPushKit() setupCallKit() } private func setupPushKit() { voipRegistry.delegate = self voipRegistry.desiredPushTypes = [.voIP] DispatchQueue.main.async { self.voipRegistry.pushToken(for: .voIP) } } // MARK: - CallKit Setup private func setupCallKit() { let configuration = CXProviderConfiguration(localizedName: "MyApp") configuration.maximumCallGroups = 1 configuration.maximumCallsPerCallGroup = 1 configuration.supportsVideo = true configuration.iconTemplateImageData = UIImage(named: "callIcon")?.pngData() provider = CXProvider(configuration: configuration) provider?.setDelegate(self, queue: .main) } // MARK: - Background Launch Handling func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { print("Axtest") completionHandler(.newData) } } extension AppDelegate: PKPushRegistryDelegate { func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { APNsImpl().registerToken(token: pushCredentials.token.map { String(format: "%02.2hhx", $0) }.joined()) } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) { guard type == .voIP else { return } print("call kit") let payloadDict = payload.dictionaryPayload let update = CXCallUpdate() update.remoteHandle = CXHandle(type: .phoneNumber, value: "dsfsdfddsf") update.hasVideo = payloadDict["hasVideo"] as? Bool ?? false provider?.reportNewIncomingCall(with: UUID(), update: update, completion: { error in if let error = error { print("Failed to report incoming call: \(error.localizedDescription)") } else { print("Successfully reported incoming call") } }) } }
Replies
1
Boosts
0
Views
226
Activity
Dec ’25
Critical CallKit Issue: Audio Route Flapping due to reason: 3 (CategoryChange) after User Toggle
I am facing a severe audio routing instability issue when using CallKit and the Zego Express SDK on iOS. The problem is that the audio route immediately reverts from the Speaker back to the Earpiece, effectively disabling the Speaker button functionality.📝 Observed BehaviorWhen the user taps the native CallKit Speaker Button, the audio route is correctly changed to the Speaker, but then instantly flips back to the Receiver (Earpiece), as shown in the system log captured via AVAudioSession.routeChangeNotification monitoring.🧾 Log Evidence (Flapping Occurs in 0.4 seconds)The following log snippet clearly illustrates the system overriding the user's action (reason: 4) with an unexpected CategoryChange (reason: 3) event: TimestampComponentReason CodeDescriptionRouteIs Speaker16:31:18.009[CallKitManager]4Override (CallKit/ControlCenter)Loa ngoài (Speaker)true16:31:18.411[CallKitManager]3CategoryChangeThiết bị nhận (Receiver)false
Replies
1
Boosts
0
Views
263
Activity
Dec ’25
iOS 26: Unable to Transition from CallKit Screen to App when remoteHandle is nil or empty string
Hello, I am developing an internal phone application using CallKit. I am experiencing an issue with the behavior of remoteHandle settings in iOS 26 and would appreciate any insights you can provide towards a solution. 1. Problem Description When an iPhone running iOS 26 is in a sleep state and receives a VoIP incoming call where remoteHandle is set to nil or an empty string (@""), we are unable to transition to our application (the UIExtension provided by the provider) from the CallKit UI's "More" (…) button after answering the call. 2. Conditions and Symptoms OS Version: iOS 26 Initial State: iPhone is in a sleep state Call Type: An unsolicited(unknown number) VoIP incoming call where the CXCallUpdate's remoteHandle is set to either nil or [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:@""] Symptoms: After answering the VoIP call by sliding the button, selecting the "More" (…) button displayed on the CallKit screen does not launch our application's UIExtension (custom UI), and the iPhone instead stay to the CallKit screen. 3. Previous Behavior (Up to iOS 18) Up to iOS 18, even when remoteHandle was set to an empty string using the following code, the application would transition normally from "More" after answering an incoming call from a sleep state. CXCallUpdate *update = [[CXCallUpdate alloc] init]; update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:@""]; [provider reportNewIncomingCallWithUUID:uuid update:update completion:completion]; 4. Unsuccessful Attempts to Resolve The issue remained unresolved after changing the handling for unsolicited(unknown number) incoming calls as follows: CXCallUpdate *update = [[CXCallUpdate alloc] init]; update.remoteHandle = nil; // Set remoteHandle to nil [provider reportNewIncomingCallWithUUID:uuid update:update completion:completion]; 5. Workaround (Temporary) The problem can be resolved, and the application can transition successfully, by setting a dummy numerical value (e.g., "0") for the value in remoteHandle using the following code: CXCallUpdate *update = [[CXCallUpdate alloc] init]; update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:@"0"]; // Set a dummy numerical value [provider reportNewIncomingCallWithUUID:uuid update:update completion:completion]; 6. Additional Information If remoteHandle is correctly set with the caller's number (i.e., not an unsolicited(unknown number) call; e.g., value:@"1234567890"), the application transitions normally from the "More" button after answering an incoming call from a sleep state, even in iOS 26. The above issue does not occur when answering incoming calls while the iPhone is in an active state (not sleeping). 7. Questions Have there been any other reports of similar behavior? Should this be considered a bug in CallKit for iOS 26? Should I make file a new Feedback report? Is there a suitable method to resolve this issue when the caller ID is unsolicited (nil or an empty string)? This problem significantly impacts user operations as end-users are unable to perform essential in-app actions such as hold or transfer after answering an unsolicited(unknown number) call from a sleep state. We are eager to find an urgent solution and would appreciate any information or advice you can provide. Thank you for your assistance.
Replies
5
Boosts
0
Views
485
Activity
Feb ’26
Is there a way to prevent the app from coming to the foreground when accepting a call with a banner-type call kit in a VoIP app?
I'm developing a VoIP app. Currently, I'm using CallKit to control call acceptance, and end-of-call processing. When a call comes in while using the phone, CallKit appears as a banner at the top of the screen. When I click "Accept" on the banner, the app opens and the call is received. (For OEMs, clicking the "Accept" button in the banner will accept the call as is.) The reason this feature is needed is, for example, when a call comes in as a banner call while using a navigation app, accepting the call causes the navigation app to go to the back and the VoIP app to come to the foreground, causing inconvenience to customers. This needs to be improved. Please advise.
Replies
1
Boosts
0
Views
119
Activity
Dec ’25
CXCallDirectoryProvider – Numbers added but blocking not working
Hi all, I'm working on a Call Directory Extension using CXCallDirectoryExtensionContext. I want to add a list of numbers to be blocked. Here's the function I use: override func beginRequest(with context: CXCallDirectoryExtensionContext) { context.delegate = self let blockedNumbers = loadNumberEntries(forKey: blockedKey) let identifiedNumbers = loadNumberEntries(forKey: identifiedKey) addAllBlocking(blockedNumbers, to: context) addAllIdentification(identifiedNumbers, to: context) context.completeRequest() } private func addAllBlocking(_ entries: [NumberEntry], to context: CXCallDirectoryExtensionContext) { let numbers: [Int64] = entries.compactMap { Int64($0.countryCode + $0.phone) }.sorted() for number in numbers { context.addBlockingEntry(withNextSequentialPhoneNumber: number) print("# Added blocking entry: \(number)") } } When I run this, I see in the console: # Added blocking entry: (*my number with country code*) So it seems the number is added correctly. However, in practice, the number is not blocked on the device. I’ve made sure that: The number is stored with the country code prefix. The extension is enabled in Settings → Phone → Call Blocking & Identification. The extension is reloaded after adding numbers. The array of numbers is sorted in ascending order before calling addBlockingEntry. Despite all this, the number still isn’t blocked. Does anyone know why the print shows the number added, but it doesn’t actually block the call? Am I missing something in the way CXCallDirectoryExtensionContext works? Thanks for any advice!
Replies
1
Boosts
0
Views
919
Activity
Jan ’26
CallKit automatically shows a system top toast after iOS 26, how to dismiss it?
I’m developing an iOS app that integrates with CallKit. Starting from iOS 26, I’ve noticed that the system automatically presents a top banner / toast-style UI when a CallKit call becomes active (see attached screenshot). This UI appears to be fully managed by the system. On iOS versions prior to iOS 26, this UI did not appear under the same CallKit configuration. What I’ve observed The banner is displayed automatically by the system It appears at the top of the screen, similar to a toast or call status banner It is not a view created by my app I could not find any public API or CallKit configuration related to dismissing or controlling it My questions: Is this top banner an intended system behavior change in newer iOS versions? Is there any public API to dismiss, hide, or customize this UI? If not, is this UI considered non-dismissible by design? Any clarification on the expected behavior or recommended approach would be greatly appreciated.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
2
Boosts
0
Views
284
Activity
Jan ’26
long wait time for usernotifications.filtering entitlement
Hi, happy new year, I'm a Product Manager for a communications app that's currently in testflight. We requested the com.apple.developer.usernotifications.filtering entitlement on December 3rd, and have yet to receive a response from Apple. I understand that the holiday break may have gotten in the way, however it feels like we were lost in the queue as it's been 6 weeks with no response. Our app owner has checked-in inside appstoreconnect but has not received anything back. Is this common? Is there any process for getting a status update? Are we doing something wrong? Without this entitlement we cannot make the device ring in the background. The app is a voice and video messaging platform.
Replies
1
Boosts
2
Views
376
Activity
Jan ’26
What are the image requirements for the logo for Live Caller ID?
When Live Caller ID first came out I experimented with it and got it working using the Example PIR database. All my links from that time are now out of date and no longer work, however I seem to have found where the PIR database example and documentation has moved to (https://swiftpackageindex.com/apple/pir-service-example/main/documentation/pirservice/testinginstructionslivecalleridlookup) But what I can't find is an exact definition of the the logo size/max size/dimensions/format should be. My memory from that time is that it was very pernickety, and if things weren't exactly right, the logo wasn't displayed. I can remember the format had to be HEIC to get it to work. Looking through the documentation however, I can't see exact requirements specified. My question is - for the Live Caller ID logo what are the exact image requirements, and where are they documented?
Replies
0
Boosts
0
Views
93
Activity
Feb ’26
About audio playback panel after call end.
Dear Apple Support Team, Thank you for your continued support. I would like to inquire about the behavior of CallKit. Our company provides an office PBX extension phone application (iPhone app). When the iPhone is placed into sleep mode (screen off) and our app receives an incoming call, the following sequence sometimes results in an audio playback panel appearing at the bottom of the lock screen for a few seconds after the call ends(See attachment file for detail). Sequence to reproduce the issue: Put the iPhone into sleep mode (screen off). Receive an incoming call to our extension phone app. CallKit incoming call screen appears. Answer the call. Conduct the call. End the call from the peer. iOS versions with confirmed behavior: iOS 26.0: Not observed. iOS 26.2: Observed. iOS 26.3: Not observed. This behavior does not affect the call functionality itself; however, some users report that the temporary appearance of the audio playback panel feels unusual. If there is any known reason for this behavior or any recommended workaround, we would greatly appreciate your guidance. Additionally, if this is a known issue that was addressed in iOS 26.3, we would appreciate any information you can provide regarding that as well. Thank you very much for your assistance.
Replies
2
Boosts
0
Views
166
Activity
Feb ’26
New PushKit delegate in iOS 26.4
Starting in iOS 26.4, PushKit has introduced a new "didReceiveIncomingVoIPPushWithPayload" delegate, making it explicit whether or not an app is required to report a call for any given push. The new delegate passes in a PKVoIPPushMetadata object which includes a "mustReport" property. We have not documented the exact criteria that will cause a mustReport to return false, but those criteria currently include: The app being in the foreground at the point the push is received. The app being on an active call at the point the push is received. The system determines that delivery delays have made the call old enough that it may no longer be viable. When mustReport is false, apps should call the PushKit completion handler (as they previously have) but are otherwise not required to take any other action. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
Replies
0
Boosts
0
Views
233
Activity
Feb ’26
iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call
iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call Description I have successfully implemented VoIP pushes for the Killed state, where CallKit triggers correctly. However, when the app is in the Background state (suspended), it consistently crashes with an NSInternalInconsistencyException. The app process is killed by the iOS Watchdog because it fails to satisfy the requirement of posting an incoming call in the same run loop as the push receipt, or the completion handler is not being released fast enough by the JS bridge. Environment React Native Version: .78 React Native CallKeep Version: 4.3.14 React Native VoIP Push Notification Version: 3.3.3 iOS Version: 18.x Device: Physical iPhone [iphone 13 pro] The Issue When a VoIP push arrives while the app is in the Background: pushRegistry:didReceiveIncomingPushWithPayload: is called. RNCallKeep.reportNewIncomingCall is triggered on the Main Thread. The app is terminated by the system before the CallKit UI is fully established or before the completion() closure is executed. Current Implementation (AppDelegate.swift) func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { let payloadDict = payload.dictionaryPayload let callerName = payloadDict["callerName"] as? String ?? "Unknown Caller" let callUUIDString = payloadDict["uuid"] as? String ?? UUID().uuidString let userGUID = payloadDict["guid"] as? String ?? "0" RNCallKeep.reportNewIncomingCall( callUUIDString, handle: userGUID, handleType: "generic", hasVideo: false, localizedCallerName: callerName, supportsHolding: true, supportsDTMF: true, supportsGrouping: true, supportsUngrouping: true, fromPushKit: true, payload: ["userGuid": userGUID], withCompletionHandler: { } ) RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue) completion() } Logs Exception Type: EXC_CRASH (SIGKILL) Exception Note: EXC_CORPSE_NOTIFY Termination Reason: TCC 1 | [CoreFoundation] Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push. Observed Behavior Killed State: Works perfectly. Foreground State: Works perfectly. Background State: The phone may vibrate once, but the app process is killed before the CallKit UI appears. Questions/Suspected Causes Is RNVoipPushNotificationManager.addCompletionHandler causing a delay in the background run loop that triggers the Watchdog? Should completion() be called immediately in Swift for the Background state, rather than waiting for VoipPushNotification.onVoipNotificationCompleted in JS? Is there a known issue with RNCallKeep not being able to present the UI while the app is in a suspended background state?
Replies
3
Boosts
0
Views
189
Activity
Feb ’26
Frequent providerDidReset Callbacks in Production
Hello, We're seeing a high rate of providerDidReset callbacks in production across a large user base (iOS 16, 17, 18, and 26). I'd like to understand both the correct way to handle this delegate method and strategies to reduce its frequency. Background The callback occurs across all iOS versions we support and is not isolated to a specific device or region. The callback can occur in any app state (foreground, background, inactive), however it is most dominant in the background state — particularly during VoIP push notification handling. The callback is more prevalent during long app sessions — for example, when the app has been running continuously for a day or overnight. We do not call CXProvider.invalidate() anywhere in our codebase explicitly. After providerDidReset fires, subsequent transactions fail with CXErrorCodeRequestTransactionErrorUnknownCallUUID (error code 4). Re-initializing the provider via initializeProvider() resolves this error. Our Implementation We use a singleton proxy class (CallKitProxy) that owns the CXProvider. Below is a simplified version — some logging and non-essential parts have been removed for brevity. @objcMembers public final class CallKitProxy: NSObject { private var cxProvider: CXProvider? private let cxCallController: CXCallController private let cxCallObserver: CXCallObserver private override init() { cxCallObserver = CXCallObserver() cxCallController = CXCallController() super.init() initializeProvider() cxCallObserver.setDelegate(self, queue: nil) } private func initializeProvider() { let configuration = providerConfiguration() cxProvider = CXProvider(configuration: configuration) cxProvider?.setDelegate(self, queue: nil) } private func providerConfiguration() -> CXProviderConfiguration { let soundName = SharedUDHelper.shared.string(forKey: .pushNotificationSoundNameForCall) let sound = CallNotificationSounds(name: soundName ?? "ringtoneDefault") let configuration = CXProviderConfiguration() configuration.supportsVideo = true configuration.maximumCallsPerCallGroup = 1 configuration.maximumCallGroups = 1 configuration.supportedHandleTypes = [.phoneNumber, .generic] configuration.iconTemplateImageData = UIImage( named: "callkit_mask", in: .main, compatibleWith: nil )?.pngData() configuration.ringtoneSound = sound.name return configuration } public func requestTransaction( action: CXCallAction, completion: @escaping (Error?) -> Void ) { let transaction = CXTransaction(action: action) cxCallController.request(transaction) { error in completion(error) } } } extension CallKitProxy: CXProviderDelegate { public func providerDidReset(_ provider: CXProvider) { // End any active calls, then re-initialize the provider initializeProvider() } } Questions 1. Is re-initializing the provider inside providerDidReset the correct approach? The documentation states that providerDidReset signals the provider has been reset and all calls should be considered terminated. Should we be calling CXProvider.invalidate() on the old instance before creating a new one? Or is assigning a new CXProvider to cxProvider (which releases the old instance) sufficient? 2. What could be causing providerDidReset to fire so frequently, and how can we reduce it? We're particularly concerned about cases triggered during VoIP push handling in the background and inactive states. Are there known conditions — such as provider configuration changes, app lifecycle events, or system memory pressure — that commonly trigger this callback? And are there any recommended patterns to make the provider more resilient in these scenarios? Thank you.
Replies
1
Boosts
0
Views
146
Activity
4w
Live Caller ID Lookup: does iOS call /queries even when the number is in Contacts?
Hi! We’ve had Live Caller ID Lookup in production for a while. We’re seeing backend RPS on our /queries endpoint much higher than our expected incoming call volume. While testing with Console.app during an incoming call, it looks like iOS may still hit our service even when the caller number is already in the user’s Contacts - but I’m not 100% sure from logs alone. Can you confirm: Does iOS invoke Live Caller ID Lookup (i.e. call /queries) for every incoming call, including calls from saved Contacts? If yes, is this simply expected framework behavior? Thanks!
Replies
0
Boosts
0
Views
95
Activity
4w
Questions about VoIP Push compliance rules and CallKit handling
Hello everyone, I’m an iOS developer working on a real-time communication app that supports VoIP calls using CallKit. The app has been in production for more than 5 years. Over the years, some users have occasionally reported that they do not receive incoming call pushes. We have tried multiple optimizations on both the client and server side, but the improvement has been limited. From Apple documentation and discussions online, I understand that iOS may restrict VoIP pushes if the system detects violations of VoIP push usage rules (for example, not presenting a CallKit call after receiving a VoIP push). However, the exact rules and thresholds for these violations are not clearly documented, so I’d like to ask a few questions to better understand the expected behavior. Below is a simplified description of our current call flow. Call Flow Caller When the user initiates a call: We do not use CallKit The call is handled entirely using a custom in-app call UI Callee When the user receives a call: Device locked or app in background A VoIP push wakes the app The app presents the CallKit incoming call UI App in foreground The server still sends a VoIP push The app first reports the call to CallKit After a very short delay, the app programmatically ends the CallKit call Then a custom in-app call UI is presented via the app's long connection The reason we always send a VoIP push (even when the app is in the foreground) is that we want to maximize call delivery reliability.
Replies
5
Boosts
0
Views
285
Activity
3w
Clarification on Allowed Uses of VoIP Push Notifications for Ending/Updating CallKit State
Hello, I’m implementing VoIP calling in an iOS application using PushKit (VoIP pushes) together with CallKit. The standard call flow works correctly: Happy scenario User A initiates a call. Server sends a VoIP push to User B. User B’s device receives the push and reports the incoming call using CallKit. User B answers the call. However, I would like clarification about non-happy scenarios and when it is acceptable to use VoIP pushes to update or stop a CallKit ringing state. Apple documentation warns that VoIP pushes must be used only when they result in a call-related action, so I want to ensure the following cases are compliant. Scenario A — Caller Cancels Before Answer User A calls User B. Server sends a VoIP push to User B. User B’s device starts ringing via CallKit. Before User B answers, User A cancels the call. Question: Is it acceptable to send another VoIP push to User B indicating that the call has been cancelled so the device can: stop the CallKit ringing UI end the call optionally mark it as missed or cancelled Or should this state change be handled using a regular remote push or another signaling mechanism instead of VoIP push? Scenario B — Callee Rejects the Call User B rejects the call from CallKit. The server must inform User A that the call was rejected. Question: Is it acceptable to send a VoIP push to User A to update the CallKit state and terminate the outgoing call UI? Scenario C — Multiple Devices per User User B may be logged in on multiple devices. User A calls User B. VoIP push is sent to all devices of User B. One device answers. Question: Is it acceptable to send a VoIP push to the remaining devices instructing them to: stop ringing end the CallKit incoming call UI Or is there a recommended alternative pattern for this case? Main Question Aside from the initial incoming call VoIP push, in which situations is it considered acceptable to send additional VoIP pushes to terminate or update CallKit state (cancelled, rejected, answered on another device)? The goal is to remain compliant with PushKit policies, particularly the guidance that VoIP pushes should only be used when they result in a call-related user action. Any guidance on the recommended architecture for these cases would be greatly appreciated. Thank you.
Replies
1
Boosts
0
Views
129
Activity
3w
LiveCommunicationKit on watchOS: Displaying visual content during active call?
Our watchOS app is exploring adding audio VOIP calling capability using our in-home platform. We are using LiveCommunicationKit for this and have that all hooked up nicely in a proof of concept implementation. Our use case is primarily based around supporting end-users through various tasks with assistance from a remotely based expert. We would like for our platform to be able to display visual content on the watch's screen during the call – in other words, we would like to be able to treat this as a video call. LiveCommunicationKit fully supports all video-related flags on watchOS and doesn't appear to have any different symbol availability versus its iOS version. This high-quality thread (https://developer.apple.com/forums/thread/798090) from a DTS engineer suggests that our use case should be valid (i.e. whiteboarding apps) and that the system's response to an accepted income video call is to dismiss the LCK's incoming call screen and bring the target app to the foreground, allowing it to render its custom content. Unfortunately, on watchOS the system doesn't seem to treat a video call any differently from an audio call, and won't dismiss the system UI once it's answered. We fully realize that Apple Watch doesn't have a camera for outbound video, doesn't support VideoToolbox or other low-level video convenience libraries for simplified rendering and decoding, etc. That's not what we're worried about (yet). The documentation is at best unclear about whether LCK (or CallKit, for that matter) can hand off calls flagged as video-compatible according to how we think they should, which is passing foreground UI over to the app once the call has been accepted by the user. Can any Apple people shed some light on this? I recognize we are probably trying to do something not many people have before.
Replies
2
Boosts
0
Views
87
Activity
3w