Search code examples
iosswiftcore-telephony

iOS How to detect call state in background?


I'm trying to change button state depending on call state. I used code from here to detect call state: How to get a call event using CTCallCenter:setCallEventHandler: that occurred while the app was suspended?

And it works fine when app is in foreground. But it doesn't work in background at all. In documentation for CTCallCenter.callEventHandler:

When your application resumes the active state, it receives a single call event for each call that changed state—no matter how many state changes the call experienced while your application was suspended. The single call event sent to your handler, upon your application returning to the active state, describes the call’s state at that time.

But I don't get any call events when app resumes active. All I get is last saved call state when app was in foreground. How can I detect call state in background?

Here is my code:

AppDelegate.swift

  let callСenter = CTCallCenter()

    func block (call:CTCall!)
    {
        callState = String(call.callState)
        print(call.callState)
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
    {
        //check for call state
        callСenter.callEventHandler = block

...

        return true
    }

ViewController.swift

 override func viewDidLoad()
    {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(
            self,
            selector: #selector(cameBackFromSleep),
            name: NSNotification.Name.UIApplicationDidBecomeActive,
            object: nil
        )

        ...
    }

    func cameBackFromSleep()
    {
        self.viewWillAppear(true)
    }

    override func viewWillAppear(_ animated: Bool)
    {
        switch callState
        {
        case "CTCallStateConnected":
            print("callState: ", callState)
            self.textLabel.isHidden = true
            startBtnAnimation()
        case "CTCallStateDisconnected":
            print("callState: ", callState)
            self.textLabel.center.y += self.view.bounds.height
            self.textLabel.isHidden = false
            stopBtnAnimation()
        default: break
        }
    }

Solution

  • Finally, I solved it! I used code from this answer: Find if user is in a call or not?

    I removed everything from AppDelegate, all job is done in ViewController:

    override func viewDidLoad()
        {
            super.viewDidLoad()
    
            NotificationCenter.default.addObserver(
                self,
                selector: #selector(cameBackFromSleep),
                name: NSNotification.Name.UIApplicationDidBecomeActive,
                object: nil
            )
    
    ...
    
        }
    
        private func isOnPhoneCall() -> Bool
        {
            let callCntr = CTCallCenter()
    
            if let calls = callCntr.currentCalls
            {
                for call in calls
                {
                    if call.callState == CTCallStateConnected || call.callState == CTCallStateDialing || call.callState == CTCallStateIncoming
                    {
                        print("In call")
                        return true
                    }
                }
            }
    
            print("No calls")
            return false
        }
    
        func cameBackFromSleep()
        {
    
            self.viewWillAppear(true)
        }
    
        override func viewWillAppear(_ animated: Bool)
        {
            print("is on call", isOnPhoneCall())
            switch isOnPhoneCall()
            {
            case true:
                print("startBtnAnimation")
                startBtnAnimation()
                recordBtnIsPressed = true
            case false:
                print("stopBtnAnimation")
                stopBtnAnimation()
                recordBtnIsPressed = false
            default: break
            }
        }
    

    Now it works fine. Not sure why CTCallCenter works so weird in AppDelegate.