IOS10的電話攔截理念與android不一樣,基於隱私保護的理念IOS沒把對方號碼送給應用,因此需要反過來由app把需要識別或攔截的電話存入系統數據庫。這一功能通過Call Directory Extension模塊實現(具體操作請見https://blog.csdn.net/sinat_30336277/article/details/54944057,或者https://www.jianshu.com/p/e3d0acda8dda),通過在Blocking和Indentification兩個相關的方法中進行黑名單生成及識別號碼的生成。用戶在設置->電話->來電阻止與身份識別界面下開啟應用的該項功能時,Extension應用的beginRequestWithExtensionContext方法會被系統調用。通過在addAllBlockingPhoneNumbersToContext函數里實現了某些固話號碼段的屏蔽。這樣實現的屏蔽號碼,在設置界面下是看不到。
需要注意的問題:
1、電話號碼要加國別、區號、升序排列、唯一,xcode默認生成的代碼有問題,正確號碼格式應該如:+8618907311234、+8673122126000。可參見: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 CXCallDirectoryPhoneNumber allPhoneNumbers[] = { +8673122126000, +8673122129000, +8673182984000, +8673189520000, +8673189522000, +8673189526000, +8673189527000, +8673189587000 }; 2 NSUInteger count = (sizeof(allPhoneNumbers) / sizeof(CXCallDirectoryPhoneNumber)); 3 for (NSUInteger index = 0; index < count; index += 1) { 4 CXCallDirectoryPhoneNumber phoneNumber = allPhoneNumbers[index]; 5 for(int i=0;i<1000;i += 1){ 6 [context addBlockingEntryWithNextSequentialPhoneNumber:phoneNumber+i]; 7 } 8 }
每次通過設置來觸發號碼修改不方便,可以通過在宿主應用中主動觸發Extension來刷新。在宿主應用中合適的位置(更行了號碼數據后)調用下面的函數updateNumber,觸發Extension的CallDirectoryHandler類的beginRequestWithExtensionContext方法(context.isIncremental為true)。xcode的示例代碼會調用addOrRemoveIncrementalBlockingPhoneNumbersToContext和addOrRemoveIncrementalIdentificationPhoneNumbersToContext來更新號碼。其中"xxx.qrcode.phone"是Extention應用的Bundle Identifier
- (void)updateNumber{ CXCallDirectoryManager *manager = [CXCallDirectoryManager sharedInstance]; [manager reloadExtensionWithIdentifier:@"xxx.qrcode.phone" completionHandler:^(NSError * _Nullable error) { if (error == nil) { UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"更新成功" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; }else{ UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"更新失敗" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; } }]; }
此外,還有幾個功能沒嘗試:
1、檢查用戶授權。參見:https://blog.csdn.net/qq_26918391/article/details/52913028、https://blog.csdn.net/qq_30513483/article/details/52768699?locationNum=1
2、實時監聽來電。如:https://www.2cto.com/kf/201607/525336.html、https://blog.csdn.net/gf771115/article/details/46649115、https://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653578016&idx=2&sn=ae1474cbc3037e5c00e6da5c69cd8569&chksm=84b3b127b3c43831191d37ca0e86d2f2f7b97d180d8c0ccd6dedb9c4a9a9a8c0af909d28d558&scene=4#wechat_redirect
3、與宿主應用間數據共享(Extension與主應用是兩個應用,主應用的獲取的數據如果需要傳遞到extension,得用到appgroup)。如:https://blog.csdn.net/Rex_xing/article/details/78184598、https://www.jianshu.com/p/7f8472a97aa6
