概述
該CallKit框架提供VoIP功能,以及呼叫限制和識別的編程訪問。
VoIP功能
應用程序可以使用CallKit接聽來電欢摄,并使用本地電話用戶界面呼出。
接收來電
要接收來電笋粟,一個應用程序創(chuàng)建一個CXProvider對象怀挠,并將其存儲在全局訪問。一個應用程序報告給provider一個來電以響應外部通知害捕,如VoIP的推送通知绿淋。
這部分內(nèi)容看起來不太容易理解,最好下載官方提供的源碼尝盼,最好再看一看官方視頻吞滞。
另外,源碼只有Swift版沒有OC版盾沫。
源碼下載地址
注意
有關VoIP的推送通知和PushKit的更多信息裁赠,請參閱IP語音(VoIP)的最佳實踐。
使用由外部通知中提供的信息赴精,應用程序創(chuàng)建的UUID和CXCallUpdate對象唯一標識呼叫佩捞,主叫方,并把它們傳遞給使用 reportNewIncomingCallWithUUID:update:completion:
方法蕾哟。
一旦電話接通后一忱,供應商代表發(fā)送provider:performStartCallAction:
在實現(xiàn)中,delegate 負責配置AVAudioSession并且當操作完成的時候會調(diào)fulfill
方法谭确。
同樣的帘营,這段文字的說明也最好配合源碼來解讀。
外呼
用戶可以以以下任何一個方式中在VoIP應用中發(fā)起外呼:
- 執(zhí)行應用程序內(nèi)的交互
- 打開支持自定義URL方案的鏈接
- 啟動Siri的使用VoIP通話
要撥出電話琼富,一個應用程序從CXCallController對象請求CXStartCallAction仪吧。的動作是由一個UUID來唯一標識呼叫和CXHandle對象來指定收件人。
呼叫限制 & 驗證
應用程序可以創(chuàng)建一個呼叫目錄擴展鞠眉,根據(jù)手機號碼去驗證或限制來電薯鼠。
注意
在電話號碼簿電話分機號碼由CXCallDirectoryPhoneNumber類型代表择诈,包括后面的數(shù)字序列的國碼(如1北美或86中國)。
如何創(chuàng)建Call Directory Extension?
所有創(chuàng)建Extension的方式都是一樣的出皇,詳見我的另一篇文章羞芍。
iOS Action Extension開發(fā)教程,實現(xiàn)跨APP的數(shù)據(jù)共享
使用
所有的來電驗證和限制都在beginRequestWithExtensionContext:
方法的實現(xiàn)中郊艘。
beginRequestWithExtensionContext
方法在CallDirectoryHandler
類中荷科,其實CallDirectoryHandler
是CXCallDirectoryProvider
的子類,在你創(chuàng)建完Call Directory Extension后纱注,在擴展文件中可以看到系統(tǒng)生成的文件畏浆,在這個文件中就可以看到該方法。
識別來電者
當一個手機接收來電時狞贱,系統(tǒng)會在第一時間參考用戶的聯(lián)系人目錄去尋找匹配的手機號碼刻获。如果沒有匹配的,系統(tǒng)會到你應用程序的Call Directory Extension中去尋找匹配的手機號碼瞎嬉,這有益于保持用戶的聯(lián)系人信息和系統(tǒng)的聯(lián)系人信息相對獨立蝎毡,比如一個社交網(wǎng)絡,或者驗證由應用程序發(fā)起的來電氧枣,比如客戶服務支持或交付通知沐兵。
舉個例子,考慮某個用戶誰是Jane的社交網(wǎng)絡app的好友便监,但是Jane的聯(lián)系人中沒有這個人手機號碼扎谎。于是這個社交網(wǎng)絡APP可以使用Call Directory Extension,下載并添加所有該用戶朋友的手機號碼烧董。正因為如此簿透,當該用戶接受到一個來自于Jane的來電時,系統(tǒng)會顯示一些像"(App Name) Caller ID: Jane Applesedd"而不是像"Unknown Caller"解藻。
若要提供有關來電者身份信息,你可以在beginRequestWithExtensionContext:
的方法實現(xiàn)中使用addIdentificationEntryWithNextSequentialPhoneNumber:label:
方法葡盗。
代碼如下:
@interface CallDirectoryHandler () <CXCallDirectoryExtensionContextDelegate>
@end
@implementation CallDirectoryHandler
//識別和攔截通過該方法設置
- (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context {
context.delegate = self;
if (![self addBlockingPhoneNumbersToContext:context]) {
NSLog(@"Unable to add blocking phone numbers");
NSError *error = [NSError errorWithDomain:@"CallDirectoryHandler" code:1 userInfo:nil];
[context cancelRequestWithError:error];
return;
}
if (![self addIdentificationPhoneNumbersToContext:context]) {
NSLog(@"Unable to add identification phone numbers");
NSError *error = [NSError errorWithDomain:@"CallDirectoryHandler" code:2 userInfo:nil];
[context cancelRequestWithError:error];
return;
}
[context completeRequestWithCompletionHandler:nil];
}
//來電驗證身份
- (BOOL)addIdentificationPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context {
// Retrieve phone numbers to identify and their identification labels from data store. For optimal performance and memory usage when there are many phone numbers,
// consider only loading a subset of numbers at a given time and using autorelease pool(s) to release objects allocated during each batch of numbers which are loaded.
//
// Numbers must be provided in numerically ascending order.
CXCallDirectoryPhoneNumber phoneNumbers[] = { 18775555555, 18885555555 };
NSArray<NSString *> *labels = @[ @"Telemarketer", @"Local business" ];
NSUInteger count = (sizeof(phoneNumbers) / sizeof(CXCallDirectoryPhoneNumber));
for (NSUInteger i = 0; i < count; i += 1) {
CXCallDirectoryPhoneNumber phoneNumber = phoneNumbers[i];
NSString *label = labels[i];
//這里可以檢查來電者的身份信息
[context addIdentificationEntryWithNextSequentialPhoneNumber:phoneNumber label:label];
}
return YES;
}
@end
beginRequestWithExtensionContext:
這個方法只有當系統(tǒng)啟動App Extension時才會被調(diào)用螟左,而不是每次單獨來電時調(diào)用,你必須一次性指定全部的“呼叫標識信息”觅够。
阻止來電
當一個手機接收到來電時胶背,系統(tǒng)首先會參考用戶的黑名單以確定哪個呼叫時應該被阻止。如果這個手機號碼不在用戶或者系統(tǒng)定義的黑名單中喘先,系統(tǒng)就會參考應用程序的Call Direcotry Extension去尋找匹配的黑名單號碼钳吟。這樣做有益于應用程序,允許用戶依據(jù)一套準則阻止任意的號碼窘拯。
去阻止特定手機號碼的來電红且,你你可以在beginRequestWithExtensionContext:
的方法實現(xiàn)中使用addBlockingEntryWithNextSequentialPhoneNumber::
方法坝茎。
代碼如下:
@interface CallDirectoryHandler () <CXCallDirectoryExtensionContextDelegate>
@end
@implementation CallDirectoryHandler
//識別和攔截通過該方法設置
- (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context {
context.delegate = self;
if (![self addBlockingPhoneNumbersToContext:context]) {
NSLog(@"Unable to add blocking phone numbers");
NSError *error = [NSError errorWithDomain:@"CallDirectoryHandler" code:1 userInfo:nil];
[context cancelRequestWithError:error];
return;
}
if (![self addIdentificationPhoneNumbersToContext:context]) {
NSLog(@"Unable to add identification phone numbers");
NSError *error = [NSError errorWithDomain:@"CallDirectoryHandler" code:2 userInfo:nil];
[context cancelRequestWithError:error];
return;
}
[context completeRequestWithCompletionHandler:nil];
}
//來電攔截
- (BOOL)addBlockingPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context {
// Retrieve phone numbers to block from data store. For optimal performance and memory usage when there are many phone numbers,
// consider only loading a subset of numbers at a given time and using autorelease pool(s) to release objects allocated during each batch of numbers which are loaded.
//
// Numbers must be provided in numerically ascending order.
CXCallDirectoryPhoneNumber phoneNumbers[] = { 14085555555, 18005555555 };
NSUInteger count = (sizeof(phoneNumbers) / sizeof(CXCallDirectoryPhoneNumber));
for (NSUInteger index = 0; index < count; index += 1) {
CXCallDirectoryPhoneNumber phoneNumber = phoneNumbers[index];
[context addBlockingEntryWithNextSequentialPhoneNumber:phoneNumber];
}
return YES;
}
@end
總結
如果項目不使用VoIP,看 呼叫限制 & 驗證 模塊之后的內(nèi)容就可以了暇番。然后在擴展類的相應方法中配置各自的名單嗤放。
如果項目中使用VoIP,請繼續(xù)看其他資料壁酬。
其他資料詳見
本文翻譯自Call Directory Extension Apple官方文檔
Enhancing VoIP Apps with CallKit