我的收藏藤原とうふ店(自家用)

iOS开发 - 来电识别和骚扰拦截

2022-05-16  本文已影响0人  那月无痕

原作者:https://www.jianshu.com/p/9836bff5a0e0

需要注意的问题:

1、电话号码要加国别、区号、升序排列、唯一,xcode默认生成的代码有问题,正确号码格式应该如:+8618907311234、+8673122126000。
1.1 另外400号码属于虚拟号码, 放在PhoneNumber中的正确格式是,+86400xxxxxxx, 无区号.
1.2 目前好像只能全量更新数据,不能增量更新,效率比较低.
1.3 最大数量在100万到200万之间,原因可能是超时无效.
1.4 排序是指处理完号码, 添加国家码后的表单进行升序排列.
可参见:https://blog.csdn.net/Rex_xing/article/details/78184598

2、系统电话簿优先级高于此方法设置的识别号码,也就是同时有设置的情况下只会显示号码簿里面的姓名。

3、黑名单拦截的来电不会在历史通话中显示。

4、在按需更新号码的时候要注意如果插入了重复号码会失败(Extention模块中系统不会返回错误信息,只是在宿主进程的reloadExtensionWithIdentifier时返回错误),因此采取全量更新的办法。每次先调用removeAllIdentificationEntries,然后再插入。当然也可以在每个号码插入前先调用removeIdentificationEntryWithPhoneNumber。

5、使用sqlite3的时候,号码字段一定要记得采用bigint,我就是因为采用了int类型导致插入号码时好时坏。

6、号码的别名一定不要太长。之前犯糊涂,别名字段设置了个varchar(128),库中有大量的长度为三四十个字符的记录,结果总是报更新失败,又不知道原因。由于获取不到有效的调试信息,百思不得其解,熬了好几个夜才在一次偶然的情况下看到内存不足的信息,才慢慢发现这个问题。

7、另外,有个奇怪的、一直未能找到原因的现象:由于采用sqlite的数据库文件作为本地资源(懒得从网络更新),但插入该文件到工程中后很诡异的出现Extention不能运行,时好时坏,坏的时候连重装app都不灵。不过在后期使用中没再碰到过该问题。

  1. 苹果默认生成的代码, 号码格式是错误的, 请按照本文的要求生成.

一、创建一个新的target

image

选择Call Directory Extension

image

选中主程序YSCallDemo这个target,找到App Group打开
勾选一个开发者team

image

选中用于号码识别的target同样找到App Group打开
勾选一个开发者team

image

两个target都选中后会多了一个YSCallDemo.entitlements

image

有时候会出现文件找不到的情况,可以在target-->build phases里手动添加编译文件

image

二、准备号码库,更新号码识别库就可以号码识别了

//这里是采用realm数据库来存储号码,路径选择共享路径即可
- (void)realmConfiguation {

            NSURL *url = [[[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.yasha.group"] URLByAppendingPathComponent:@"IDCall"] URLByAppendingPathExtension:@"realm"];
            [[NSFileManager defaultManager] removeItemAtURL:url error:nil];
    // APP Group 宿主程序数据库共享
    RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
    configuration.fileURL = [[[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.yasha.group"] URLByAppendingPathComponent:@"IDCall"] URLByAppendingPathExtension:@"realm"];
    [RLMRealmConfiguration setDefaultConfiguration:configuration];
    NSLog(@"数据库地址:%@", [RLMRealmConfiguration defaultConfiguration].fileURL);
    // 数据迁移
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];

}

更新号码识别库

//调用这个方法就可以将数据写入到号码识别库
CXCallDirectoryManager *manager = [CXCallDirectoryManager sharedInstance];

    [manager reloadExtensionWithIdentifier:@"yasuo.YSCallDemo.CallExtension" completionHandler:^(NSError * _Nullable error) {
}

调用更新后程序自动执行CallDirectoryHandler.m的方法

- (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context {
    context.delegate = self;
    [self addOrRemoveIncrementalIdentificationPhoneNumbersToContext:context];
//这里直接调用号码增加和移除的方法

    [context completeRequestWithCompletionHandler:nil];
}

调用这个方法数据写入

(void)addOrRemoveIncrementalIdentificationPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context {

    //配置数据库
    RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
    configuration.fileURL = [[[[NSFileManager defaultManager]
                               containerURLForSecurityApplicationGroupIdentifier:@"group.com.yasha.group"] URLByAppendingPathComponent:@"IDCall"] URLByAppendingPathExtension:@"realm"];
    [RLMRealmConfiguration setDefaultConfiguration:configuration];
    RLMRealm *realm = [RLMRealm defaultRealm];

    [realm beginWriteTransaction];
    RLMResults *results = [[YSContactModel allObjects] sortedResultsUsingKeyPath:@"phone" ascending:YES];
    [realm commitWriteTransaction];
    if (results.count != 0) {
        [context removeAllIdentificationEntries];

        NSMutableArray *allPhoneNumbersArray = [NSMutableArray array];
        NSMutableArray *labelsArray = [NSMutableArray array];
        for (YSContactModel *model in results) {
            [allPhoneNumbersArray addObject:[NSString stringWithFormat:@"%zd",model.phone ]];
            [labelsArray addObject:model.name];
        }

        for (NSUInteger i = 0; i < allPhoneNumbersArray.count; i ++) {
            CXCallDirectoryPhoneNumber phoneNumber = [allPhoneNumbersArray[i] longLongValue];
            NSString *label = labelsArray[I];
            [context addIdentificationEntryWithNextSequentialPhoneNumber:phoneNumber label:label];
        }
    }
}

这里就可以实现号码识别了

三、常见错误

号码存入时需要加国家区号,要升序排列
比如com.apple.CallKit.error.calldirectorymanager Code=4 表示数据重复
授权没打开也会报,Domain=com.apple.CallKit.error.calldirectorymanager Code=6
官方
网上找的swift版本的报错枚举

public enum Code : Int {
        public typealias _ErrorType = CXErrorCodeCallDirectoryManagerError

        case unknown

        case noExtensionFound

        case loadingInterrupted

        case entriesOutOfOrder

        case duplicateEntries

        case maximumEntriesExceeded

        case extensionDisabled

        @available(iOS 10.3, *)
        case currentlyLoading

        @available(iOS 11.0, *)
        case unexpectedIncrementalRemoval
    }

三、通过cocoapod进来的第三方和让共享target可以使用的方法

第一步:
PROJECT --info --configurations,将对应的Debug和Release 设置成pods-你的Xcode项目名.debug和pods-你的Xcode项目名.release。
这些是在下图中可以选择的,不需要手动填写。!

image

31A227EF2AD6879836E434A72CC3F038.jpg

第二步:

TARGETS--Build Phases --Link Binary With Libraries,将pods的.a文件引入

image

作者:白河三
链接:https://www.jianshu.com/p/9836bff5a0e0
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

上一篇下一篇

猜你喜欢

热点阅读