版本記錄
版本號(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)行通信寻定。
-
- 代表電話provider的對(duì)象
-
- 由電話服務(wù)提供者對(duì)象調(diào)用的一組方法。
-
- 提供者對(duì)象的配置封裝精耐。
2. Incoming Calls
當(dāng)PushKit通知指示來(lái)電時(shí)狼速,您將生成適當(dāng)?shù)牟僮鳌?CallKit通過(guò)呈現(xiàn)用于應(yīng)答呼叫的系統(tǒng)界面來(lái)處理該操作。
-
- 接聽(tīng)來(lái)電的行為的封裝卦停。
-
- 封裝有關(guān)呼叫的新的和已更改的信息向胡。
3. Outgoing Calls
呼叫控制器開(kāi)始傳出呼叫,并處理后續(xù)與您的provider代理交互惊完。
-
- 用于與呼叫進(jìn)行交互和觀察的程序化界面僵芹。
-
- 包含零個(gè)或多個(gè)要由呼叫控制器執(zhí)行的操作對(duì)象的對(duì)象。
-
- 發(fā)起呼叫行為的封裝小槐。
4. Call-Related Actions
回應(yīng)CallKit報(bào)告的操作拇派。
-
- 一個(gè)抽象類,為表示電話操作的對(duì)象聲明一個(gè)編程接口凿跳。
-
- 表示與呼叫對(duì)象關(guān)聯(lián)的電話操作的對(duì)象的編程接口件豌。
-
- 封閉了結(jié)束通話的行為。
-
- 播放雙音多頻(DTMF)序列的封裝控嗜。
-
- 分組或取消分組呼叫的封裝茧彤。
-
- 將通話保持或?qū)⑼ㄔ捯瞥男袨榈姆庋b。
-
- 封閉靜音或取消靜音的行為疆栏。
5. Call Information
獲取有關(guān)通話的信息曾掂,并在通話狀態(tài)發(fā)生變化時(shí)收到通知。
-
- 電話呼叫承边。
-
- 用于管理活動(dòng)呼叫列表并監(jiān)視呼叫更改的對(duì)象的編程接口遭殉。
-
- 呼叫改變狀態(tài)時(shí)由呼叫觀察者對(duì)象調(diào)用的方法的集合。
-
- 可以到達(dá)呼叫接收方的方式博助,例如電話號(hào)碼或電子郵件地址险污。
6. Caller ID
使用呼叫目錄應(yīng)用程序擴(kuò)展可阻止呼叫并提供來(lái)電顯示信息。
-
- 主機(jī)應(yīng)用程序的Call Directory應(yīng)用程序擴(kuò)展的主要目標(biāo)富岳。
-
CXCallDirectoryExtensionContext
- 用于添加識(shí)別和阻止條目到Call Directory應(yīng)用程序擴(kuò)展的編程接口蛔糯。
-
CXCallDirectoryExtensionContextDelegate
- 請(qǐng)求失敗時(shí)由Call Directory擴(kuò)展上下文對(duì)象調(diào)用的一組方法。
-
- 管理Call Directory應(yīng)用程序擴(kuò)展的對(duì)象的編程接口窖式。
參考文章
- iOS Call Kit for VOIP
- XAMARIN Introduction to CallKit
- WWDC16 Session 230 (Enhancing VoIP Apps with CallKit)
- Apple Call Kit Speakerbox Demo
- PushKit Practice
后記
本篇已結(jié)束蚁飒,后面更精彩~~~~