在 IOS 10(Swift 3,Xcode 8)中检测 GSM 呼叫状态和来自后台状态的通知

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

TLDR:从后台检测呼叫结束事件 请参阅以下问题的更新:

是否可以使用 背景状态 中的 Swift 在 IOS 10 中 detect/get 调用状态事件。在早期版本中有一个 CORE Telephony api 但现在似乎已弃用。

我看过 CallKit Api 但它说它用于基于 VOIP 的呼叫。我需要获取正常 CDMA/GSM 呼叫的 状态,而不是基于 VOIP 的呼叫 并且当呼叫结束时只向服务器发出通知。我不需要访问任何可能成为隐私问题的数据点,只需要一个事件来判断通话结束的时间,然后我的应用程序(即后台应用程序)就会启动。而已。关于如何执行此操作的任何指示?

更新: 使用 CallKit Api 我能够获取通话状态,但无法区分 voip 和普通 GSM 通话。我可以用那个工作。通过执行以下操作,我还能够获得本地通知。

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")
        }
    }
}

函数显示为:

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

但是(正如预期的那样),当应用程序在后台长时间(超过 3 分钟) 或屏幕锁定时,这将不起作用。我觉得我快到了,但缺少一些东西。还认为这不是执行此操作的正确方法,或者必须有更好的(swift/IOS 标准)方法来执行此操作。请建议。已经失去了 50 个赏金点数:)

我认为 CallKit 不再让我们区分调用类型。 它确实会触发事件,但我们无法过滤掉蜂窝事件。

本期更详细地讨论了事件触发器: Call states

希望这会在 6 月发生变化,Apple 可能会向 CallKit 添加新功能。

亲切的问候,

穆昆德

答案是否定的,您无法获取有关 call/GSM 数据的信息,Call kit 仅与 VOIP 相关。

"Is it possible to detect/get an event for call state in IOS 10 using Swift from background state"

是的。

您的应用程序的后台状态只是其暂停过程中的一个临时停靠点。发生这种情况时,系统将停止您的代码试图响应的所有进程。

Apple 这样做是有充分理由的。他们不使用用户不使用的应用程序来耗尽设备上的电池。如果他们不这样做,您的 iPhone 电池会很快耗尽。因此,为了强制执行此操作,所有处于后台状态的应用程序最终都将被暂停。也就是说,当然,除非您以几种不同的方式配置您的应用程序。

1) Background Executions

看起来您可能已经在您的应用程序中这样做了。但这将允许您的应用程序执行任何可能尚未完成或需要稍微扩展的长 运行ning 任务。正如您所知道的,这些后台任务的运行时间是有限制的 运行。当您的应用程序暂停时,它不会执行。它将使您的应用程序在后台状态最多保持 3 分钟以完成其工作。完成后,您的应用程序将立即进入挂起状态。

2) Background Modes

确保您的应用程序保持后台状态的最可靠方法是在您的项目配置中启用一项功能,该功能将指示您的应用程序使用 有效 后台模式。我的应用 Sublam 就是这样做的。它是一个音乐播放器应用程序,可以增强 iTunes 中的音乐,使其听起来最好听。如果用户只能在应用程序处于前台时听音乐,那将是非常烦人的。差点被囚禁,永远无法离开,否则音乐就会停止。我启用了后台模式,让我的应用程序在后台运行,远离可怕的挂起状态。这样我的应用程序就可以处理用户输入以更改歌曲、暂停、播放或我的应用程序需要做出反应的任何其他操作。

您的应用程序需要符合有效的后台模式,以确保它保持在后台状态并能够对传入的任何调用做出反应。否则,CXCallObserverDelegate 方法将不会执行完全没有。


"I need to get the state of normal CDMA/GSM calls, not VOIP based calls"

正如 Mukund 和 Raza 在上面所说的那样 - 您不能使用 CallKit 来确定该信息。希望这会成为未来 CallKit 的新功能。但目前不支持此功能。

PS : 我假设 VOIP 呼叫由您处理

对于APNS/PushKit字典的有效负载是从您的托管服务器获取的。

只需添加键值对isVOIPCall:true即可区分

过了很长一段时间,这似乎在 iOS 中不可行 10. 我确实尝试按照建议使用背景模式,但我既不需要播放音乐也不需要一直跟踪位置因此他们不适合我。

我不能使用 Push Kit,因为目的是获取普通 GSM 呼叫的事件,而不是 voip 呼叫。