callKit框架是ios10之后更新的一个框架,代替了原来的CoreTelephony.framework,使用CallKit可以实现电话的拦截
首先创建一个项目之后,创建一个target,选择Call Directory Extension,会创建一个extension
限制通话的三个方法已经实现但是需要修改,还要在主程序里面添加检测授权的方法和更新电话的代码
一、主程序的代码
检测是否授权,如果想要拦截某个电话,需要在设置界面,设置->电话->来电阻止与身份识别内打开授权,如果用户没有授权需要检测是否授权,可以每隔一段时间检测一下,如果没有授权就提醒一下。
注意ExtensionWithIdentifier这个参数是extension的bundle Identifier
-(void)checkPermissions { CXCallDirectoryManager *manager = [CXCallDirectoryManager sharedInstance]; // 获取权限状态 [manager getEnabledStatusForExtensionWithIdentifier:@"XXXXXX" completionHandler:^(CXCallDirectoryEnabledStatus enabledStatus, NSError * _Nullable error) { if (!error) { NSString *title = nil; if (enabledStatus == CXCallDirectoryEnabledStatusDisabled ) { title = @"未授权,请在设置->电话->来电阻止与身份识别内授权相关权限"; } } }]; }
给主程序添加代码,array是一个数组,里面存放着电话号码,利用NSUserDefaults把数组存放在app group,group的标识要和这里的一致
注意:另外需要注意的是数组必须是升序的,且必须以86开头的
注意:创建NSUserDefaults的时候有个参数是initWithSuiteName:这里要和后面的名称一致
NSUserDefaults * userDefaults = [[NSUserDefaults alloc]initWithSuiteName:@“XXXXXXXX"]; NSArray *sortedArray = [self.mPhoneNumberList sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { return [obj1 compare:obj2]; }]; [userDefaults setObject:sortedArray forKey:@"blackPhoneNum"]; [userDefaults synchronize]; [self checkPermissions]; [self updateData];
更新需要拦截的电话
-(void)updateData { CXCallDirectoryManager *manager = [CXCallDirectoryManager sharedInstance]; [manager reloadExtensionWithIdentifier:@“XXXXXXX" completionHandler:^(NSError * _Nullable error) { }]; }
二.extensiond的代码CallDirectoryHandler.m的方法实现
- (BOOL)addBlockingPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context { NSUserDefaults * userDefaults = [[NSUserDefaults alloc]initWithSuiteName:@“XXXXXXXX"]; NSArray * array = [userDefaults objectForKey:@"blackPhoneNum"]; [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSString * phoneStr = obj; int64_t phoneInt = [phoneStr integerValue]; CXCallDirectoryPhoneNumber number = phoneInt ; [context addBlockingEntryWithNextSequentialPhoneNumber:number]; }]; return YES; } - (BOOL)addIdentificationPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context { NSUserDefaults * userDefaults = [[NSUserDefaults alloc]initWithSuiteName:@“XXXXXX"]; NSArray * array = [userDefaults objectForKey:@"blackPhoneNum"]; [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSString * phoneStr = obj; int64_t phoneInt = [phoneStr integerValue]; CXCallDirectoryPhoneNumber number = phoneInt ; NSString *label = @"黑名单"; [context addIdentificationEntryWithNextSequentialPhoneNumber:number label:label]; }]; return YES; }
三.extension和程序之间是不能通讯的,需要利用app group来共享内存,
打开app group的方法,注意需要在主项目和extension都打开并选择同一个标识
TARGETS-->AppExtensionDemo-->Capabilities-->App Groups