TLDR: Detect call end event from background Please see update to the question below:
Is it possible to detect/get an event for call state in IOS 10 using Swift from background state. In the earlier versions there was a CORE Telephony api but this seems to be deprecated now.
I have seen the CallKit Api but it says that it is for VOIP based calls. I need to get the state of normal CDMA/GSM calls, not VOIP based calls and when the call ends just fire a notification to server. I do not need to access any data points which can be a privacy issue, just need an event for when the call ends and then my app which would be a background app would fire up. Thats it. Any pointers on how to do this ?
UPDATE: Using CallKit Api i am able to get call states though not able to distinguish between voip and normal GSM calls. I can work with that. I have also been able to get a local notification by doing the below.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
application.beginBackgroundTask(withName: "showN", expirationHandler:nil)
return true
}
extension AppDelegate: CXCallObserverDelegate {
func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
if call.hasEnded == true {
print("Disconnected")
let trigger = UNTimeIntervalNotificationTrigger(timeInterval:60,repeats:false)
let identifier = "MyCallLocalNotification"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if let error = error{
print(error)
}
})
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(AppDelegate.showN), userInfo: nil, repeats: false)
print("Done")
}
if call.isOutgoing == true && call.hasConnected == false {
print("Dialing")
}
if call.isOutgoing == false && call.hasConnected == false && call.hasEnded == false {
print("Incoming")
}
if call.hasConnected == true && call.hasEnded == false {
print("Connected")
}
}
}
and the function showN as:
func showN(){
let identifier = "MyCallLocalNotification"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval:1,repeats:false)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if let error = error{
print(error)
}
})
However (as expected), this does not work when the app has been in background for a long time (more than 3 minutes) or when the screen is locked. I feel i am almost there but missing something. Also think this is not a proper way to do this or there must be a better (swift/IOS standard) way to do this. Please Suggest. Have already lost 50 bounty points :)
Yes.
The background state of your application is only a temporary pit-stop on it's way to becoming suspended. When this occurs the system will stop all processes that your code is trying to react to.
Apple does this for a very good reason. They do not applications the user is not using to eat up battery on the device. If they didn't do this your iPhone battery would become depleted very quickly. So to enforce this, all applications that remain in the background state will eventually be suspended. That is, of course, unless you configure your app in a couple of different ways.
1) Background Executions
This it looks like you may already be doing in your application. But this would allow your application to execute any long running tasks that may not have completed or that need to be extended for a little bit. As you have figured out there is a limit to how long these background tasks are allowed to run. It will not execute while your application is suspended. It will keep your application in the background state for up to 3 minutes to complete it's work. Once this has finished your application will immediately enter suspended state.
2) Background Modes
The most reliable way to ensue your application will remain in the background state is to enable a capability in your projects configuration that will indicate your application utilizes a valid background mode. My app Sublam does this. It is a music player application that enhances the music in your iTunes to sound it's best. It would be very annoying to the user if they could only listen to music while the application was in the foreground. Almost kept prisoner, never able to leave or the music would stop. I enabled a background mode to keep my application in the background and away from the dreaded suspended state. This way my application can handle user input to change the song, pause, play or any other action my application would need react to.
Your application will need to conform to a valid background mode to ensure that it remains in the background state and to be able to react to any calls coming in. Otherwise, the CXCallObserverDelegate
methods won't execute at all.
As Mukund and Raza said above - you can not use CallKit to determine that information. Hopefully this will become a new feature of CallKit in the future. But as of now this functionality is not supported.
After a long while it looks like this may not be feasible in iOS 10. I did try using the background modes as suggested but neither i need to play music nor keep tracking the location at all times hence they do not work out for me.
I cannot use Push Kit
because the intent is to get events for normal GSM calls and not voip calls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With