한국어

Coding

온누리070 플레이스토어 다운로드
    acrobits softphone
     온누리 070 카카오 프러스 친구추가온누리 070 카카오 프러스 친구추가친추
     카카오톡 채팅 상담 카카오톡 채팅 상담카톡
    
     라인상담
     라인으로 공유

     페북공유

   ◎위챗 : speedseoul


  
     PAYPAL
     
     PRICE
     

pixel.gif

    before pay call 0088 from app


글 수 101

AR / VR 스토어 세일 : 4 월 5 일까지 연장!

AR / VR 도서 번들로 책을 최대 50 %까지 절약하십시오.

iOS 용 CallKit 자습서

앱이 시스템 수준 전화 통합을 위해 CallKit을 사용하는 방법과 통화 차단 / 식별을위한 디렉토리 확장을 구축하는 방법에 대해 알아보십시오.

번역

  • Swift 3, iOS 10, Xcode 8

iOS에서의 삶이 VoIP 앱 개발자에게는 언제나 완벽한 것은 아닙니다. 특히 알림 전달은 어려웠습니다.백그라운드에서 앱을 사용하면 단 한 번의 옵션으로 일반적인 알림 만 남았습니다. 풍부하고 내장 된 호출 UI와 비교해 보면 갑자기 앱이 너무 통합적이라고 느끼지 않을 것입니다.

다행히도, 애플은 iOS 10에서 CallKit을 도입하여 그 모든 것을 바꾸 었습니다!

이 튜토리얼에서는 다음과 같은 앱을 빌드하여 CallKit의 힘을 엿볼 수 있습니다.

  • 시스템 서비스를 사용하여 수신 및 발신 통화를보고합니다.
  • 수신 전화를 식별하거나 차단하기 위해 전화 번호부를 관리합니다.

참고 : CallKit 기능은 시뮬레이터에서 작동하지 않습니다. 이 튜토리얼을 따라하기 위해서는 iOS 10.2가 설치된 iPhone이 필요합니다.

시작하기

이 자습서의 시작 프로젝트 를 다운로드하고 압축을 풉니 다. 장치에서 프로젝트를 디버그하려면 코드 서명을 설정해야합니다. Xcode에서 프로젝트 파일을 열고 프로젝트 탐색기에서 핫라인을 선택하십시오.

번들 식별자를 변경하여 시작합니다. 프로젝트가 선택되면 일반 탭으로 이동하여 신원 섹션을 찾으십시오. 번들 식별자를 고유 한 것으로 변경하십시오.

번들 식별자 변경

그런 다음 서명 섹션을 찾습니다. 팀 옆에있는 드롭 다운에서 원하는 개발 팀을 선택하십시오 (제 경우에는 개인 팀입니다). 또한 "자동 서명 관리"가 선택되어 있는지 확인하십시오. 그러면 Xcode가 앱의 프로비저닝 프로파일을 자동으로 만들 수 있습니다.

코드 서명 설정

설정을 테스트하려면 iPhone에서 앱을 빌드하고 실행하십시오.

첫 번째 실행

이 응용 프로그램은 아무것도하지 않습니다!

이 응용 프로그램은 아무것도하지 않습니다!

현재이 애플리케이션은별로 도움이되지 않지만 이미 스타터 프로젝트에 소스 파일이 상당히 많이 있음을 알 수 있습니다. 그들은 주로 UI를 설정하고 사용자 상호 작용을 다루는 책임이 있지만 다음 단계로 이동하기 전에 살펴볼 가치가있는 두 가지 주요 클래스가 있습니다.

  • Call 는 전화 Call 나타냅니다. 이 클래스는 호출을 식별하는 속성 (예 : UUID 또는 핸들)과 사용자가 호출을 시작하거나 응답하거나 종료하는 시점을 나타내는 수명주기 콜백을 제공합니다.
  • CallManager 현재 앱에서 진행중인 전화 목록을 유지 관리하며 전화를 추가하거나 제거하는 방법을 제공합니다. 튜토리얼 전반에 걸쳐이 클래스를 확장 할 것이다.

CallKit은 무엇입니까?

CallKit은 앱이 기본 전화 UI와 긴밀하게 통합되도록하여 VoIP 환경을 개선하는 것을 목표로하는 새로운 프레임 워크입니다. CallKit을 채택하면 앱에서 다음을 수행 할 수 있습니다.

  • 잠금 상태와 잠금 해제 상태 모두에서 기본 수신 전화 화면을 사용하십시오.
  • 기본 전화 응용 프로그램의 연락처, 즐겨 찾기 및 최근 화면에서 통화를 시작하십시오.
  • 시스템의 다른 통화와 상호 작용하십시오.

이 섹션에서는 CallKit 아키텍처에 익숙해집니다. 아래 다이어그램은 모든 주요 플레이어를 보여줍니다.

arch00

CallKit으로 작업 할 때 상호 작용할 기본 클래스는 CXProvider 와 CXCallController 입니다.다이빙 할 시간!

CXProvider

앱은 CXProvider 를 사용하여 대역 외 통지를 시스템에보고합니다. 이들은 일반적으로 들어오는 호출과 같은 외부 이벤트입니다.

이러한 이벤트가 발생할 때마다 CXProvider 는 호출 업데이트를 만들어 시스템에 알립니다.통화 업데이트 란 무엇입니까? 통화 업데이트는 새롭거나 변경된 통화 관련 정보를 캡슐화합니다. CXCallUpdate 클래스는 호출자의 이름과 같은 속성을 노출하거나 오디오 전용인지 또는 화상 통화인지를 표시합니다.

차례대로 시스템이 앱에 이벤트를 알리려고 할 때마다 CXAction 인스턴스의 형태로 앱을 알립니다. CXAction 은 전화 통신 작업을 나타내는 추상 클래스입니다. 각 작업에 대해 CallKit은 CXAction의 다른 구체적인 구현을 제공합니다. 예를 들어 발신 전화 시작은 CXStartCallAction , CXAnswerCallAction 은 수신 전화 응답에 사용됩니다. 동작은 고유 한 UUID로 식별되며 실패하거나 수행 할 수 있습니다.

Apps는 CXProviderDelegate 프로토콜을 통해 CXProvider 와 통신 할 수 있습니다. CXProviderDelegate 프로토콜은 공급자 라이프 사이클 이벤트 및 수신 작업에 대한 메서드를 정의합니다.

CXCallController

앱은 CXCallController 를 사용하여 "시작 통화"와 같은 사용자 요청에 대해 시스템에 CXCallController . 이것은 CXProvider 와 CXProvider 의 주요 차이점입니다. 공급자의 작업이 시스템에보고하는 동안 호출 컨트롤러는 사용자를 대신하여 시스템에서 요청을합니다.

콜 컨트롤러는 트랜잭션을 사용하여 이러한 요청을 수행합니다. CXTransaction 대표되는 트랜잭션은 하나 이상의 CXAction 인스턴스를 포함합니다. 통화 컨트롤러는 시스템에 트랜잭션을 보내고 모든 것이 정상적으로 처리되면 시스템은 공급자에게 적절한 조치로 응답합니다.

물론 많은 정보가 있었지만 실제로 어떻게 작동합니까?

수신 전화

아래 다이어그램은 들어오는 콜 흐름의 개요입니다.

들어오는

  1. 들어오는 호출이있을 때마다 앱은 CXCallUpdate 를 생성하고 제공자를 사용하여 시스템에 전송합니다.
  2. 이 시점에서 시스템은 모든 서비스에 대한 수신 호출로이를 게시합니다.
  3. 사용자가 호출에 응답하면 시스템은 CXAnswerCallAction 인스턴스를 공급자에게 보냅니다.
  4. 앱은 적절한 CXProviderDelegate 메소드를 구현하여 호출에 응답 할 수 있습니다.

첫 번째 단계는 공급자에 대한 대리자를 만드는 것입니다.

Xcode로 돌아가서 프로젝트 탐색기에서 강조 표시된 App 그룹을 사용하여 File \ New \ File ...으로 이동하여 iOS \ Source \ Swift File을 선택하십시오. 이름을 ProviderDelegate로 설정하고 작성을 클릭 하십시오 .

파일에 다음 코드를 추가하십시오.

 AVFoundation 가져 오기
 CallKit 가져 오기

 클래스 ProviderDelegate : NSObject {
   // 1.
   fileprivate는 callManager를 사용합니다. CallManager
   fileprivate는 공급자를 제공합니다 : CXProvider
  
   init (callManager : CallManager) {
     self.callManager = callManager
     // 2.
     공급자 = CXProvider (구성 : 형식 (of : self) .providerConfiguration)
    
     super.init ()
     // 삼.
     provider.setDelegate (self, queue : nil)
   }
  
   // 4.
   정적 var 공급자 구성 : CXProviderConfiguration {
     let providerConfiguration = CXProviderConfiguration (localizedName : "핫라인")
    
     providerConfiguration.supportsVideo = true
     providerConfiguration.maximumCallsPerCallGroup = 1
     providerConfiguration.supportedHandleTypes = [.phoneNumber]
    
     return providerConfiguration
   }
 }

다음과 같은 상황이 발생합니다.

  1. 공급자 대리자는 공급자와 통화 컨트롤러와 상호 작용하므로 두 가지 모두에 대한 참조를 저장합니다. 속성은 fileprivate 로 표시되어 있으므로 동일한 파일의 확장명에서 속성에 fileprivate 수 있습니다.
  2. 아래의 정적 변수로 저장되는 적절한 CXProviderConfiguration 하여 공급자를 초기화합니다. 공급자 구성은 호출의 동작 및 기능을 지정합니다.
  3. 공급자가 제공하는 이벤트에 응답하려면 해당 대리자를 설정합니다.ProviderDelegate 가 아직 CXProviderDelegate 따르지 CXProviderDelegate 줄은 빌드 오류를 발생 CXProviderDelegate .
  4. 핫라인의 경우 공급자 구성을 통해 화상 통화, 전화 번호 처리를 허용하고 통화 그룹 수를 하나로 제한 할 수 있습니다. 추가 사용자 정의는 CallKit 설명서를 참조하십시오.

구성 바로 아래에 다음 도우미 메서드를 추가하십시오.

 func reportIncomingCall (uuid : UUID, handle : String, hasVideo : Bool = false, 완료 : ((NSError?) -> Void)?) {
   // 1.
   let update = CXCallUpdate ()
   update.remoteHandle = CXHandle (type : .phoneNumber, value : handle)
   update.hasVideo = hasVideo
  
   // 2.
   provider.reportNewIncomingCall (with : uuid, update : update) {오류
     if error == nil {
       // 삼.
       let call = 호출 (uuid : uuid, handle : handle)
       self.callManager.add (call : call)
     }
    
     // 4.
     완료? (NSError로 오류)
   }
 }

이 도우미 메서드는 앱이 CXProvider API를 호출하여 들어오는 호출을보고하도록 허용합니다. 다음은 진행 상황입니다.

  1. 모든 관련 통화 메타 데이터가 포함 된 시스템의 통화 업데이트를 준비합니다.
  2. 공급자에서 reportIncomingCall(with:update:completion) 을 호출하면 시스템에 수신 호출이 통지됩니다.
  3. 시스템이 호출을 처리하면 완료 핸들러가 호출됩니다. 오류가없는 경우 Call 인스턴스를 만들고 CallManager 를 통해 호출 목록에 추가합니다.
  4. 완성 처리기를 호출합니다 ( nil 이 아닌 경우).

이 메소드는 수신 호출을 시뮬레이트하기 위해 앱의 다른 클래스에서 호출 할 수 있습니다.

다음 단계는 프로토콜 준수를 보장하는 것입니다. 여전히 ProviderDelegate.swift 에서 CXProviderDelegate 를 준수하도록 새 확장을 선언하십시오.

 확장 ProviderDelegate : CXProviderDelegate {
  
   func providerDidReset (_ 공급자 : CXProvider) {
     stopAudio ()
    
     callManager.calls {
       call.end ()
     }
    
     callManager.removeAllCalls ()
   }
 }

CXProviderDelegate 는 하나의 필수 메서드 인 providerDidReset(_:) 만을 지정합니다. 공급자는 재설정 될 때이 메소드를 호출하여 앱이 진행중인 모든 호출을 정리하고 정리 상태로 되돌릴 수있는 기회를 제공합니다. 이 구현에서는 진행중인 오디오 세션을 종료하고 모든 활성 통화를 처리합니다.

이제 ProviderDelegate 는 들어오는 호출을보고하는 방법을 ProviderDelegate 합니다. 이제 사용할 것입니다!

프로젝트 탐색기에서 App 그룹이 강조 표시된 상태에서 AppDelegate.swift 를 열어 편집합니다. 먼저 새 속성을 클래스에 추가합니다.

 lazy var providerDelegate : ProviderDelegate = ProviderDelegate (callManager : self.callManager)

공급자 대리인을 사용할 준비가되었습니다! AppDelegate 다음 메서드를 추가합니다.

 func displayIncomingCall (uuid : UUID, handle : String, hasVideo : Bool = false, 완료 : ((NSError?) -> Void)?) {
   providerDelegate.reportIncomingCall (uuid : uuid, handle : 핸들, hasVideo : hasVideo, 완료 : 완료)
 }

이 메서드는 다른 클래스가 공급자 대리자의 도우미 메서드에 액세스 할 수있게합니다.

퍼즐의 마지막 부분은이 호출을 사용자 인터페이스에 연결하는 것입니다. 프로젝트 탐색기에서 UI /보기 컨트롤러 그룹을 확장하고 앱의 기본 화면에 대한 컨트롤러 인 CallsViewController.swift를 엽니 다. unwindSegueForNewCall(_:) 의 빈 구현을 찾아 다음 코드로 unwindSegueForNewCall(_:) .

 @IBAction 개인 기능 unwindForNewCall (_ segue : UIStoryboardSegue) {
   // 1.
   newCallController = segue.source를!  NewCallViewController
   가드하자 handle = newCallController.handle else {return}
   let videoEnabled = newCallController.videoEnabled
  
   // 2.
   let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask (expirationHandler : nil)
   DispatchQueue.main.asyncAfter (wallDeadline : DispatchWallTime.now () + 1.5) {
     AppDelegate.shared.displayIncomingCall (uuid : UUID (), handle : handle, hasVideo : videoEnabled) {_ in
       UIApplication.shared.endBackgroundTask (backgroundTaskIdentifier)
     }
   }
 }

스 니펫은 다음을 수행합니다.

  1. 이 unwind segue의 소스 인 NewCallViewController 에서 호출의 속성을 추출합니다.
  2. 사용자는 작업이 완료되기 전에 앱을 일시 중지 할 수 있으므로 백그라운드 작업을 사용해야합니다.

이제 모든 것이 연결되고, 응용 프로그램을 빌드하고 실행하고 다음을 수행하십시오.

  1. 오른쪽 구석에있는 더하기 버튼을 누릅니다.
  2. 번호를 입력하고 분할 된 컨트롤에서 "수신"이 선택되어 있는지 확인한 다음 완료를 누릅니다.
  3. 화면을 잠급니다. 이 단계는 중요하고 풍부한 기본 네비게이션 UI에 액세스하는 유일한 방법이기 때문에 중요합니다.

몇 초 이내에 기본 수신 전화 UI가 표시됩니다.

작동 중!

작동 중!

그러나 전화를 받자 마자 UI가 다음 상태에 머물러 있다는 것을 알 수 있습니다.

아니면 그렇지?

아니면 그렇지?

이것은 전화 응답을 담당하는 조각을 구현해야하기 때문입니다. Xcode로 돌아가 ProviderDelegate.swift로 돌아와 다음 코드를 클래스 확장에 추가합니다.

 func 공급자 (_ 공급자 : CXProvider, 작업 수행 : CXAnswerCallAction) {
   // 1.
   가드하자 call = callManager.callWithUUID (uuid : action.callUUID) else {
     action.fail ()
     반환
   }
  
   // 2.
   configureAudioSession ()
   // 삼.
   call.answer ()
   // 4.
   action.fulfill ()
 }

 // 5.
 func 공급자 (_ 공급자 : CXProvider, didActivate audioSession : AVAudioSession) {
   startAudio ()
 }

다음은 단계별 분석입니다.

  1. 응답 할 호출의 UUID에 해당하는 호출 관리자로부터 참조를 가져 오는 것으로 시작합니다.
  2. 호출에 대한 오디오 세션을 구성하는 것은 응용 프로그램의 책임입니다. 시스템은 높은 우선 순위로 세션을 활성화 처리합니다.
  3. answer() 를 호출하면 호출이 현재 활성화되었음을 나타냅니다.
  4. 행동을 처리 할 때 실패하거나 이행하는 것이 중요합니다. 프로세스 중에 오류가 없으면 fulfill() 을 호출하여 성공을 나타낼 수 있습니다.
  5. 시스템이 공급자의 오디오 세션을 활성화하면 대리인에게 알립니다. 통화 오디오 처리를 시작할 수있는 기회입니다.

빌드 및 응용 프로그램을 실행하고 들어오는 호출을 다시 시작하십시오. 통화에 응답하면 시스템이 진행중인 통화 상태로 성공적으로 전환됩니다.

그게 더 좋아!

그게 더 좋아!

휴대 전화의 잠금을 해제하면 iOS와 앱 모두 현재 올바른 통화 상태를 반영합니다.

홈 화면에 표시된 진행중인 통화 및 핫라인의 기본 화면

홈 화면에 표시된 진행중인 통화 및 핫라인의 기본 화면

전화 끊기

전화를 받으면 새로운 문제가 있음을 알 수 있습니다. 현재 전화를 끊을 방법이 없습니다. 앱은 기본 통화 화면과 앱 내에서 통화를 종료하는 두 가지 방법을 지원합니다.

아래의 다이어그램은 두 경우 모두 무슨 일이 벌어지고 있는지 보여줍니다.

통화 종료

첫 번째 단계의 차이점을 확인하십시오. 사용자가 통화 중 화면 (1a)에서 통화를 종료하면 시스템에서 자동으로 CXEndCallAction 을 제공 업체에 보냅니다. 그러나 핫라인 (1b)을 사용하여 통화를 종료하려면 작업을 트랜잭션으로 랩핑하고 시스템에서 요청하십시오. 시스템이 요청을 처리하면 CXEndCallAction 다시 공급자에게 보냅니다.

결말 호출을 지원하려는 방식에 관계없이 앱이 작동하려면 필요한 CXProviderDelegate 메서드를 구현해야합니다. ProviderDelegate.swift를 열고 클래스 확장에 다음 구현을 추가합니다.

 func 공급자 (_ 공급자 : CXProvider, 작업 수행 : CXEndCallAction) {
   // 1.
   가드하자 call = callManager.callWithUUID (uuid : action.callUUID) else {
     action.fail ()
     반환
   }
  
   // 2.
   stopAudio ()
   // 삼.
   call.end ()
   // 4.
   action.fulfill ()
   // 5.
   callManager.remove (call : call)
 }

그리 어렵지 않습니다! 다음은 진행 상황입니다.

  1. 먼저 통화 관리자로부터 통화에 대한 참조를 가져옵니다.
  2. 통화가 끝나기 직전에 통화 오디오 처리를 중지해야합니다.
  3. end() 호출하면 호출 상태가 변경되므로 다른 클래스가 새 상태에 반응 할 수 있습니다.
  4. 이 시점에서 조치가 완수 된 것으로 표시하게됩니다.
  5. 더 이상 전화가 필요 없기 때문에 통화 관리자는 통화를 처리 할 수 ​​있습니다.

이것은 호출 UI를 처리합니다. 앱에서 전화를 CallManager 려면 CallManager 를 연장해야합니다. 프로젝트 탐색기에서 통화 관리 그룹을 확장하면 CallManager.swift가 열립니다.

호출 관리자는 CXCallController 와 통신하므로 인스턴스에 대한 참조가 필요합니다.CallManager 클래스에 다음 속성을 추가합니다.

 비공개로 callController = CXCallController ()

이제 다음 메소드를 클래스에 추가하십시오.

 func end (호출 : 호출) {
   // 1.
   let endCallAction = CXEndCallAction (call : call.uuid)
   // 2.
   let transaction = CXTransaction (액션 : endCallAction)
  
   requestTransaction (transaction)
 }

 // 삼.
 개인 func requestTransaction (_ 트랜잭션 : CXTransaction) {
   callController.request (transaction) {오류
     if let error = error {
       print ( "트랜잭션을 요청하는 중 오류 : \ (오류)")
     } else {
       print ( "요청 된 트랜잭션")
     }
   }
 }

다음과 같은 현상이 발생합니다.

  1. 먼저 "통화 종료"작업을 만듭니다. 호출의 UUID를 이니셜 라이저에 전달하므로 나중에 식별 할 수 있습니다.
  2. 다음 단계는 조치를 트랜잭션으로 랩핑하여 시스템에 보낼 수있게하는 것입니다.
  3. 마지막으로 호출 컨트롤러에서 request(_:completion:) 를 호출합니다. 시스템은 공급자가이 트랜잭션을 수행하도록 요청할 것이며,이 트랜잭션은 방금 구현 한 대리자 메서드를 호출합니다.

마지막 단계는 작업을 사용자 인터페이스에 연결하는 것입니다.CallViewViewController.swift를 열고 tableView(_:cellForRowAt:) 구현 바로 아래에서 다음 호출을 작성합니다.

 재정의 func tableView (_ tableView : UITableView, 커밋 editingStyle : UITableViewCellEditingStyle, forRowAt indexPath : IndexPath) {
   let call = callManager.calls [indexPath.row]
   callManager.end (call : call)
 }

사용자가 행에서 스 와이프 - 삭제를 호출하면 앱은 CallManager 에게 해당 통화를 종료하도록 요청합니다.

장치에서 프로젝트를 빌드하고 실행하고 다음 단계를 수행하십시오.

  1. 오른쪽 구석에있는 더하기 버튼을 누릅니다.
  2. 번호를 입력하고 분할 된 컨트롤에서 "수신"이 선택되어 있는지 확인한 다음 완료를 누릅니다.
  3. 몇 초 이내에 들어오는 전화를 받게됩니다. 대답을하면 UI에 활성 상태로 표시됩니다.
  4. 활성 통화를 나타내는 행에서 왼쪽으로 스 와이프 한 다음 끝내기를 누릅니다.

이 시점에서 통화가 종료됩니다. 잠금 / 홈 화면이나 앱에서 진행중인 통화를보고하지 않습니다.

지금 끊지 마!

지금 끊지 마!

기타 공급자 조치

CXProviderDelegate 의 설명서 페이지를 보면 공급자가 수행 할 수있는 더 많은 작업 (음소거 및 그룹화, 보류중인 통화 설정 포함)이 있음을 알 수 있습니다. 후자는 Hotline의 좋은 특징처럼 들리므로 지금 바로 구현할 것입니다.

사용자가 통화의 보류 상태를 설정하려고 할 때마다 앱은 CXSetHeldCallAction 인스턴스를 공급자에게 보냅니다. 관련 위임 메서드를 구현하는 것은 사용자의 임무입니다.ProviderDelegate.swift를 열고 클래스 확장에 다음 구현을 추가합니다.

 func 공급자 (_ 공급자 : CXProvider, 작업 수행 : CXSetHeldCallAction) {
   가드하자 call = callManager.callWithUUID (uuid : action.callUUID) else {
     action.fail ()
     반환
   }
  
   // 1.
   call.state = action.isOnHold?  .held : .active
  
   // 2.
   if call.state == .held {
     stopAudio ()
   } else {
     startAudio ()
   }
  
   // 삼.
   action.fulfill ()
 }

이것은 매우 간단합니다.

  1. 호출에 대한 참조를 얻은 후에는 작업의 isOnHold 속성에 따라 상태를 업데이트합니다.
  2. 새로운 상태에 따라 통화 오디오를 시작하거나 처리를 중지 할 수 있습니다.
  3. 이 시점에서 수행 된 작업을 표시 할 수 있습니다.

이것은 사용자가 시작한 행동이기 때문에 CallManager 클래스도 확장해야합니다.CallManager.swift를 열고 다음 구현을 end(call:) 바로 추가하십시오 end(call:) .

 func setHeld (호출 : 호출, onHold : Bool) {
   setHeldCallAction = CXSetHeldCallAction (call : call.uuid, onHold : onHold)
   let transaction = CXTransaction ()
   transaction.addAction (setHeldCallAction)
  
   requestTransaction (transaction)
 }

이 코드는 end(call:) 메소드와 매우 유사합니다. 실제로이 두 메소드의 유일한 차이점은이 메소드가 CXSetHeldCallAction 의 인스턴스를 트랜잭션으로 래핑한다는 것입니다. 작업에는 통화의 UUID 및 보류 상태가 포함됩니다.

이제이 작업을 UI에 연결해야 할 때입니다. CallsViewController.swift를 열고 파일 끝에 UITableViewDelegate 로 표시된 클래스 확장을 찾습니다.tableView(_:titleForDeleteConfirmationButtonForRowAt:) 바로 아래의 클래스 확장에 다음 구현을 추가합니다.

 재정의 func tableView (_ tableView : UITableView, didSelectRowAt indexPath : IndexPath) {
   let call = callManager.calls [indexPath.row]
   call.state = call.state == .held?  .active : .held
   callManager? .setHeld (call : call, onHold : call.state == .held)
  
   tableView.reloadData ()
 }

사용자가 행을 탭할 때마다 위의 코드는 해당 통화의 보류 상태를 업데이트합니다.

응용 프로그램을 빌드하고 실행하고 새로운 수신 전화를 시작하십시오. 통화 셀을 탭하면 상태 라벨이 '활성'에서 '대기 중'으로 변경됩니다.

IMG_6741

발신 통화 처리

마지막으로 사용자가 실행하는 작업은 발신 전화를 걸기위한 것입니다.ProviderDelegate.swift를 열고 다음 구현을 CXProviderDelegate 클래스 확장에 추가합니다.

 func 공급자 (_ 공급자 : CXProvider, 작업 수행 : CXStartCallAction) {
   call = 통화 (uuid : action.callUUID, 발신 : true, 처리 : action.handle.value)
   // 1.
   configureAudioSession ()
   // 2.
   call.connectedStateChanged = {[약한 자기, 약한 호출] in
     가드하자 강하다 셀프 = 자기, 전화 = 다른 통화 {돌아 가기}

     if call.connectedState == .pending {
       strongSelf.provider.reportOutgoingCall (with : call.uuid, startedConnectingAt : nil)
     } else if call.connectedState == .complete {
       strongSelf.provider.reportOutgoingCall (with : call.uuid, connectedAt : nil)
     }
   }
   // 삼.
   call.start {[약한 자기, 약한 호출] 성공
     가드하자 강하다 셀프 = 자기, 전화 = 다른 통화 {돌아 가기}

     성공 {
       action.fulfill ()
       strongSelf.callManager.add (call : call)
     } else {
       action.fail ()
     }
   }
 }

공급자는 발신 요청이있을 때이 위임 메서드를 호출합니다.

  1. 통화 관리자에서 통화의 UUID로 Call 를 만든 후에는 앱의 오디오 세션을 구성해야합니다. 수신 통화와 마찬가지로이 시점에서 귀하의 책임은 구성 일뿐입니다. 실제 처리는 나중에 provider(_:didActivate) 대리자 메서드가 호출 될 때 시작됩니다.
  2. 대리인은 통화의 수명주기를 모니터링합니다. 처음에는 발신 전화가 연결되기 시작했다고보고합니다. 통화가 마지막으로 연결되면 공급자 대리인도이를보고합니다.
  3. 호출에서 start() 를 호출하면 라이프 사이클이 변경됩니다. 연결이 성공하면 통화가 완료된 것으로 표시 될 수 있습니다.

프로 바이더 대리자가 발신 통화를 처리 할 준비가되었으므로 이제 앱을 만드는 법을 가르쳐야 할 때입니다. :] CallManager.swift를 열고 다음 메소드를 클래스에 추가하십시오.

 func startCall (handle : String, videoEnabled : Bool) {
   // 1
   let handle = CXHandle (type : .phoneNumber, value : handle)
   // 2
   let startCallAction = CXStartCallAction (call : UUID (), handle : handle)
   // 삼
   startCallAction.isVideo = videoEnabled
   let transaction = CXTransaction (액션 : startCallAction)
  
   requestTransaction (transaction)
 }

이 메소드는 CXTransaction "Start call"액션을 래핑하여 시스템에 요청합니다.

  1. CXHandle 표시된 핸들은 핸들 유형과 그 값을 지정할 수 있습니다. 핫라인은 전화 번호 핸들을 지원하므로 여기서도 사용하게됩니다.
  2. CXStartCallAction 은 고유 한 UUID와 핸들을 입력으로받습니다.
  3. 액션의 isVideo 속성을 설정하여 호출이 오디오 전용인지 또는 비디오 호출인지를 지정할 수 있습니다.

새 액션을 UI에 연결해야 할 때입니다. CallsViewController.swift를 열고 unwindForNewCall unwindForNewCall(_:) 의 이전 구현을 unwindForNewCall(_:) 다음과 일치시킵니다.

 @IBAction 개인 기능 unwindForNewCall (_ segue : UIStoryboardSegue) {
   newCallController = segue.source를!  NewCallViewController
   가드하자 handle = newCallController.handle else {return}
   수신 = newCallController.incoming하자
   let videoEnabled = newCallController.videoEnabled
  
   들어오는 경우 {
     let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask (expirationHandler : nil)
     DispatchQueue.main.asyncAfter (wallDeadline : DispatchWallTime.now () + 1.5) {
       AppDelegate.shared.displayIncomingCall (uuid : UUID (), handle : handle, hasVideo : videoEnabled) {_ in
         UIApplication.shared.endBackgroundTask (backgroundTaskIdentifier)
       }
     }
   } else {
     callManager.startCall (handle : handle, videoEnabled : videoEnabled)
   }
 }

코드에 미묘한 변화가 있습니다. incoming 것이 틀릴 때마다 View Controller는 호출 관리자에게 나가는 호출을 시작하도록 요청합니다.

그게 전화를하는 데 필요한 전부입니다. 테스트를 시작할 시간입니다! 기기에서 앱을 만들고 실행하십시오. 새 통화를 시작하려면 오른편 모서리의 더하기 버튼을 탭하고, 이번에는 분류 된 컨트롤에서 "발신"을 선택하십시오.

나가는

이 시점에서 새 통화가 목록에 표시되어야합니다. 통화의 현재 단계에 따라 다른 상태 라벨이 표시됩니다.

전화 걸기 2

나는 지금 전화 할 수있다!

나는 지금 전화 할 수있다!

여러 통화 관리

핫라인 사용자가 여러 번 전화를받는 시나리오를 상상하기 쉽습니다. 처음에는 전화를 걸고 들어오는 전화를 걸고 들어오는 전화가 오기 전에 홈 버튼을 눌러이를 시뮬레이트 할 수 있습니다.이 시점에서 앱은 사용자에게 다음 화면을 표시합니다.

IMG_6753

시스템은 사용자가 문제점을 해결하는 방법을 결정하도록합니다. 선택에 따라 여러 액션을 CXTransaction 합니다. 예를 들어 사용자가 진행중인 통화를 종료하고 새 통화에 응답하면 시스템은 전자 CXStartCallAction 대한 CXStartCallAction 과 전자 CXEndCallAction 대한 CXEndCallAction 을 만듭니다. 두 작업 모두 트랜잭션으로 래핑되고 공급자에게 전송되며, 공급자는이를 개별적으로 처리합니다. 따라서 앱이 이미 개별 요청을 수행하는 방법을 알고 있다면 추가 조치가 필요하지 않습니다.

추가 코드없이 기능 구현하기!

추가 코드없이 기능 구현하기!

위의 시나리오를 해결하여 테스트 할 수 있습니다. 통화 목록에는 선택 사항이 반영됩니다.앱은 한 번에 하나의 오디오 세션 만 처리합니다. 재개를 선택하면 다른 통화가 자동으로 보류됩니다.

복수형

전화 번호 디렉터리 확장 만들기

디렉토리 확장은 CallKit에서 제공하는 새로운 확장 점입니다. 그것은 귀하의 VoIP 애플 리케이션 수 있습니다 :

  • 시스템의 차단 목록에 전화 번호를 추가하십시오.
  • 수신 전화를 자신의 전화 번호 또는 전자 메일 주소와 같은 기타 고유 식별 정보로 식별합니다.

시스템이 전화를받을 때마다 주소록에서 일치 사항을 확인합니다. 디렉토리를 찾지 못하면 앱 별 디렉토리 확장을 체크인 할 수 있습니다. 핫라인에 디렉토리 확장을 추가하지 않으시겠습니까?

Xcode로 돌아가 File \ New \ Target ...으로 이동하여 Call Directory Extension을 선택 하십시오 . HotlineDirectory로 이름을 지정하고 마침을 클릭하십시오. Xcode는 자동으로 CallDirectoryHandler.swift 라는 새 파일을 만듭니다. 프로젝트 탐색기에서 찾아 내고 내용을 확인하십시오.

첫 번째 방법은 beginRequest(with:) 입니다. 이 메소드는 확장 기능이 초기화 될 때 호출됩니다. 오류가있는 경우 확장 프로그램은 cancelRequest(withError:) 호출하여 호스트 응용 프로그램에 확장 요청을 취소하도록 cancelRequest(withError:) 합니다. 앱 별 디렉토리를 구축하는 두 가지 다른 방법에 의존합니다.

addBlockingPhoneNumber(to:) 는 차단되어야하는 모든 전화 번호를 수집합니다. 구현을 다음으로 바꾸십시오.

 private func addBlockingPhoneNumbers (컨텍스트 : CXCallDirectoryExtensionContext) throws {
   전화 번호를 알려주십시오 : [CXCallDirectoryPhoneNumber] = [1234]
   phoneNumber에 대한 전화 번호 {
     context.addBlockingEntry (withNextSequentialPhoneNumber : phoneNumber)
   }
 }

주어진 전화 번호로 addBlockingEntry(withNextSequentialPhoneNumber:) 를 호출하면 차단 목록에 추가됩니다. 번호가 차단되면 시스템 전화 통신 공급자는 해당 번호의 전화를 표시하지 않습니다.

이제 addIdentificationPhoneNumbers(to:) 살펴보십시오. 메소드 본문을 아래 코드로 바꿉니다.

 private func addIdentificationPhoneNumbers (컨텍스트 : CXCallDirectoryExtensionContext) throws {
   전화 번호를 알려주십시오 : [CXCallDirectoryPhoneNumber] = [1111]
   let labels = [ "RW 튜토리얼 팀"]
  
   for (phoneNumber, label) for zip (전화 번호, 레이블) {
     context.addIdentificationEntry (withNextSequentialPhoneNumber : phoneNumber, label : label)
   }
 }

지정된 전화 번호와 레이블로 addIdentificationEntry(withNextSequentialPhoneNumber:label:) 를 호출하면 새로운 식별 항목이 작성됩니다. 시스템이이 번호에서 전화를 수신 할 때마다 호출 UI는 일치하는 레이블을 사용자에게 표시합니다.

새 확장 프로그램을 테스트 할 차례입니다. 장치에서 핫라인 구성표를 작성하고 실행하십시오. 이 시점에서 귀하의 내선 번호가 아직 활성화되지 않았을 수 있습니다. 사용하려면 다음 단계를 수행하십시오.

  1. 설정 앱으로 이동합니다.
  2. 전화 선택
  3. 통화 차단 및 식별 선택
  4. 핫라인 사용
참고 : 시스템에서 확장 프로그램을 인식하거나 사용하는 데 문제가있는 경우 앱을 종료하고 다시 실행 해보십시오. 때때로 iOS는 내선 번호를 사용하기 위해 약간의 추가 도움이 필요합니다.

확장 허용

차단 된 통화를 테스트하는 것은 쉽습니다. 핫라인을 실행하고 번호 1234 에서 수신 전화를 시뮬레이트합니다. 시스템에서 아무 것도보고하지 않는다는 것을 알 수 있습니다. 사실, ProviderDelegate 에서 reportIncomingCall(uuid:handle:hasVideo:completion:) 구현에 중단 점을 넣으면 reportNewIncomingCall(withupdate:completion:) 이 오류를보고하는 경우가 있습니다.

전화 식별을 테스트하려면 핫라인을 다시 실행하고 새 통화를 시뮬레이션하십시오. 이번에는 번호 1111을 입력하십시오. 다음 호출 UI가 표시됩니다.

참고하시기 바랍니다 : 실제 숫자가 아닙니다.]

참고하시기 바랍니다 : 실제 숫자가 아닙니다.]

이 응용 프로그램은 최고입니다!

이 응용 프로그램은 최고입니다!

축하해! 제 1 자 VoIP 경험을 제공하기 위해 CallKit을 활용하는 앱을 만들었습니다! :]

어디로 갈 것인가?

이 자습서의 완성 된 프로젝트를 다운로드 할 수 있습니다.

CallKit에 대해 더 자세히 알고 싶으면 세션 230 (WWDC 2016)을 확인하십시오.

나는 당신이 CallKit 튜토리얼을 즐겼기를 바랍니다. 질문이나 의견이 있으시면 아래 포럼 토론에 참여하십시오!

이와 비슷한

새 항목
신속 패키지 관리자 소개 
새 항목
MVVM 및 데이터 바인딩 : Android 디자인 패턴 
새 항목
통합 로깅으로 마이그레이션 : 콘솔 및 인 스트 루먼트 
새 항목
AR / VR 주 공짜 수상자 및 판매 확장!

기여자

코멘트

번호
제목
글쓴이
101 Objective-c JSON Parsing 제이슨 파싱 Dictionary Array 구분 기호
admin
2019-06-06 6834
100 사용자 정의 컨테이너보기 컨트롤러 전환 xcode objective c
admin
2019-05-25 6806
99 Xcode 글꼴 크기 변경
admin
2019-05-25 9178
98 실습 Objective C Code 연습 실행 온라인 무료 사이트 회원가입 불필요 광고 무
admin
2019-05-22 6471
97 초보) delegate 는 왜필요한가 이것만알면 간단 쉽게 이해 objective C 날로먹기가능
admin
2019-05-22 6373
96 What is a Composite Object? objective c 강의 사이트 아주 훌륭한 유익한 좋은
admin
2019-05-22 11944
95 Segue를 통한 뷰 컨트롤러 전환과 데이터 교환 방법. Delegate 가장 정확하게 설명 쉽게
admin
2019-05-21 6436
94 hide/show text fields with auto layouts and programmatically objective c
admin
2019-05-19 7218
93 Text field 숨기기
admin
2019-05-19 6429
92 Objective-C (전역) 상수 선언 및 사용
admin
2019-05-18 7759
91 키체인 uuid keychaine 설명 및 사용
admin
2019-04-29 6490
90 개발자 등록 인증서 다운로드 푸시 인증요청서 등록 인증서 다운
admin
2019-04-27 7276
89 iOS Application 개발 시작하기 개발자 등록, 등록요청서 , 인증서 다운
admin
2019-04-25 7436
88 iOS Application 개발 시작하기 프로비저닝 생성, XCode 프로젝트 설정
admin
2019-04-25 7642
87 Easy APNs Provider 사용방법 iOS Push발송 테스트
admin
2019-04-23 9403
86 IOS Push php
admin
2019-04-20 6649
85 How to rename an XCode project
admin
2019-04-20 6892
84 Push Notifications and Local Notifications – Tutorial
admin
2019-04-19 7353
83 Push Notifications and Local Notifications (Xcode 9, iOS 11)
admin
2019-04-19 7276
82 A macOS, Linux, Windows app to test push notifications on iOS and Android
admin
2019-04-19 6416
81 Push Notifications by Tutorials iOS developers
admin
2019-04-19 7679
80 Sample app in Swift Objective C receive VoIP push notifications 푸시 테스트 앱
admin
2019-04-19 7932
79 How to create Apple Certificates - Step 1: CSR file creation CSR 생성
admin
2019-04-19 7091
78 Voice Over IP (VoIP) Best Practices Xcode
admin
2019-04-19 10530
77 ios 개발자 계정 만들기 지불 방법 핵심 키포인트 인증서요청 앱등록 앱출시 요점만 쉽게 설명
admin
2019-04-17 6705
76 HybridApp Cordova 코르도바 란
admin
2019-04-15 7729
75 Linphone rebuild
admin
2019-04-09 6513
74 How to rename Xcode project
admin
2019-04-08 7079
73 Part 2: Implementing PushBots SDK for your iOS App
admin
2019-04-08 7148
72 Part 1: Preparing Certificates + Provisioning Profile (iOS)
admin
2019-04-08 6988
71 ios push notification pushkit xcode swift
admin
2019-04-08 6646
70 Xcode 9, Swift 4 Remote Push Notification Setup W/ Firebase
admin
2019-04-08 7386
69 VoIP Push Notifications using iOS Pushkit
admin
2019-04-08 7785
68 UILocalNotification is deprecated in iOS10
admin
2019-04-08 7205
67 아이폰 UserNotifications 사용법
admin
2019-04-08 7276
66 아이폰 VoIP Services Certificate 생성 방법 - 서비스 인증서 생성하는 방법
admin
2019-04-08 7147
65 [아이폰] PushKit 앱 개발 방법
admin
2019-04-08 6907
64 PushKit이란 ? 푸시 알람을 앱에 보내는 것
admin
2019-04-08 10052
63 OSX 키체인접근 p12 파일 인증서, 개인키를 PEM 파일로 openssl
admin
2019-04-08 7320
62 APNs 애플 푸시 앱 개발 push 키 등록 만들기 가장 잘된 동영상 설명
admin
2019-04-08 8317
61 푸시 메시지를 활성화하기 위한 전제 조건 사전작업
admin
2019-04-06 6487
60 푸시 메시지 구성
admin
2019-04-06 6523
59 APNS 또는 GCM 사용을 위한 앱 구성 방법 순서
admin
2019-04-06 7254
58 iOS 인증서 및 프로비저닝 프로파일 만들기
admin
2019-04-04 11349
57 Mac용 키체인 접근이란 무엇입니까?
admin
2019-04-04 7530
56 Apple Push Notification Service 시작하기 AWS 샘플앱 이용 푸시 테스트
admin
2019-04-04 7436
55 iOS Notification 만들기 push 푸시
admin
2019-04-04 9478
54 Mac OS X에서 Java(JDK) 설치 및 삭제하기
admin
2019-04-03 6713
53 iOS12 Chat, Learn Swift 4.2, build iOS 12 Chat Application 스터디
admin
2019-04-03 7088
IOS 앱이 시스템 수준 전화 통합을 위해 CallKit을 사용하는 방법과 통화
admin
2019-04-02 12288
51 CallKit Tutorial for iOS 콜킷 사용
admin
2019-04-02 12095
50 Enhancing VoIP Apps with CallKit - Apple WWDC 2016 콜킷
admin
2019-04-02 6997
49 iOS Beginner : Messaging & Phone call (Swift 4 & Xcode 9)
admin
2019-04-01 7204
48 맥 개발 환경 설정하기
admin
2019-04-01 7395
47 Homebrew 설치 (MacOSX) 동영상
admin
2019-04-01 6942
46 개발자를 위한 맥(Mac) 정보 - 패키지관리자 Homebrew
admin
2019-04-01 7021
45 installing MacPorts on macOS Sierra (plus installing ffmpeg)
admin
2019-04-01 6992
44 MacPort 의 소개와 간단 사용법 - OSX 환경 세팅하기
admin
2019-04-01 7011
43 MacPorts 설치 및 사용법
admin
2019-04-01 7315
42 MacPorts to use system for compiling, installing, and managing open source software. file
admin
2019-04-01 8041
41 애플앱개발 앱스토어등록 개발자사이트등록 앱튠스콘넥트사이트등록
admin
2019-03-24 7075
40 애플 개발자 사이트 apple 앱스토어에 앱을 등록하는 순서
admin
2019-03-24 7796
39 맥 모하비 설치 VM Vmware Workstation Pro 15 설치 ebay 싸게구매
admin
2019-03-23 7479
38 포인터에 익숙해지기 포인터 정리
admin
2019-01-20 6828
37 푸시 알림을 수신하려면 응용 프로그램이 Apple 푸시 알림 서비스 APN
admin
2019-01-10 7566
36 아이폰 카톡 푸시 알림이 안올때! 상세안내 체크
admin
2019-01-10 27699
35 매우 천천히 반응하는 Apple iPhone XS Max 터치 스크린을 수정하는 방법, 터치 스크린 응답 지연됨 문제 해결 가이드
admin
2018-11-09 8110
34 Apple iPhone XS Max 셀룰러 데이터가 작동하지 않는 문제 해결 가이드
admin
2018-11-09 11707
33 Apple iPhone XS Max에서 지속적으로 충돌하는 응용 프로그램을 수정하는 방법 문제 해결 가이드
admin
2018-11-09 7791
32 Apple iPhone XS Max 작동하지 않는 얼굴 ID를 수정하는 방법 문제 해결 가이드
admin
2018-11-09 9123
31 작동하지 않는 Apple iPhone XS Max 마이크를 해결 방법 문제 해결 가이드
admin
2018-11-09 8151
30 iPhone XS Max를 문제 해결, iPhone 과열 문제 해결 [문제 해결 가이드]
admin
2018-11-09 8517
29 Apple iPhone XS Max 배터리가 빨리 소모되면 어떻게해야합니까? 문제 해결 가이드 및 배터리 절약 팁
admin
2018-11-09 8697
28 iPhone XS Max 시스템 가이드 소프트 강제 재시작 모든 설정 네트워크 설정 초기화
admin
2018-11-08 11354
27 IPAD IPHONE X 아이패드 아이폰 전문가 리뷰 트러블슈팅 문제해결
admin
2018-11-08 7014
26 IPad Air와 iPad Pro의 차이점
admin
2018-11-08 7610
25 IPHONE 아이폰 푸쉬 노티피케이션 동작 안되는 현상 해결방법
admin
2018-11-08 7500
24 IOS12 업데이트 후 작동하지 않는 Apple iPhone X 알림 수정 방법
admin
2018-11-08 8067
23 아이폰 푸시 노티피케이션 온/오프
admin
2018-11-08 7362
22 Objective-C 입문
admin
2018-06-01 8071
21 프로토콜
admin
2018-06-01 7636
20 카테고리
admin
2018-06-01 7553
19 메소드의 포인터
admin
2018-06-01 7905
18 선택기
admin
2018-06-01 7512
17 클래스 형
admin
2018-06-01 7517
16 클래스 메소드
admin
2018-06-01 7549
15 가시성
admin
2018-06-01 7523
14 정적 형식
admin
2018-06-01 7418
13 오브젝트의 해방
admin
2018-06-01 15999
12 이니셜 라이저
admin
2018-06-01 7702
11 재정
admin
2018-06-01 12474
10 상속
admin
2018-06-01 7634
9 메소드
admin
2018-06-01 7897
8 클래스의 선언과 정의
admin
2018-06-01 8208
7 가져 오기
admin
2018-06-01 8037
6 Objective-C는?
admin
2018-06-01 8052
5 [프로그래밍]아이폰 SDK와 Xcode 통합 개발환경
admin
2018-06-01 8246
4 [프로그래밍]Objective-C 셀렉터(@selector)
admin
2018-06-01 8115
3 VMWare를 이용한 mac os를 설치방법
admin
2018-05-11 9383
2 mac OS 여러가지 맥 버젼 별 설명 구분 시에라 까지
admin
2018-05-11 15985