iOS反騷擾電話-CallKit

iOS10增加了識別騷擾電話的API玖瘸,有三款主流的軟件已經(jīng)實(shí)現(xiàn)秸讹。也有一些報(bào)道分析 前幾天查了查資料,動手寫了一個(gè)Demo.

原理

電話號碼是用Call Directory extension事先存在系統(tǒng)里的雅倒,當(dāng)來電時(shí)璃诀,系統(tǒng)會查詢存儲的數(shù)據(jù), 根據(jù)號碼綁定的label,決定直接屏蔽還是顯示來電蔑匣。

iOS-CallKit.png
When using CallKit's Call Blocking & Identification feature (new in iOS 
10), phone numbers to be blocked or identified are loaded by your app's 
Call Directory extension prior to an incoming call and the phone numbers 
are stored by the system. Then, when an incoming call arrives, this stored 
data is consulted by the system and an incoming call may either be 
blocked or identified in the incoming call UI with the label provided.
For privacy and performance reasons, Call Directory app extensions are 
not launched when incoming calls arrive and an app extension cannot 
retrieve the phone number for an incoming call

http://stackoverflow.com/questions/38098036/how-to-get-the-incoming-call-number-by-using-callkit
https://www.zhihu.com/question/47542405

步驟

1 . 新建一個(gè)工程劣欢,New 一個(gè) Target,選Call Directory Extension ,會自動生成模版代碼裁良。

  override func beginRequest(with context: CXCallDirectoryExtensionContext) {
        context.delegate = self

        do {
            try addBlockingPhoneNumbers(to: context)
        } catch {
            NSLog("Unable to add blocking phone numbers")
            let error = NSError(domain: "CallDirectoryHandler", code: 1, userInfo: nil)
            context.cancelRequest(withError: error)
            return
        }

        do {
            try addIdentificationPhoneNumbers(to: context)
        } catch {
            NSLog("Unable to add identification phone numbers")
            let error = NSError(domain: "CallDirectoryHandler", code: 2, userInfo: nil)
            context.cancelRequest(withError: error)
            return
        }

        NSLog("beginRequest context ", context);
        context.completeRequest()
    }

    private func addBlockingPhoneNumbers(to context: CXCallDirectoryExtensionContext) throws {
        // Retrieve phone numbers to block from data store. For optimal performance and memory usage when there are many phone numbers,
        // 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.
        //
         let phoneNumbers: [CXCallDirectoryPhoneNumber] = [ +8618005555555, +8618005555555 ]

        for phoneNumber in phoneNumbers {
            context.addBlockingEntry(withNextSequentialPhoneNumber: phoneNumber)
        }
    }

    private func addIdentificationPhoneNumbers(to context: CXCallDirectoryExtensionContext) throws {
        // Retrieve phone numbers to identify and their identification labels from data store. For optimal performance and memory usage when there are many phone numbers,
        // 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.
        //
        // Numbers must be provided in numerically ascending order.
        let phoneNumbers: [CXCallDirectoryPhoneNumber] = [ +8618005555555, +8618005555555 ]
        let labels = [ "騷擾電話", "Local business" ]

        for (phoneNumber, label) in zip(phoneNumbers, labels) {
            context.addIdentificationEntry(withNextSequentialPhoneNumber: phoneNumber, label: label)
        }
    }

2 . 手工給Extension 生成 一個(gè) CallDirectoryExtension.entitlements 文件凿将。
3 . 運(yùn)行。在設(shè)備的設(shè)置 —> 電話 —> Call Blocking & Identification价脾,開啟我們的 App牧抵。
4 . 打電話

效果

IMG_4610.png

API

beginRequest

該方法在 Containing App 調(diào)用 reload 或者在 設(shè)置 —> 電話 —> Call Blocking & Identification里開啟權(quán)限的時(shí)候,會自動被調(diào)用侨把。但是打斷點(diǎn)的時(shí)候犀变,無法進(jìn)來。

open class CXCallDirectoryProvider : NSObject, NSExtensionRequestHandling {

    
    open func beginRequest(with context: CXCallDirectoryExtensionContext)
}

給系統(tǒng)數(shù)據(jù)庫增加騷擾電話號碼

    open func addBlockingEntry(withNextSequentialPhoneNumber 
phoneNumber: CXCallDirectoryPhoneNumber)
  • 數(shù)據(jù)量大時(shí)座硕,需要分批處理弛作,注意內(nèi)存問題。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.
  • 號碼升序排列华匾。 Numbers must be provided in numerically ascending order
  • 號碼需要加區(qū)號映琳。 Edit retrievePhoneNumbersToIdentifyAndLabels() to include the number and label you want. Add +CountryCode at the start (not confirmed yet if this is essential)

給系統(tǒng)數(shù)據(jù)庫增加騷擾電話號碼以及提示的文本

    open func addIdentificationEntry(withNextSequentialPhoneNumber phoneNumber:
 CXCallDirectoryPhoneNumber, label: String)

提交

    open func completeRequest(completionHandler completion:
 (@escaping (Bool) -> Swift.Void)? = nil)

蘋果開發(fā)交流網(wǎng)站上的總結(jié)

https://forums.developer.apple.com/thread/48837

I've managed to get this working, here's what I did and 
some observations:

1) Create a new target of Type Call Directory Extension.

2) Edit retrievePhoneNumbersToIdentifyAndLabels() to include the number
 and label you want. Add +CountryCode at the start (not confirmed yet
 if this is essential)

3) Run the containing app target.

4) In setting go to Phone/Call Blocking & IdentificationAnd turn on you 
extension (or it will automatically be turned on if you run the
 entension target rather than the containing app target)

5) Make a call

Its not possible to hit any breakpoints in the extension if running in 
XCode regardless of which target you execute. NSLog statements can be 
viewed via XCode's devices, it indicates that the extension is called in 
step 4) if the above steps are called. I don't know if/when its called 
subsequently after that, it has to be otherwise how can an updated list
 be applied?

If you want to make a change to the label, the OS does caching, so turn
 off the extension, delete the containing app app, clear the call history
 from the phone app, install and run again.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末机隙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子萨西,更是在濱河造成了極大的恐慌有鹿,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谎脯,死亡現(xiàn)場離奇詭異葱跋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)源梭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門娱俺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人废麻,你說我怎么就攤上這事荠卷。” “怎么了烛愧?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵油宜,是天一觀的道長。 經(jīng)常有香客問我怜姿,道長慎冤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任沧卢,我火速辦了婚禮蚁堤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘但狭。我一直安慰自己违寿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布熟空。 她就那樣靜靜地躺著藤巢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪息罗。 梳的紋絲不亂的頭發(fā)上掂咒,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機(jī)與錄音迈喉,去河邊找鬼绍刮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛挨摸,可吹牛的內(nèi)容都是我干的孩革。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼得运,長吁一口氣:“原來是場噩夢啊……” “哼膝蜈!你這毒婦竟也來了锅移?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤饱搏,失蹤者是張志新(化名)和其女友劉穎非剃,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體推沸,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡备绽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鬓催。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肺素。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宇驾,靈堂內(nèi)的尸體忽然破棺而出压怠,到底是詐尸還是另有隱情,我是刑警寧澤飞苇,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站蜗顽,受9級特大地震影響布卡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜雇盖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一忿等、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧崔挖,春花似錦贸街、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至脓鹃,卻和暖如春逸尖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瘸右。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工娇跟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人太颤。 一個(gè)月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓苞俘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親龄章。 傳聞我的和親對象是個(gè)殘疾皇子吃谣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容