CallKit框架詳細(xì)解析(一) —— 基本概覽(一)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.02.01

前言

蘋(píng)果 iOS 10 新發(fā)布了一個(gè)新的框架CallKit赞警,使第三方VOIP類型語(yǔ)音通話類APP有了更好的展現(xiàn)方式和用戶體驗(yàn)的提升,接下來(lái)這幾篇我們就一起看一下這個(gè)框架澄成。

Overview

先看一下該框架的基本信息窝爪。

CallKit框架可以顯示App的VoIP服務(wù)的系統(tǒng)調(diào)用UI亿笤,并協(xié)調(diào)其他應(yīng)用程序和系統(tǒng)與您的呼叫服務(wù)硕盹。

CallKit可讓您將呼叫服務(wù)與系統(tǒng)上其他與呼叫相關(guān)的應(yīng)用程序集成在一起。 CallKit提供了呼叫接口祈坠,您可以使用VoIP服務(wù)處理后端通信害碾。 對(duì)于傳入和傳出呼叫,CallKit顯示與電話應(yīng)用程序相同的接口颁虐,為您的應(yīng)用程序提供更原生的外觀和感覺(jué)蛮原。 CallKit可以正確響應(yīng)系統(tǒng)級(jí)別的行為,例如Do Not Disturb另绩。

除了處理呼叫之外,您還可以提供Call Directory應(yīng)用程序擴(kuò)展程序花嘶,以提供來(lái)電顯示信息以及與您的服務(wù)關(guān)聯(lián)的黑名單列表笋籽。

在蘋(píng)果官方WWDC16 Enhancing VoIP Apps with CallKit(Session 230)中,蘋(píng)果的工程師為我們展示了集成Call Kit后的VOIP 通話APP的效果椭员,例如在iPhone鎖屏狀態(tài)下APP來(lái)電時(shí)车海,通過(guò)Call Kit可以像iOS原生電話來(lái)電一樣展現(xiàn)全屏的來(lái)電及接聽(tīng)界面,VOIP APP與系統(tǒng)Call有著相同的通話優(yōu)先級(jí)別,而且在通訊錄中的拔號(hào)記錄侍芝,Siri喚起研铆,勿擾模式等都有著很好的支持。

下面看一下原生APP州叠、第三方APP在CallKit框架下的關(guān)系棵红,在需要的時(shí)刻,原生或者第三方APP通過(guò)Call Kit提供的API向系統(tǒng)請(qǐng)求諸如來(lái)電咧栗、拔出等展現(xiàn)服務(wù)逆甜,由Call Service統(tǒng)一安排調(diào)度這些請(qǐng)求以達(dá)成統(tǒng)一的交互響應(yīng)。

下面看一下框架的基本結(jié)構(gòu)致板。


Receiving an Incoming Call - 接收來(lái)電

要配置您的應(yīng)用程序以接收來(lái)電交煞,請(qǐng)首先創(chuàng)建一個(gè)CXProvider對(duì)象并將其存儲(chǔ)以供全局訪問(wèn)。 應(yīng)用程序會(huì)向provider報(bào)告來(lái)電斟或,以響應(yīng)外部通知素征,例如由PushKit生成的VoIP推送通知。

// Listing 1 Receiving a VoIP–related push notification

// MARK: PKPushRegistryDelegate
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
    // report new incoming call
}

注意:有關(guān)VoIP推送通知和PushKit的更多信息萝挤,請(qǐng)參閱 Voice Over IP (VoIP) Best Practices御毅。

使用外部通知提供的信息,應(yīng)用程序?qū)?chuàng)建一個(gè)UUID和一個(gè)CXCallUpdate對(duì)象來(lái)唯一標(biāo)識(shí)調(diào)用和調(diào)用者平斩,并使用 reportNewIncomingCallWithUUID:update:completion:方法將它們傳遞給provider亚享。

// Listing 2 Handling an incoming call

if let uuidString = payload.dictionaryPayload["UUID"] as? String,
    let identifier = payload.dictionaryPayload["identifier"] as? String,
    let uuid = UUID(uuidString: uuidString)
{
    let update = CXCallUpdate()    
    update.callerIdentifier = identifier
    
    provider.reportNewIncomingCall(with: uuid, update: update) { error in
        // …
    }
}

在呼叫連接之后,系統(tǒng)調(diào)用provider委托provider:performStartCallAction:方法绘面。 在你的實(shí)現(xiàn)中欺税,委托負(fù)責(zé)配置一個(gè)AVAudioSession,并在完成時(shí)調(diào)用fulfill揭璃。

// Listing 3 Initiating the audio for a call

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    // configure audio session
    action.fulfill()
}

Making Outgoing Calls - 打出電話

用戶可以通過(guò)以下任何方式使用VoIP應(yīng)用發(fā)起呼叫:

  • 在應(yīng)用程序內(nèi)執(zhí)行交互
  • 使用受支持的自定義網(wǎng)址方案打開(kāi)鏈接
  • 使用Siri啟動(dòng)VoIP呼叫

要發(fā)出呼叫晚凿,應(yīng)用程序?qū)钠?a target="_blank" rel="nofollow">CXCallController對(duì)象請(qǐng)求一個(gè)CXStartCallAction對(duì)象。 該操作由唯一標(biāo)識(shí)呼叫的UUID和指定收件人的CXHandle對(duì)象組成瘦馍。

// Listing 4 Starting an outgoing call

let uuid = UUID()
let handle = CXHandle(type: .emailAddress, value: "jappleseed@apple.com")
 
let startCallAction = CXStartCallAction(call: uuid)
startCallAction.destination = handle
 
let transaction = CXTransaction(action: startCallAction)
callController.request(transaction) { error in
    if let error = error {
        print("Error requesting transaction: \(error)")
    } else {
        print("Requested transaction successfully")
    }
}

注意:有關(guān)注冊(cè)和處理URL的更多信息歼秽,請(qǐng)參閱 Using URL Schemes to Communicate with Apps。有關(guān)使用Siri啟動(dòng)呼叫的更多信息情组,請(qǐng)參閱INStartAudioCallIntentHandling協(xié)議燥筷。

收件人應(yīng)答呼叫后,系統(tǒng)會(huì)調(diào)用provider代理 provider:performStartCallAction:方法院崇。 在你實(shí)現(xiàn)這個(gè)方法的時(shí)候肆氓,配置一個(gè)AVAudioSession,并在完成時(shí)調(diào)用action對(duì)象的fulfill方法底瓣。

// Listing 5 Initiating the call

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    // configure audio session
    action.fulfill()
}

注意:下載Speakerbox: Using CallKit to create a VoIP app程序示例代碼項(xiàng)目谢揪,該示例演示如何使用CallKit框架創(chuàng)建VoIP應(yīng)用程序。


Call Blocking and Identification - 呼叫阻止和識(shí)別

應(yīng)用程序可以創(chuàng)建一個(gè)Call Directory應(yīng)用程序擴(kuò)展,以通過(guò)電話號(hào)碼識(shí)別和阻止來(lái)電者拨扶。

Call Directory擴(kuò)展中的電話號(hào)碼由CXCallDirectoryPhoneNumber類型表示凳鬓,由國(guó)家代碼(如北美的1或中國(guó)的86)組成,后跟數(shù)字序列患民。

Creating a Call Directory App Extension - 創(chuàng)建一個(gè)Call Directory程序擴(kuò)展

您可以通過(guò)添加一個(gè)新的項(xiàng)目目標(biāo)并選擇應(yīng)用程序擴(kuò)展下的Call Directory擴(kuò)展模板來(lái)為您的應(yīng)用程序創(chuàng)建一個(gè)Call Directory擴(kuò)展缩举。

您在Call Directory擴(kuò)展的CXCallDirectoryProvider子類的beginRequestWithExtensionContext:方法的實(shí)現(xiàn)中設(shè)置了傳入呼叫的標(biāo)識(shí)和阻止。 系統(tǒng)啟動(dòng)應(yīng)用擴(kuò)展程序時(shí)調(diào)用此方法酒奶。

有關(guān)應(yīng)用擴(kuò)展程序的更多信息蚁孔,請(qǐng)參閱 App Extension Programming Guide

Identifying Incoming Callers - 識(shí)別來(lái)電

當(dāng)電話收到來(lái)電時(shí)惋嚎,系統(tǒng)首先咨詢用戶的聯(lián)系人以找到匹配的電話號(hào)碼杠氢。如果找不到匹配項(xiàng),則系統(tǒng)會(huì)查詢您的應(yīng)用程序的呼叫目錄分機(jī)以查找匹配的條目以識(shí)別電話號(hào)碼另伍。這對(duì)于維護(hù)與系統(tǒng)聯(lián)系人分離的用戶的聯(lián)系人列表(例如社交網(wǎng)絡(luò))或者用于識(shí)別可以從應(yīng)用內(nèi)發(fā)起的來(lái)話呼叫的應(yīng)用是有用的鼻百,諸如用于客戶服務(wù)支持或者遞送通知。

例如摆尝,考慮在社交網(wǎng)絡(luò)應(yīng)用程序中與Jane交朋友的用戶温艇,但是他們的聯(lián)系人中沒(méi)有她的電話號(hào)碼。社交網(wǎng)絡(luò)應(yīng)用程序具有呼叫目錄應(yīng)用程序擴(kuò)展堕汞,下載并添加所有用戶的朋友的電話號(hào)碼勺爱。因此,當(dāng)用戶從Jane收到來(lái)電時(shí)讯检,系統(tǒng)會(huì)顯示“(App Name)Caller ID:Jane Appleseed”琐鲁,而不是“Unknown Caller”

要提供有關(guān)傳入調(diào)用者的標(biāo)識(shí)信息人灼,可以在beginRequestWithExtensionContext:的實(shí)現(xiàn)中使用 addIdentificationEntryWithNextSequentialPhoneNumber:label:方法围段。

// Listing 6

@interface CustomCallDirectoryProvider: CXCallDirectoryProvider
@end
 
@implementation CustomCallDirectoryProvider
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
    NSDictionary<NSNumber *, NSString *> *labelsKeyedByPhoneNumber = @{ … };
    for (NSNumber *phoneNumber in [labelsKeyedByPhoneNumber.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
       NSString *label = labelsKeyedByPhoneNumber[phoneNumber];
       [context addIdentificationEntryWithNextSequentialPhoneNumber:(CXCallDirectoryPhoneNumber)[phoneNumber unsignedLongLongValue] label:label];
    }
 
    [context completeRequestWithCompletionHandler:nil];
}
@end

由于此方法僅在系統(tǒng)啟動(dòng)應(yīng)用程序擴(kuò)展而不是針對(duì)每個(gè)單獨(dú)呼叫時(shí)調(diào)用,因此您必須一次指定呼叫標(biāo)識(shí)信息投放;例如奈泪,您不能向Web服務(wù)請(qǐng)求查找有關(guān)來(lái)電的信息。

Blocking Incoming Calls - 阻止來(lái)電

當(dāng)電話收到來(lái)電時(shí)灸芳,系統(tǒng)首先查詢用戶的阻止列表以確定是否應(yīng)阻止呼叫涝桅。 如果電話號(hào)碼不在用戶或系統(tǒng)定義的阻止列表中,則系統(tǒng)會(huì)查詢您的應(yīng)用程序的呼叫目錄擴(kuò)展以查找匹配的阻止號(hào)碼烙样。 例如苹支,這對(duì)于維護(hù)已知律師的數(shù)據(jù)庫(kù)或允許用戶阻止符合一組標(biāo)準(zhǔn)的任何數(shù)字的應(yīng)用程序很有用。

要阻止特定電話號(hào)碼的來(lái)電误阻,可以在beginRequestWithExtensionContext:的實(shí)現(xiàn)中使用 addBlockingEntryWithNextSequentialPhoneNumber:方法。

注意:您可以指定您的呼叫目錄應(yīng)用程序擴(kuò)展在其beginRequestWithExtensionContext:的實(shí)現(xiàn)中添加標(biāo)識(shí)和/或阻止電話號(hào)碼。

// Listing 7

@interface CustomCallDirectoryProvider: CXCallDirectoryProvider
@end
 
@implementation CustomCallDirectoryProvider
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
    NSArray<NSNumber *> *blockedPhoneNumbers.sorted = @[ … ];
     for (NSNumber *phoneNumber in [blockedPhoneNumbers.sorted sortedArrayUsingSelector:@selector(compare:)]) {
        [context addBlockingEntryWithNextSequentialPhoneNumber:(CXCallDirectoryPhoneNumber)[phoneNumber unsignedLongLongValue]];
     }
 
    [context completeRequestWithCompletionHandler:nil];
}
@end

Topics

1. First Steps

與通話相關(guān)的操作通過(guò)您的provider及其代理進(jìn)行路由究反,您可以使用與您的服務(wù)進(jìn)行通信寻定。

2. Incoming Calls

當(dāng)PushKit通知指示來(lái)電時(shí)狼速,您將生成適當(dāng)?shù)牟僮鳌?CallKit通過(guò)呈現(xiàn)用于應(yīng)答呼叫的系統(tǒng)界面來(lái)處理該操作。

  • CXAnswerCallAction

    • 接聽(tīng)來(lái)電的行為的封裝卦停。
  • CXCallUpdate

    • 封裝有關(guān)呼叫的新的和已更改的信息向胡。

3. Outgoing Calls

呼叫控制器開(kāi)始傳出呼叫,并處理后續(xù)與您的provider代理交互惊完。

  • CXCallController

    • 用于與呼叫進(jìn)行交互和觀察的程序化界面僵芹。
  • CXTransaction

    • 包含零個(gè)或多個(gè)要由呼叫控制器執(zhí)行的操作對(duì)象的對(duì)象。
  • CXStartCallAction

    • 發(fā)起呼叫行為的封裝小槐。

4. Call-Related Actions

回應(yīng)CallKit報(bào)告的操作拇派。

5. Call Information

獲取有關(guān)通話的信息曾掂,并在通話狀態(tài)發(fā)生變化時(shí)收到通知。

  • CXCall

    • 電話呼叫承边。
  • CXCallObserver

    • 用于管理活動(dòng)呼叫列表并監(jiān)視呼叫更改的對(duì)象的編程接口遭殉。
  • CXCallObserverDelegate

    • 呼叫改變狀態(tài)時(shí)由呼叫觀察者對(duì)象調(diào)用的方法的集合。
  • CXHandle

    • 可以到達(dá)呼叫接收方的方式博助,例如電話號(hào)碼或電子郵件地址险污。

6. Caller ID

使用呼叫目錄應(yīng)用程序擴(kuò)展可阻止呼叫并提供來(lái)電顯示信息。

參考文章

后記

本篇已結(jié)束蚁飒,后面更精彩~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市萝喘,隨后出現(xiàn)的幾起案子淮逻,更是在濱河造成了極大的恐慌琼懊,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爬早,死亡現(xiàn)場(chǎng)離奇詭異哼丈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)筛严,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)醉旦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人桨啃,你說(shuō)我怎么就攤上這事车胡。” “怎么了照瘾?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵匈棘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我网杆,道長(zhǎng)羹饰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任碳却,我火速辦了婚禮队秩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昼浦。我一直安慰自己馍资,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布关噪。 她就那樣靜靜地躺著鸟蟹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪使兔。 梳的紋絲不亂的頭發(fā)上建钥,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音虐沥,去河邊找鬼熊经。 笑死,一個(gè)胖子當(dāng)著我的面吹牛欲险,可吹牛的內(nèi)容都是我干的镐依。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼天试,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼槐壳!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起喜每,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤务唐,失蹤者是張志新(化名)和其女友劉穎雳攘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绍哎,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡来农,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了崇堰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涩咖,死狀恐怖海诲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情檩互,我是刑警寧澤特幔,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站闸昨,受9級(jí)特大地震影響蚯斯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饵较,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一拍嵌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧循诉,春花似錦横辆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至划纽,卻和暖如春脆侮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勇劣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工靖避, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芭毙。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓筋蓖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親退敦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子粘咖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容