Search code examples
iosswiftios10core-telephonycallkit

Detecting GSM Call States in IOS 10 (Swift 3, Xcode 8) and Notification from Background state


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 :)


Solution

  • 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.