在iOS 10(Swift 3,Xcode 8)中检测GSM通话状态和后台状态通知

13

简述:如何在后台检测通话结束事件 请看下面问题的更新:

是否可以使用Swift在IOS 10中从后台状态检测/获取呼叫状态事件。在早期版本中有一个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")
        }
    }
}

并且函数showN如下:

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点赏金 :)
5个回答

5

“如何使用Swift在IOS 10的后台状态检测或获取呼叫状态事件?”

是可以的。

你的应用程序的后台状态只是它成为暂停状态的一个临时中转站。当发生这种情况时,系统将停止您的代码试图对其做出反应的所有进程。

苹果公司有很好的原因做出这样的决定。他们不允许用户没有使用的应用程序消耗设备上的电池电量。如果他们不这样做,你的iPhone电池会很快耗尽。因此,所有保持在后台状态的应用程序最终都会被暂停。当然,除非您以几种不同的方式配置您的应用程序。

1) 后台执行

看起来你可能已经在你的应用程序中执行这个了。但是这会使你的应用程序执行任何长时间运行的任务,这些任务可能尚未完成或需要延长一段时间。正如您已经了解到的那样,这些后台任务的运行时间是有限制的。它不会在您的应用程序处于暂停状态时执行。它将保持您的应用程序在后台状态最多3分钟以完成其工作。一旦完成,您的应用程序将立即进入暂停状态。

2) 后台模式

enter image description here

确保您的应用程序保持在后台状态的最可靠方法是在您的项目配置中启用一个功能,表明您的应用程序使用了有效的后台模式。我的应用程序Sublam就是这样做的。它是一款音乐播放器应用程序,可以增强您iTunes中的音乐,使其听起来更好。如果用户只能在前台听音乐,那会非常令人讨厌。我启用了一个后台模式,以保持我的应用程序处于后台,并远离可怕的暂停状态。这样,我的应用程序可以处理用户输入以更改歌曲、暂停、播放或任何其他我需要对其做出反应的操作。

您的应用程序将需要符合有效的后台模式,以确保它保持在后台状态,并能够对任何呼叫作出反应。否则,CXCallObserverDelegate方法根本不会执行。


"我需要获取普通CDMA/GSM呼叫的状态,而不是基于VOIP的呼叫"

正如Mukund和Raza上面所说的那样 - 你不能使用CallKit来确定这些信息。希望在未来,这将成为CallKit的一个新功能。但目前,这个功能不受支持。


如果我在应用程序中启用音乐功能的后台模式,但与音乐/音频/airplay无关,那么苹果会拒绝我的应用程序吗? - Why
是的。这就是为什么我说要符合有效的背景模式。如果您的应用程序不需要使用它,那么您可能需要考虑以其他方式实现您想要做的事情。 - Brandon A

2

长时间以来,似乎在iOS 10中这可能不可行。我尝试使用建议的后台模式,但我既不需要播放音乐也不需要始终跟踪位置,因此它们对我没有用。

我无法使用Push Kit,因为意图是获取普通GSM电话的事件,而不是VoIP电话。


0

答案是绝对不行,你无法获取通话/GSM数据的信息,Call kit仅与VOIP相关。


是的,我理解。然而,如果您看到问题的最后一部分,我想知道如何在后台保持我的应用程序活动,以便即使是 VoIP 通话,我也想向用户显示通知。 - ankit
请查看以下网址: - Raza.najam
您可以在当前时间之外的某个时间让代理呼叫,除此之外,在通话结束时您不能控制代理。 - Raza.najam

0

PS:假设您负责处理VOIP呼叫

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

只需添加一个键值对isVOIPCall:true来区分。


0

我认为CallKit不再让我们区分通话类型了。 它确实会触发事件,但我们将无法过滤掉蜂窝网络的通话。

这个问题更详细地讨论了事件触发: 通话状态

希望在六月份有所改变,苹果可能会为CallKit添加新功能。

此致敬礼,

Mukund


谢谢回复。那么如果设备没有连接到互联网,是否会生成任何事件? - Why
是的,我认为在没有网络的情况下应该触发事件。这里有另一个相关的讨论 https://forums.developer.apple.com/thread/69150。希望能帮到你。 - Mukund Agarwal
嗨。问题已更新,请查看。 - Why

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接