Как определить входящий вызов программно

Мне нужно мое приложение для отправки уведомления, когда есть вызов (входящий вызов, связанный, завершенный вызов)   Я зарегистрировал свой viewController с уведомлением.

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(callReceived:) name:CTCallStateIncoming object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(callEnded:) name:CTCallStateDisconnected object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(callConnected:) name:CTCallStateConnected object:nil];

Я также сделал метод проверки состояния вызова

-(IBAction)checkForCall:(id)sender{
    NSLog(@"call state %@ id %@",call.callState,call.callID);
    CTCallCenter *callCenter = [[CTCallCenter alloc] init];
    callCenter.callEventHandler = ^(CTCall* call){
        if (call.callState == CTCallStateDisconnected)
        {
            NSLog(@"Call has been disconnected");

        }
        else if (call.callState == CTCallStateConnected)
        {
            NSLog(@"Call has just been connected");

        }
        else if(call.callState == CTCallStateIncoming)
        {
            NSLog(@"Call is incoming");

        }
        else
        {
            NSLog(@"None of the conditions");
        }
    };
}

Но ничего из этого не получается. Пожалуйста, помогите мне.

Где ошибка? Есть ли какой-нибудь код, который рассказывает, как использовать основную телефонию?

Ответ 1

используйте этот

Appdelegate.h

#import <CoreTelephony/CTCallCenter.h>
#import <CoreTelephony/CTCall.h>
...
@property (nonatomic, strong) CTCallCenter* callCenter;

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{  
   .... 
  self.callCenter = [[CTCallCenter alloc] init];
  [self handleCall];
   .... 
}

-(void)handleCall
{
    self.callCenter.callEventHandler = ^(CTCall *call){

       if ([call.callState isEqualToString: CTCallStateConnected])
       {
          //NSLog(@"call stopped");
       }
       else if ([call.callState isEqualToString: CTCallStateDialing])
       {
        }
       else if ([call.callState isEqualToString: CTCallStateDisconnected])
       {
          //NSLog(@"call played");
        }
       else if ([call.callState isEqualToString: CTCallStateIncoming])
       {
           //NSLog(@"call stopped");
       }
     };
  }

Ответ 2

In Swift 3 

Использовать CXCallObserver

import CallKit

var callObserver = CXCallObserver()

class AppDelegate: UIResponder, UIApplicationDelegate, CXCallObserverDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

callObserver.setDelegate(self, queue: nil) //Set delegate to self to call delegate method. 

return true 

}

 func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {

    if call.hasConnected {
        Print("Call Connect -> \(call.uuid)")
    }

    if call.isOutgoing {
        Print("Call outGoing \(call.uuid)")
    }

    if call.hasEnded {
        Print("Call hasEnded \(call.uuid)")
    }

    if call.isOnHold {
        Print("Call onHold \(call.uuid)")
      }
  }
}

Ответ 3

для iOS 10 И быстро 3:

a) скопируйте и вставьте новый пустой контроллер в новый проект b) запустите его, asyncAfter вызовет вызов... ПРИМЕЧАНИЕ: работает только на устройстве.

// only for iOS10

import UIKit
import CoreTelephony
import CallKit

class ViewController: UIViewController, CXCallObserverDelegate {
    var callCenter : CTCallCenter?
    var observer : CXCallObserver?

    override func viewDidLoad() {
        super.viewDidLoad()

        setup()

        let delay = 2.0
        let when = DispatchTime.now() + delay
        DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in
            self.makeCall()
        })
    }

    final func setup() {

        let networkInfo = CTTelephonyNetworkInfo()
        let code = networkInfo.subscriberCellularProvider?.mobileCountryCode
        print("\(code)")

        self.observer = CXCallObserver()
        self.observer?.setDelegate(self, queue: nil)

        self.callCenter = CTCallCenter()
    }

    final func makeCall() {

        guard let url = URL(string: "telprompt://55555") else {
            print("illegal URL")
            return
        }

        guard UIApplication.shared.canOpenURL(url) else{
            print("cannot open url")
            return
        }

        // iso9.. UIApplication.shared.openURL(url)

        UIApplication.shared.open(url, options: [:], completionHandler: { (Bool) in

        })
    }

    public func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall){

        print("isOutgoing =  \(call.isOutgoing)")
        print("hasConnected =  \(call.hasConnected)")
        print("hasEnded = \(call.hasEnded)")
    }
}

Ответ 4

Это имена состояний, а не имена уведомлений. Вам нужно настроить callEventHandler и проверить состояние там.