Is there a way for my app to know that a phone number has just been messaged to or a call to 911 just started? Or SOS has just been executed by the user?
CallKit
RSS for tagDisplay 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
94 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hi community,
I'm an iOS developer developing a proof of concept for Automaker apps, and I'm trying to make a phone call with the following code:
let url = URL(string: "tel://1234567890")
But the banner is not shown in the Carplay Automaker App, if I have the same view opened in the iOS application the banner is shown and I can make the phone call...
Thanks,
David Cosialls.
Need help from Apple to provide more details on what can contribute to "CXErrorCodeRequestTransactionErrorInvalidAction".
For the same client build, we are seeing a spike of errors only from older OS (< 16.5) with error code 6 (.invalidAction) when requesting a transaction with CXStartCallAction. This happened after we update to XCode 16.1.
Hello
Iphone - ISO 17.6
I'm looking for an example on how I can access and manage a list of blocked phone contacts from CallKit ? / Swift.
Ive seen a number of posts which suggest this may not be possibe
Any hints / guidance would be appreciated
Thank you
Dear Apple team, I would like to report a problem that started after update my iPhone to iOS 18.0.1. When user receives a call and reject, CXCall is giving wrong values compared the previous version of iOS (minor of 18).
In iOS 17.7, we received this values:
hasConnected = false
hasEnded = true
iOS 18.0.1 we received 2 CXCall events:
first event
hasConnected = true
hasEnded = false
second event
hasConnected = true
hasEnded = true
This behaviour is strange and not intuitive, and if we check the documentation, don`t make sense:
A call is considered connected when both caller and callee can start communicating and A call is considered ended when the user disconnects or all other callers disconnect.
Our code is very simple and use callObserver function to make the flow:
public func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
if call.hasConnected, !call.hasEnded {
//GoToViewControllerX
}
if call.hasEnded {
//DoSomething
}
}
With the behavior of iOS 18 the project will enter in first conditional and then will enter in second conditional.
I need some help or some instruction because the intention ir only enter in first conditional if the call really happens.
I've noticed delays with the Live Caller ID Lookup feature, taking around 3 to 6 seconds to complete, even on repeated lookups. This seems odd since there's no server activity during these repeats, suggesting the information might be coming from a cache. Most of the time, it’s fast, but there are cases when it's unexpectedly slow, and I haven’t quite figured out the pattern yet. Is anyone else seeing this issue?
FB number FB15372765 - with sysdiagnose and video demonstrating the delay.
I am currently working on integrating an app with Siri, adding support for starting VOIP calls and sending messages. Although it is understood it is recommended to use SiriKit for calling and messaging, I would like to allow users to select a profile to use for calling. As far as I am aware the notion of selecting a profile to call from is not something SiriKit supports, therefore, it was decided to go with App Intents to allow for more control over the parameters utilized to start calls.
After integrating VOIP calling with App Intents, I noticed CallKit is not able to start calls when the App Intent is invoked from the background. I get the following error:
Error Domain=com.apple.CallKit.error.requesttransaction Code=6 "(null)”
This seems to correspond to the CXErrorCodeRequestTransactionError invalidAction. This error only happens when the intent is invoked from the background. Changing the App Intent property openAppWhenRun to true solves the issue as it brings the app to foreground before running the intent.
However, I would like to support starting calls from the background to avoid making users unlock their phones prior to starting a call with Siri to make it a truly hands-free experience. I suspect the desired behavior is possible, most likely with SiriKit, as some famous VOIP calling apps (i.e. WhatsApp, Messenger, etc) exhibit the behavior I described. However, is there any way to start calls from the background with App Intents? Or is the desired behavior something exclusive to SiriKit?
I have pasted three code snippets below that can replicate the issue. At the moment I am on Xcode Version 15.3, macOS Sonoma 14.6.1, and testing on iOS 16.6.1
To demonstrate the issue I have created the following CXProviderDelegate:
class CallManager: NSObject, CXProviderDelegate {
func startCall() {
let callKitProvider = CXProvider(configuration: CXProviderConfiguration())
callKitProvider.setDelegate(self, queue: nil)
let callKitController = CXCallController()
let recipient = CXHandle(type: .generic, value: "Demo Outgoing Call")
let uuid = UUID()
let startCallAction = CXStartCallAction(call: uuid, handle: recipient)
let transaction = CXTransaction(action: startCallAction)
callKitController.request(transaction) { error in
if let error {
print(error)
} else {
print("no errors")
}
}
callKitProvider.reportOutgoingCall(with: uuid, connectedAt: nil)
}
func providerDidReset(_ provider: CXProvider) {
// no-op, not required to demonstrate the issue
}
}
Then, I have a UIViewController that is the only screen of this example app:
class ViewController: UIViewController {
@IBOutlet weak var startCallButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
startCallButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}
@objc func buttonTapped() {
let manager = CallManager()
manager.startCall()
}
}
As for app intents, I put together a very simple intent to trigger the start of an outgoing call:
struct StartCall: AppIntent {
static var title: LocalizedStringResource = "Start Call"
static var openAppWhenRun = false
func perform() async throws -> some IntentResult {
let manager = CallManager()
manager.startCall()
return .result()
}
}
When the UIViewController is presented and I tap the button to start a call I see the green call banner appear and "no errors" is printed to the console as intended. However, when I open the Shortcuts app and run the app intent, the green banner does not appear and the message Error Domain=com.apple.CallKit.error.requesttransaction Code=6 "(null)” is printed to the console.
Hi,
Incoming calls were working fine when the app was run from Xcode in both production and debug modes. I added the APS Environment to production, but after releasing it on TestFlight, it's not working, and I am not receiving PushKit notifications.
Dear Apple R&D Team, I want to report a bug of CallKit caused by Voicemail in iOS18.0.
The following are the header files referenced by our code:
#import <CallKit/CXCallObserver.h>
#import <CallKit/CXCall.h>
Our VoIP app uses the callObserver callback function provided by CXCallObserverDelegate to monitor changes in the system phone status (see the attached picture). The problems we encountered are:
Before upgrading to iOS18.0, when we rejected a call, we would receive a callObserver callback, and the status value of hasConnected of CXCall was NO;
After upgrading to iOS18.0, when we also rejected a call, the status value of hasConnected of CXCall was YES.
So we checked the new features of iOS18.0 and found that it was the influence of the new feature Voicemail.
On iOS18.0 devices, if you reject a call, you will enter the Voicemail state by default, which means that I rejected the call, but callObserver told me that the call was connected, which is inconsistent with the user's intuitive experience and will also cause our App to respond incorrectly (cannot resume audio automatically).
In fact, the Voicemail function is enabled by default for devices upgraded to iOS 18.0. After I reject a call, I have to wait for the caller to hang up before I can receive callObserver telling me that the call has been hung up. This experience is very bad, because when the caller does not hang up the call, our App cannot sense that I have hung up the call and thinks that I am still on the call, but in fact I did hang up the call.
Please refer to the code in the attached picture. According to our understanding, the status should flow like this:
When I receive an incoming call, the callObserver callback will trigger, call.hasConnected is NO and call.hasEnded is NO;
When I reject the call and switch to Voicemail, the callObserver callback will trigger, call.hasConnected should be NO and call.hasEnded should be YES;
When I manually restore the call through Voicemail, the callObserver callback will trigger, call.hasConnected should be YES and call.hasEnded should be NO;
When the caller or I finally hang up the call, the callObserver callback will trigger, call.hasConnected is YES, call.hasEnded is YES;
However, the current status is as follows:
When I receive an incoming call, the callObserver callback will trigger, call.hasConnected is NO and call.hasEnded is NO;
When I reject the call and switch to Voicemail, the callObserver callback will trigger, call.hasConnected is YES and call.hasEnded is NO;
When I manually restore the call through Voicemail, the callObserver callback will not trigger;
Only when the caller finally hangs up, the callObserver callback will trigger, call.hasConnected is YES and call.hasEnded is YES;
Our request is very simple. We need to pause audio when a call comes in and resume audio when the call is hung up or rejected. This is our sample code:
- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call API_AVAILABLE(ios(10.0))
{
bool pause_audio = false;
BOOL calling = !call.onHold && !call.hasConnected && !call.hasEnded;
BOOL disconnected = !call.onHold && !call.hasConnected && call.hasEnded;
BOOL connected = !call.onHold && call.hasConnected && !call.hasEnded;
BOOL hang_up = !call.onHold && call.hasConnected && call.hasEnded;
if (calling) {
xc_log(XC_LOG_INFO, "A phone call is %s", call.outgoing ? "outgoing" : "incoming");
pause_audio = true;
} else if (disconnected) {
xc_log(XC_LOG_INFO, "An %s phone call has been disconnected", call.outgoing ? "outgoing" : "incoming");
// action of phone call end, resume audio
} else if (connected) {
xc_log(XC_LOG_INFO, "An %s phone call has just been connected", call.outgoing ? "outgoing" : "incoming");
pause_audio = true;
} else if (hang_up) {
xc_log(XC_LOG_INFO, "An %s phone call has been hang up", call.outgoing ? "outgoing" : "incoming");
// action of phone call end, resume audio
} else {
xc_log(XC_LOG_INFO, "Unknown telephony state occured");
}
if (pause_audio) {
dispatch_async(dispatch_get_main_queue(), ^{
// action of phone call begin, pause audio
});
}
}
I would appreciate any help !!!
Hello,
I am a developer currently working on a personal contact management app.
What is the app?
My app stores additional information beyond basic contact details. Therefore, instead of using the Contacts framework, I manage contact objects using Core Data.
What am I trying to achieve?
I want to display additional information on the caller ID screen when a call is received from a number stored in my app.
What have I tried?
I’ve attempted the following methods without success:
1. Call Directory Extension:
I thought using this method would allow me to display additional information from Core Data on the call screen. However, I learned that when a call is received, the iOS system first searches for the phone number in the Contacts app and only looks to the Extension app if no match is found. Therefore, displaying contact information from my app seems unfeasible.
2. Custom Call UI:
Using CallKit seemed like a viable option to display the necessary information during a call, but it appears to only be possible with VoIP apps. My app does not support VoIP calls, so this method was also not implementable.
I am wondering if there are any technologies available that could help me achieve my goal, or if there’s something I might be missing. Any advice would be greatly appreciated.
Thank you!
If a similar question has been asked, I apologize for the repetition.
Hello, experts!
During a VOIP call, the following happens:
device 1 makes a call to device 2
device 2 deliberately does not receive the call
some time passes, timeout is triggered and the call is terminated with CXCallEndedReason = remoteEnded, as evidenced by a line in the logs of the incoming call:
`[info] reportCallWasEnded callId=[***-***-***], reason=[CXCallEndedReason(rawValue: 2)].`
What is the reason why CXEndCallAction may be called from CXProviderDelegate even though the call was not manually terminated by clicking on the “End Call” button
Since I updated to iOS 18, CallKit-linked caller not display on screen of CarPlay.
CarPlay display only "{App Name} Caller ID".
When iOS version was 17.x, CarPlay displayed caller name of CallKit-linked contact.
I think CarPlay should perform the same function as iOS 17.
Please review it.
Dual SIM management on the iPhone is not very efficient. I am using an iPhone 13, and I have to frequently change the SIM line because sometimes I recharge one SIM, and other times I recharge the second SIM. I have selected the default SIM line in the settings, which means calls should always go through the default set SIM line. However, this is not happening. I have to manually go to the contact of the person and change the SIM line before making a call. Could you provide a feature where, when calling any person, the call always goes through the selected default SIM line?
Hello, I am wondering about developing my application.
Can the new commands available with iOS 18 give me access to the call log (recent calls)? With a request prior to installing the application for example.
I saw that Truecaller has just launched an update on iOS to offer the same features as Android, i.e. capture the call log.
Apple allows applications like Truecaller to integrate their spam databases into the iOS caller ID system. I wonder by which command!
Otherwise, I can perhaps use the "SMS and Call Spam Reporting" commands and divert them to retrieve the call log.
To tell you the truth, I'm trying to find, for my application, a way to retrieve recent call data to create a call dashboard of certain calls, by retrieving the name or phone number, call date, call time and call duration.
Does anyone have an idea?
We’ve encountered significant differences in our VoIP app’s workflow between iOS 17 and iOS 18, particularly on devices with Dynamic Island. Our app functioned as expected in iOS 17 and even iOS 18 on devices without Dynamic Island, but with the public release of iOS 18 on Dynamic Island-supported iPhones, we’re receiving a lot of feedback from users reporting confusing behavior during both incoming and outgoing calls.
Here’s a breakdown of the issue:
In iOS 17 and iOS 18 (on non-Dynamic Island models), when our app initiates a second call, the app remains in the foreground, allowing the user to see both calls within our UI. Users can manage their calls, swap between them, and even merge them, all without leaving the app. If the user switches to the CallKit controller via the app switcher, it reflects the state of the calls in our app, which has worked well for our users.
However, on iOS 18 devices with Dynamic Island, adding a second call now backgrounds our app and brings the CallKit controller UI to the foreground. This causes confusion, as users lose context of managing multiple calls within our app. Though users can switch back to our app manually, this extra step disrupts their workflow, especially when handling multiple active calls. This change doesn't occur on iOS 18 devices without Dynamic Island.
Additionally, during an active call, if an incoming call arrives, the Dynamic Island notification takes over, and the app UI is again backgrounded in favor of the CallKit controller screen. Even when declining the incoming call from the notification, the user remains in the CallKit controller UI, requiring another step to return to our app using the app switcher or the "app" button in CallKit.
This inconsistent behavior makes call management unnecessarily complex for our users, who need a streamlined experience, especially since our app is used in healthcare communications that is often critical in nature.
Is there any documentation on changes to CallKit behavior specific to Dynamic Island devices in iOS 18? We’d appreciate any guidance on designing a VoIP experience that doesn’t involve these disruptive view switches, particularly for Dynamic Island-supported iPhones.
Thank you for your help!
Since upgrading to iOS 18, an issue has been observed where blocked incoming calls display "(null)" instead of the actual application name. At the time the calls defined by the same application contain the name of the application correctly.
I am a developer based in Ireland. I updated an iPhone 12 to iOS18.1 Beta 4 in order to investigate the Call Record Feature. We have a VoIP App and I wanted to see if there is any interaction with this new Call Record feature. However there is no option appearing for me under Settings ->Apps->Phone for Call RECORD
My suspicion is that this is because I am in Europe and Apple Intelligence is not available here.
We have our Apps available in the USA so is there anyway that I can enable Call record for some testing.
Alternatively does anybody know if Call record should work with Callkit VoIP Apps?
Hello Apple Developer Community,
I'm developing a call-blocking app for iOS and have encountered an issue with iOS 18. Despite calls being successfully blocked by our app's Call Directory extension, they are still appearing as unanswered calls in the native Phone app.
Details:
iOS version: 18
App uses CallKit and Call Directory extension
Calls are blocked successfully (not ringing on device)
Blocked calls show up as "Unanswered" in Phone app's recent calls list
Expected behavior: Blocked calls should not appear in the Phone app's recent calls list.
Actual behavior: Blocked calls appear as "Unanswered" in the recent calls list.
The app declares support for Voice-over IP (VoIP) in the UIBackgroundModes key in your Info.plist, but we are still unable to locate any VoIP services. Apps that declare support for VoIP in the UIBackgroundModes key in your Info.plist file must have features that require VoIP.
My app rejected for VOIP and the app is totally supported video call or call when app is terminated or in background how can. i solve that rejection issue
iOS 18 (22A3354) will not offer a option in settings (> Apps > Phone) after calling openSettings to enable live caller id lookup extension.
iPhone and MacBook are in the same network.
The PIRService runs on MacBook and is reachable via iPhone Safari (via http://MacBookPro:8080/).
Hummingbird print log: hb_method=GET hb_uri=/ [Hummingbird] Request.
After deploying the application via Xcode to the iPhone no requests are printed in the terminal.
The extension was added like documented and bundle id is also checked multiple times.
issuerRequestUri in service-config.json is http://MacBookPro:8080/issue.
As far as I can tell, everything has been set up in accordance with the Testing Live Caller ID instructions.
Is there something missing?