热门频道

推荐频道

打开App
24
LVXIANGAN

iOS之来电阻止与身份识别实现 原创

2017-07-26 11:41:49

      为了屏蔽各种中介的电话骚扰,最近安装了腾讯手机管家,安装完成后,设置“骚扰拦截”功能时,App提示需要点击“设置--->电话--->来电阻止与身份识别--->勾选App提供的"黄页"、“电话识别”和“电话拦截”。



了解过苹果沙盒机制的朋友都知道,一般在App中要访问到其他 App/硬件(地理位置,相册,通讯录,话筒) 内容,会通过系统弹窗询问用户,必须要获取管理员许可才行,比如这样:



那么上面的“来电阻止和身份识别”功能又是什么东东呢?


CallKit.framework


苹果在iOS 10中为我们带来了callkit.framework,当我们语言通话显示系统界面时,它允许我们对来电号码进行识别、过滤、标记、阻止等操作。目前国内垃圾电话、骚扰电话、诈骗电话不胜其烦,针对iPhone全球第二大市场,苹果今次顺势而为推出开放接口,也算是人心所向。有兴趣的朋友可以通过官方文档说明了解callkit.framework


下面我们尝试来写一个demo,让自己App出现在电话“设置--->电话--->来电阻止与身份识别 列表中,实现来电过滤功能

1、新建一个iOS工程




2、完成后,新建target:点击"+"---> 选择iOS,Call Directory Extension, 输入名称如:CallFirewall,一路next,选择“Activate”






3、完成上面操作,可以看到在项目工程中,自动生成了下面几个文件。



4、打开文件 CallDirectoryHandler.h 和 CallDirectoryHandler.m,使用注意事项,请参照代码注释:

  1. //
  2. // CallDirectoryHandler.h
  3. // CallFirewall
  4. //
  5. // Created by lvxiangan on 26/07/2017.
  6. // Copyright © 2017 lvxiangan. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #import <CallKit/CallKit.h>
  10. @interface CallDirectoryHandler : CXCallDirectoryProvider
  11. @end
  1. //
  2. // CallDirectoryHandler.m
  3. // CallFirewall
  4. //
  5. // Created by lvxiangan on 26/07/2017.
  6. // Copyright © 2017 lvxiangan. All rights reserved.
  7. //
  8. #import "CallDirectoryHandler.h"
  9. @interface CallDirectoryHandler () <CXCallDirectoryExtensionContextDelegate>
  10. @end
  11. @implementation CallDirectoryHandler
  12. // 请求前检查
  13. - (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context {
  14. context.delegate = self;
  15. if (![self addBlockingPhoneNumbersToContext:context]) {
  16. NSLog(@"Unable to add blocking phone numbers");
  17. NSError *error = [NSError errorWithDomain:@"CallDirectoryHandler" code:1 userInfo:nil];
  18. [context cancelRequestWithError:error];
  19. return;
  20. }
  21. if (![self addIdentificationPhoneNumbersToContext:context]) {
  22. NSLog(@"Unable to add identification phone numbers");
  23. NSError *error = [NSError errorWithDomain:@"CallDirectoryHandler" code:2 userInfo:nil];
  24. [context cancelRequestWithError:error];
  25. return;
  26. }
  27. [context completeRequestWithCompletionHandler:nil];
  28. }
  29. // 来电阻止
  30. - (BOOL)addBlockingPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context {
  31. // Retrieve phone numbers to block from data store. For optimal performance and memory usage when there are many phone numbers,
  32. // 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.
  33. //
  34. // Numbers must be provided in numerically ascending order.
  35. CXCallDirectoryPhoneNumber phoneNumbers[] = { 14085555555, 18005555555 };
  36. NSUInteger count = (sizeof(phoneNumbers) / sizeof(CXCallDirectoryPhoneNumber));
  37. for (NSUInteger index = 0; index < count; index += 1) {
  38. CXCallDirectoryPhoneNumber phoneNumber = phoneNumbers[index];
  39. [context addBlockingEntryWithNextSequentialPhoneNumber:phoneNumber];
  40. }
  41. return YES;
  42. }
  43. // 来电识别
  44. - (BOOL)addIdentificationPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context {
  45. // Retrieve phone numbers to identify and their identification labels from data store. For optimal performance and memory usage when there are many phone numbers,
  46. // 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.
  47. //
  48. // Numbers must be provided in numerically ascending order.
  49. CXCallDirectoryPhoneNumber phoneNumbers[] = { 18775555555, 18885555555 };
  50. NSArray<NSString *> *labels = @[ @"Telemarketer", @"Local business" ];
  51. NSUInteger count = (sizeof(phoneNumbers) / sizeof(CXCallDirectoryPhoneNumber));
  52. for (NSUInteger i = 0; i < count; i += 1) {
  53. CXCallDirectoryPhoneNumber phoneNumber = phoneNumbers[i];
  54. NSString *label = labels[i];
  55. [context addIdentificationEntryWithNextSequentialPhoneNumber:phoneNumber label:label];
  56. }
  57. return YES;
  58. }
  59. #pragma mark - CXCallDirectoryExtensionContextDelegate
  60. // 添加黑名单或识别来电失败处理
  61. - (void)requestFailedForExtensionContext:(CXCallDirectoryExtensionContext *)extensionContext withError:(NSError *)error {
  62. // An error occurred while adding blocking or identification entries, check the NSError for details.
  63. // For Call Directory error codes, see the CXErrorCodeCallDirectoryManagerError enum in <CallKit/CXError.h>.
  64. //
  65. // This may be used to store the error details in a location accessible by the extension's containing app, so that the
  66. // app may be notified about errors which occured while loading data even if the request to load data was initiated by
  67. // the user in Settings instead of via the app itself.
  68. }
  69. @end





同理,参照腾讯手机管家的做法,我们建多几个target,就会在“来电阻止与身份识别”中有多个选项。




这样,我们就可以根据自定义target用途,来编写不同功能的代码了。