先导入 Call Directory Extension
导入完成后,项目会多了一个文件夹
文件夹里的文件是CallKit 中 来电识别功能 添加黑名单功能
的实现模版
发现问题:
1,addBlockingPhoneNumbersToContext
、addIdentificationPhoneNumbersToContext
,这两个方法中 承载电话号的 数据类型是CXCallDirectoryPhoneNumber
, 这个类型是int64_t
类型,也是long long
类型,所以大家在做类型转换的时候需要注意。
2,如何动态修改CXCallDirectoryPhoneNumber数组和对应的标识数组?
因为宿主程序 和 扩展程序的数据 是隔离的,所以我们需要在宿主程序和 扩展程序都 开启 APP Groups
宿主程序和 扩展程序都设置完 APP Groups 就可以共享数据了。
在宿主程序中把从服务端请求回来的最新数据,写入到NSUserDefaults
中,我用来电识别功能举个🌰 ,如下:
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.testCallKit"];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:10];
[dict setObject:@"欧弟122" forKey:@"8615657138888"];
[userDefault setObject:dict forKey:@"PhoneNumbers"];
[userDefault synchronize];
上面代码 需要注意的是 :
1, SuiteName
的名字 是刚才设置 APP Groups 时创建的。
2,电话号码前面要加 区号 ,中国大陆的区号就是 86 或者 +86。
回到 CallDirectoryHandler.m
更改如下:
- (BOOL)addIdentificationPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context {
NSDictionary *dict = [[[NSUserDefaults alloc] initWithSuiteName:@"group.testCallKit"] objectForKey:@"PhoneNumbers"];
NSMutableDictionary *incomingTelegramInfo = @{}.mutableCopy;
[dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
incomingTelegramInfo[@([key longLongValue])] = obj;
}];
for (NSNumber *phoneNumber in [incomingTelegramInfo.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
NSString *label = incomingTelegramInfo[phoneNumber];
[context addIdentificationEntryWithNextSequentialPhoneNumber:(CXCallDirectoryPhoneNumber)[phoneNumber unsignedLongLongValue] label:label];
}
return YES;
}
那么如何维护号码库呢?
经调研发现,目前非越狱手机没有 获取来电号码 的权限,所以就不能用 单个来电号码 去云端数据库比对处理,只能通过第三方应用 把号码数据库写入到手机本地,当来电时 系统自动去和本地号码库比对 并做出身份显示。
机制如下:
我也咨询了做安卓的童鞋,如何在来电时触发第三方应用,他提供了 保活进程 的思路。我这里就不过多阐述了。可以参考Android来电号码获取代码
iOS 参考:
官方文档
iOS关于系统电话、短信的调用