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

113 Posts

Post

Replies

Boosts

Views

Activity

Delivery of expired voip notifications
Hello, We are facing issue that sometimes a voip notification gets delivered after it is expired. The issue can be simply demonstrated we set the device to flight mode, and after 20s we disable flight mode. We still receive the voip notification. We are setting the expiration header as following apns-expiry=0, so from my understanding it should not be delivered if the device was not able to receive the notification in the fist attempt. I have read following thread https://developer.apple.com/forums/thread/778512, from which I understand this is a long standing issue. Hence my question is, is there any way how we can notify the call kit that the call is actually no longer valid, and do not display the call to the user at all? Currently we are forced to always display CallKit call when the notification comes, and some of our users are confused that they see a missed call which they did not have any chance to pick up. Please let me know if you need any more information. Best Regards, Adam Chlupacek
2
0
254
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
377
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
235
Feb ’26
CallKit requestTransaction error code 2
Hello, In production, a large number of users experience outgoing call reporting fails with the following error: com.apple.CallKit.error.requesttransaction Code=2 The iOS version doesn't matter, errors are present in v15-26 Details My CXProvider held as a global singleton, so it’s unlikely to be deinited. There is no explicit call to CXProvider.invalidate() in the app. If I manually invalidate the CXProvider, I observe the expected failure when trying to create an outgoing call (com.apple.CallKit.error.requesttransaction error 2). However, If I recreate the CXProvider after the error, outgoing calls are reported correctly. Many users trigger the providerDidReset delegate method (CXProviderDelegate) before this error. According to the documentation, providerDidReset can be called by the system, and we are supposed to end all active calls, but the documentation doesn't suggest recreating the CXProvider. Question Should I recreate CXProvider after providerDidReset and forget about that, or could this error be caused by something else?
5
0
542
Feb ’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
194
Feb ’26
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
610
Feb ’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
475
Jan ’26
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
948
Jan ’26
After unholding CallKit, the audio does not restore.
In my application, I use CallKit and have supportsHolding = true set. During my phone call, another call comes in (e.g., GSM). I accept the incoming call and put the current call on hold. If I end the active call myself, everything is fine, and CallKit calls the method provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession). However, if the other party ends the call, the second call remains on hold. In the application, the user clicks on unhold, and I notify CallKit that the hold has ended. But in this case, the didActivate method is not called at all. If I try to activate the audio myself after unhold, I receive the error: Domain=NSOSStatusErrorDomain Code=561017449 "Session activation failed" UserInfo={NSLocalizedDescription=Session activation failed} AVAudioSessionErrorInsufficientPriority == NSOSStatusErrorDomain Code: 561017449 What needs to be done for CallKit to activate my audio?
4
2
1.7k
Jan ’26
Can reproduce in SpeakerBox that CallKit doesn't activate audiosession when call finished by remote caller
I can reproduce the bug that CallKit doesn't active audiosession after the outgoing call put on hold because of an incoming call. VoIP calling with CallKit Steps to reproduce: Download SpeakerBox example app from the link above and start it with XCode Start a new outgoing call Call your phone from other phone Hold and Accept the call After a few secs finish the call from the other phone The outgoing call will be still on hold Click on the call and click Toggle Hold The call won't be active again because the audiosession is activated. Logs: Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Requested transaction successfully Starting audio Type: stdio AURemoteIO.cpp:1162 failed: 561017449 (enable 3, outf< 1 ch, 44100 Hz, Float32> inf< 1 ch, 44100 Hz, Float32>) Type: Error | Timestamp: 2024-08-15 12:20:29.949437+02:00 | Process: Speakerbox | Library: libEmbeddedSystemAUs.dylib | Subsystem: com.apple.coreaudio | Category: aurioc | TID: 0x19540d AVAEInternal.h:109 [AVAudioEngineGraph.mm:1344:Initialize: (err = PerformCommand(*outputNode, kAUInitialize, NULL, 0)): error 561017449 Type: Error | Timestamp: 2024-08-15 12:20:29.949619+02:00 | Process: Speakerbox | Library: AVFAudio | Subsystem: com.apple.avfaudio | Category: avae | TID: 0x19540d Couldn't start Apple Voice Processing IO: Error Domain=com.apple.coreaudio.avfaudio Code=561017449 "(null)" UserInfo={failed call=err = PerformCommand(*outputNode, kAUInitialize, NULL, 0)} Type: Notice | Timestamp: 2024-08-15 12:20:29.949730+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d Route change: Type: Notice | Timestamp: 2024-08-15 12:20:30.167498+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d ReasonUnknown Type: Notice | Timestamp: 2024-08-15 12:20:30.167549+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d Previous route: Type: Notice | Timestamp: 2024-08-15 12:20:30.167568+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d <AVAudioSessionRouteDescription: 0x302c00bc0, inputs = ( "<AVAudioSessionPortDescription: 0x302c01330, type = MicrophoneBuiltIn; name = iPhone Mikrofon; UID = Built-In Microphone; selectedDataSource = (null)>" ); outputs = ( "<AVAudioSessionPortDescription: 0x302c004d0, type = Receiver; name = Vev\U0151; UID = Built-In Receiver; selectedDataSource = (null)>" )> Type: Notice | Timestamp: 2024-08-15 12:20:30.167626+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d
11
1
958
Jan ’26
CallKit does not activate audio session with higher probability after upgrading to iOS 18.4.1
Hi, We've noticed that this issue occurs more frequently after upgrading to iOS 18.4.1 and can result in one-way audio. Our app uses CallKit with WebRTC to establish VoIP connections. However, on iOS 18.4.1, CallKit no longer triggers: func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) We're currently comparing the occurrence rate across different iOS versions to better understand the impact. Could you please help analyze the root cause of this issue?
37
1
3.1k
Dec ’25
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
140
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
329
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
265
Dec ’25
Callkit call blocking problem
We tested call blocking on iOS 26 and noticed something strange: the call will not be blocked if an outgoing call was made to its number before. Nevertheless, it will be blocked if we delete the outgoing call record from the Phone.app Recents. This behavior looks like a bug and is unexpected when using our application. Was this a planned callkit change in iOS 26? Is it possible to get the correct call blocking behavior back? We set blocking rules with addBlockingEntry(withNextSequentialPhoneNumber:) and this problem is not present in iOS 18 and earlier. Thank you in advance
12
4
1k
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
279
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
154
Dec ’25
Error Blocking Phone Numbers
In my case, when I try to block calls on iOS 26, the blocking doesn't occur; the scenarios seem intermittent. If I create two CallDirectory extensions, the first blocks the numbers, but the second doesn't. Interestingly, the extension marks the number as suspicious. There's also a case where, on iOS 26 on an iPhone 16 Pro, the functionality doesn't work at all. I'd like to know if there have been any changes to the use of CallKit in iOS 26, because users of my app on iOS 18 and below report successful blocking.
1
1
313
Dec ’25
CallKit: Rejecting a Cellular Call Also Rejects Application Video Call
Rejecting a Cellular Call Also Rejects Application Video Call Steps: 1.When a user receives a cellular call and it is in the "ringing" state and application receives a video call which is reported to CallKit 2.User rejects the Cellular call from Callkit UI, Video call is also getting rejected. 3.Application is receiving performEndCallAction when user is rejecting the Cellular call As a part of CXcallobserver Application is receiving call connected then disconnected for the cellular call Irrespective of OS, the issue only reproduces on cellular calls if Live Voicemail is enabled. Issue is not reproduced when Live Voicemail is disabled for cellular calls, and it is not reproducing on FaceTime calls, regardless of the Live Voicemail setting. This results in a poor user experience because: The recipient unintentionally misses the CallKit-reported call. The initiator receives confusing and inaccurate status information, believing the recipient is busy rather than having chosen to decline the pending video call.
1
0
321
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
161
Dec ’25
Delivery of expired voip notifications
Hello, We are facing issue that sometimes a voip notification gets delivered after it is expired. The issue can be simply demonstrated we set the device to flight mode, and after 20s we disable flight mode. We still receive the voip notification. We are setting the expiration header as following apns-expiry=0, so from my understanding it should not be delivered if the device was not able to receive the notification in the fist attempt. I have read following thread https://developer.apple.com/forums/thread/778512, from which I understand this is a long standing issue. Hence my question is, is there any way how we can notify the call kit that the call is actually no longer valid, and do not display the call to the user at all? Currently we are forced to always display CallKit call when the notification comes, and some of our users are confused that they see a missed call which they did not have any chance to pick up. Please let me know if you need any more information. Best Regards, Adam Chlupacek
Replies
2
Boosts
0
Views
254
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
377
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
235
Activity
Feb ’26
CallKit requestTransaction error code 2
Hello, In production, a large number of users experience outgoing call reporting fails with the following error: com.apple.CallKit.error.requesttransaction Code=2 The iOS version doesn't matter, errors are present in v15-26 Details My CXProvider held as a global singleton, so it’s unlikely to be deinited. There is no explicit call to CXProvider.invalidate() in the app. If I manually invalidate the CXProvider, I observe the expected failure when trying to create an outgoing call (com.apple.CallKit.error.requesttransaction error 2). However, If I recreate the CXProvider after the error, outgoing calls are reported correctly. Many users trigger the providerDidReset delegate method (CXProviderDelegate) before this error. According to the documentation, providerDidReset can be called by the system, and we are supposed to end all active calls, but the documentation doesn't suggest recreating the CXProvider. Question Should I recreate CXProvider after providerDidReset and forget about that, or could this error be caused by something else?
Replies
5
Boosts
0
Views
542
Activity
Feb ’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
194
Activity
Feb ’26
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
610
Activity
Feb ’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
475
Activity
Jan ’26
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
948
Activity
Jan ’26
After unholding CallKit, the audio does not restore.
In my application, I use CallKit and have supportsHolding = true set. During my phone call, another call comes in (e.g., GSM). I accept the incoming call and put the current call on hold. If I end the active call myself, everything is fine, and CallKit calls the method provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession). However, if the other party ends the call, the second call remains on hold. In the application, the user clicks on unhold, and I notify CallKit that the hold has ended. But in this case, the didActivate method is not called at all. If I try to activate the audio myself after unhold, I receive the error: Domain=NSOSStatusErrorDomain Code=561017449 "Session activation failed" UserInfo={NSLocalizedDescription=Session activation failed} AVAudioSessionErrorInsufficientPriority == NSOSStatusErrorDomain Code: 561017449 What needs to be done for CallKit to activate my audio?
Replies
4
Boosts
2
Views
1.7k
Activity
Jan ’26
Can reproduce in SpeakerBox that CallKit doesn't activate audiosession when call finished by remote caller
I can reproduce the bug that CallKit doesn't active audiosession after the outgoing call put on hold because of an incoming call. VoIP calling with CallKit Steps to reproduce: Download SpeakerBox example app from the link above and start it with XCode Start a new outgoing call Call your phone from other phone Hold and Accept the call After a few secs finish the call from the other phone The outgoing call will be still on hold Click on the call and click Toggle Hold The call won't be active again because the audiosession is activated. Logs: Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Received provider(_:didDeactivate:) Requested transaction successfully Starting audio Type: stdio AURemoteIO.cpp:1162 failed: 561017449 (enable 3, outf< 1 ch, 44100 Hz, Float32> inf< 1 ch, 44100 Hz, Float32>) Type: Error | Timestamp: 2024-08-15 12:20:29.949437+02:00 | Process: Speakerbox | Library: libEmbeddedSystemAUs.dylib | Subsystem: com.apple.coreaudio | Category: aurioc | TID: 0x19540d AVAEInternal.h:109 [AVAudioEngineGraph.mm:1344:Initialize: (err = PerformCommand(*outputNode, kAUInitialize, NULL, 0)): error 561017449 Type: Error | Timestamp: 2024-08-15 12:20:29.949619+02:00 | Process: Speakerbox | Library: AVFAudio | Subsystem: com.apple.avfaudio | Category: avae | TID: 0x19540d Couldn't start Apple Voice Processing IO: Error Domain=com.apple.coreaudio.avfaudio Code=561017449 "(null)" UserInfo={failed call=err = PerformCommand(*outputNode, kAUInitialize, NULL, 0)} Type: Notice | Timestamp: 2024-08-15 12:20:29.949730+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d Route change: Type: Notice | Timestamp: 2024-08-15 12:20:30.167498+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d ReasonUnknown Type: Notice | Timestamp: 2024-08-15 12:20:30.167549+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d Previous route: Type: Notice | Timestamp: 2024-08-15 12:20:30.167568+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d <AVAudioSessionRouteDescription: 0x302c00bc0, inputs = ( "<AVAudioSessionPortDescription: 0x302c01330, type = MicrophoneBuiltIn; name = iPhone Mikrofon; UID = Built-In Microphone; selectedDataSource = (null)>" ); outputs = ( "<AVAudioSessionPortDescription: 0x302c004d0, type = Receiver; name = Vev\U0151; UID = Built-In Receiver; selectedDataSource = (null)>" )> Type: Notice | Timestamp: 2024-08-15 12:20:30.167626+02:00 | Process: Speakerbox | Library: Speakerbox | TID: 0x19540d
Replies
11
Boosts
1
Views
958
Activity
Jan ’26
CallKit does not activate audio session with higher probability after upgrading to iOS 18.4.1
Hi, We've noticed that this issue occurs more frequently after upgrading to iOS 18.4.1 and can result in one-way audio. Our app uses CallKit with WebRTC to establish VoIP connections. However, on iOS 18.4.1, CallKit no longer triggers: func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) We're currently comparing the occurrence rate across different iOS versions to better understand the impact. Could you please help analyze the root cause of this issue?
Replies
37
Boosts
1
Views
3.1k
Activity
Dec ’25
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
140
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
329
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
265
Activity
Dec ’25
Callkit call blocking problem
We tested call blocking on iOS 26 and noticed something strange: the call will not be blocked if an outgoing call was made to its number before. Nevertheless, it will be blocked if we delete the outgoing call record from the Phone.app Recents. This behavior looks like a bug and is unexpected when using our application. Was this a planned callkit change in iOS 26? Is it possible to get the correct call blocking behavior back? We set blocking rules with addBlockingEntry(withNextSequentialPhoneNumber:) and this problem is not present in iOS 18 and earlier. Thank you in advance
Replies
12
Boosts
4
Views
1k
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
279
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
154
Activity
Dec ’25
Error Blocking Phone Numbers
In my case, when I try to block calls on iOS 26, the blocking doesn't occur; the scenarios seem intermittent. If I create two CallDirectory extensions, the first blocks the numbers, but the second doesn't. Interestingly, the extension marks the number as suspicious. There's also a case where, on iOS 26 on an iPhone 16 Pro, the functionality doesn't work at all. I'd like to know if there have been any changes to the use of CallKit in iOS 26, because users of my app on iOS 18 and below report successful blocking.
Replies
1
Boosts
1
Views
313
Activity
Dec ’25
CallKit: Rejecting a Cellular Call Also Rejects Application Video Call
Rejecting a Cellular Call Also Rejects Application Video Call Steps: 1.When a user receives a cellular call and it is in the "ringing" state and application receives a video call which is reported to CallKit 2.User rejects the Cellular call from Callkit UI, Video call is also getting rejected. 3.Application is receiving performEndCallAction when user is rejecting the Cellular call As a part of CXcallobserver Application is receiving call connected then disconnected for the cellular call Irrespective of OS, the issue only reproduces on cellular calls if Live Voicemail is enabled. Issue is not reproduced when Live Voicemail is disabled for cellular calls, and it is not reproducing on FaceTime calls, regardless of the Live Voicemail setting. This results in a poor user experience because: The recipient unintentionally misses the CallKit-reported call. The initiator receives confusing and inaccurate status information, believing the recipient is busy rather than having chosen to decline the pending video call.
Replies
1
Boosts
0
Views
321
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
161
Activity
Dec ’25