【Swift4】【CallKit】CXCall、電話の発着信等を取得する。

電話の着信時、受話時、終話時をアプリで受け取りたかったので調べてみた。
参考サイト

Xcode|iOS10から新しく加わったCallkitを使って通話の状態を取得してみた

上記サイトが役に立ちました。
ただ、Objective-cだったのでSwiftに変更。

CallKitのCXCallObserverのデリゲートでCXCallの値で送られてくるようだ。

CXCall – CallKit | Apple Developer Documentation
デベロッパサイトを見てgoogle翻訳

var uuid:UUID
コールの一意の識別子。
(よくわからん、とりあえず無視の方向で。w)

var isOutgoing:Bool
呼び出しが発信かどうかを示すブール値。
(コールが発信中か受信中か?)

var hasConnected:Bool
呼び出しが接続されているかどうかを示すブール値。
(通話中かどうか?)

var hasEnded:Bool
呼び出しが終了したかどうかを示すブール値。
(通話が終了したかどうか。)

var isOnHold:Bool
通話が保留状態かどうかを示すブール値。
(保留中?)

状態の変化があったときこれらの組み合わせで通知が来るようだ。
ちょっとややこしい。

とりあえずアプリで受けたいのは「着信」「受話」「終話」
なので下記のような感じで試してみた。

    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        callStateValue(call: call)
    }
    
    func callStateValue(call: CXCall)  {
        print("通知があったよ!")
        print("isOutgoing   ", call.isOutgoing);
        print("hasConnected ", call.hasConnected);
        print("hasEnded     ", call.hasEnded);
        print("isOnHold     ", call.isOnHold);
    }

これで、家電からiPhoneに電話。「着信」「受話」「保留」「保留解除」「終話」と、「着信」から受けずに電話を切って「終話」。とやってみた。

まず着信
  通知があったよ!
  isOutgoing false
  hasConnected false
  hasEnded false
  isOnHold false

すべてfalseの通知が来ます。

続いてそこから電話を受けます。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded false
  isOnHold false

保留にします。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded false
  isOnHold true

保留を終わります。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded false
  isOnHold false

電話を切ります。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded true
  isOnHold false

もう一度着信は同じなので割愛して、電話を受けずに切った場合。
  通知があったよ!
  isOutgoing false
  hasConnected false
  hasEnded true
  isOnHold false

こうして見ると、hasConnectedだけでは「電話に出たとき」か「通話の終了」の通知かはわからず、hasEndedを含める必要があるのがわかります。
あ、しかも、これじゃ、着信から電話に出たのか、保留から電話にもどったかわからないじゃん。/(^o^)\
そこを区別するにはこちら側でなにか記録して区別するしか無いですね。

ところで、iPhoneの保留ってどうするか知ってますか?
試そうと思って家電からiPhoneに受話してみたが、保留の機能が見つからない!/(^o^)\
仕方ないので一旦切って調べてみると、「消音」の長押しだそうだ。
試そうと思って家電からiPhoneに受話してみたが、長押ししてみても保留にならない!/(^o^)\
仕方ないので一旦切って調べてみると、「消音」の3秒位長押しだそうだ。
そしてもういっかい試してみたらちゃんとできました。/(^o^)\
古い情報だと保留中は電子音とか書いてありますが、先程試した時は日本語で「保留中ですお待ち下さい」から音楽になっていました。
あと、通話中のスクリーンショットを撮ろうと思ったのですが、
通話する、「音量UP+サイドキー」を押すで、電話が切れる!/(^o^)\
タイミング悪かったかなと再度通話する、「音量UP+サイドキー」で、電話が切れる!/(^o^)\
どうも通話中はスクリーンショットが撮れないようです。
ちなみに画面収録も着話したら録画が切れました。通話中は記録できないようです。
なんかすっごい電話代無駄にした気がする。/(^o^)\

閑話休題/(^o^)\それはさておき、

形にしてみよう。
受話状態になったらこれを参考に
【Swift4】NotificationCenterの備忘録。 | iPhoneアプリ備忘録
通知が来るようにしてみた。

メイン画面にはLabelを。

import UIKit
import CallKit

class ViewController: UIViewController {
    
    var callObserver : CallKitController!
    @IBOutlet weak var stateLabel: UILabel!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        callObserver = CallKitController()
        
        /// NotificationCenterに登録する
        NotificationCenter.default.addObserver(self,  //オブザーバとして登録
            selector: #selector(catchNotification(notification:)), //通知を受け取った時に投げるメソッド
            name: Notification.Name("myNotificationName"), //通知の名前
            object: nil)
    }
    
    @objc func catchNotification(notification: Notification) -> Void {
        print("Catch notification")
        // 通知を受け取ったことにより行いたい処理を書く
        stateLabel.text = "通話を受けたよ!"
    }
}

電話を通知する方のクラス。

import UIKit
import CallKit

class CallKitController: NSObject  ,CXCallObserverDelegate{
    
    var callObserver = CXCallObserver()
    
    override init() {
        super.init()
        callObserver.setDelegate(self, queue: DispatchQueue.main)
        print("コールキットオブザーバーinit")
    }
    
    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        callStateValue(call: call)
    }
    
    func callStateValue(call: CXCall)  {
        print("通知があったよ!")
        print("isOutgoing   ", call.isOutgoing);
        print("hasConnected ", call.hasConnected);
        print("hasEnded     ", call.hasEnded);
        print("isOnHold     ", call.isOnHold);
        
        // 発信
        if (call.isOutgoing == true && call.hasConnected == false) {
            print("発信 CXCallState : Dialing");
        }

        // 着信
        if (call.hasConnected == false && call.hasEnded == false) {
            print("着信 CXCallState : Incoming");
        }

        // 受話
        if (call.hasConnected == true && call.hasEnded == false) {
            print("受話 CXCallState : Connected");
            // Notification通知を送る(通知を送りたい箇所に書く。例えば何らかのボタンを押した際の処理の中等)
            NotificationCenter.default.post(name: Notification.Name("myNotificationName"),
                                            object: nil)
        }

        // 切断
        if (call.hasConnected == true && call.hasEnded == true) {
            print("切断 CXCallState : Disconnected");
        }
    }
}

こんな感じで実現できました。\(^o^)/
GitHubが使えればコードをアップできるらしいけどよくわかんないんだよね。/(^o^)\

【Swift4】【CallKit】CXCall、電話の発着信等を取得する。” に3件のコメントがあります

      1. ありがとうございます。
        ドロイド君では、簡単に出来た事がiPhoneの新しいバージョンからは、出来なくなったと聞いたので、参考にしてみます。

BlackField へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です