2021.6 更新
根據(jù)目前了解情況,除查找技術(shù)解決方案外,還有可能向蘋果申請?zhí)厥鈾?quán)限來解決此問題。關(guān)鍵詞:com.apple.developer.pushkit.unrestricted-voip
需求
公司項(xiàng)目有一套即時(shí)的視頻語音聊天功能,產(chǎn)品希望是當(dāng)App切入后臺掛起或者被用戶劃掉后,收到視頻語音推送時(shí),App可以持續(xù)震動(dòng)及響鈴(持續(xù)震動(dòng)及響鈴),并且用戶點(diǎn)擊通知時(shí),App啟動(dòng)后就可以及時(shí)的進(jìn)行視頻語音通話(用戶無等待)。
技術(shù)現(xiàn)狀
蘋果推送有三種方案:
1.普通推送
2.靜默推送
3.VoIP推送
針對三種推送方案的說明,網(wǎng)上有很多很詳細(xì)的資料,這里就不一一列舉。我們很快的就可以鎖定,如果要實(shí)現(xiàn)以上需求,VoIP是我們唯一可以選擇的方案。
在Xcode11之前,我們可以直對接VoIP推送,唯一面臨的是蘋果的審核。但是前段時(shí)間蘋果發(fā)布了一則通知:
Important
On iOS 13.0 and later, if you fail to report a call to CallKit, the system will terminate your app. Repeatedly failing to report calls may cause the system to stop delivering any more VoIP push notifications to your app. If you want to initiate a VoIP call without using CallKit, register for push notifications using the UserNotifications framework instead of PushKit. For more information, see UserNotifications.
通過Xcode11我們收到VoIP推送時(shí),如果我們沒有調(diào)用Callkit相關(guān)代碼,即reportNewIncomingCallWithUUID,我們會直接收到以下崩潰信息:
Apps receving VoIP pushes must post an incoming call (via CallKit or IncomingCallNotifications) in the same run loop as pushRegistry:didReceiveIncomingPushWithPayload:forType:[withCompletionHandler:] without delay.
*** Assertion failure in -[PKPushRegistry _terminateAppIfThereAreUnhandledVoIPPushes], /BuildRoot/Library/Caches/com.apple.xbs/Sources/PushKit/PushKit-37/PKPushRegistry.m:343
顯然蘋果為了避免我們不正當(dāng)?shù)氖褂肰oIP推送,進(jìn)行了強(qiáng)制處理,所以我們需要對接CallKit咯?如果這樣做了,在提交的時(shí)候,以下信息可能在等著你:
Apple Dear Developer,
The Chinese Ministry of Industry and Information Technology (MIIT) http://www.miit.gov.cn/n1146285/ ... n3057713/index.html requested that CallKit functionality be deactivated in all apps available on the China App Store.
Since your app currently includes CallKit and is available for sale on the China App Store, you will need to submit an update that removes CallKit functionality in China.
VOIP call functionality continues to be allowed but can no longer take advantage of CallKit ’ s intuitive look and feel. CallKit can continue to be used in apps outside of China.
If you have questions or do not believe your app is subject to this update, please contact MIIT.
Best regards,
App Store Review
那我們通過手機(jī)號碼等條件,進(jìn)行區(qū)域處理。國內(nèi)使用普通推送,國外通過VoIP來做應(yīng)該可以通過蘋果要求,但是老板不同意了,我們面向的是國內(nèi)用戶。仿佛已經(jīng)撞到南墻了!
另辟蹊徑
那讓我們先來對比下幾個(gè)大廠如何做的。
- QQ:收到視頻通話,手機(jī)持續(xù)震動(dòng)幾秒直至推送自動(dòng)隱藏。點(diǎn)擊QQ無等待直接可以接聽
- 微信:收到視頻通話,手機(jī)持續(xù)震動(dòng)至少30s。點(diǎn)擊微信無需等待直接可以接聽
- 閑魚:收到視頻通話,手機(jī)震動(dòng),點(diǎn)擊閑魚后無需等待直接可以接聽
BOSS: QQ、微信都實(shí)現(xiàn)了,你為什么實(shí)現(xiàn)不了。。。
既然這些App都收到了VoIP推送并且激活了App,同時(shí)沒有出現(xiàn)CallKit的電話界面,說明通過某些方式是可以實(shí)現(xiàn)的。那我就把重點(diǎn)放在了當(dāng)我們調(diào)用reportNewIncomingCallWithUUID方法的時(shí)候,系統(tǒng)做了什么。如果可以找到,那我們就可以偷偷地做個(gè)好心人幫系統(tǒng)做一下。
嘗試思路一
嘗試打印當(dāng)前所有線程內(nèi)的方法調(diào)用,看這個(gè)過程中,是否有一些不一樣的方法被調(diào)用,令人遺憾的是并沒有找到有用的信息。
嘗試思路二
監(jiān)聽所有通知的發(fā)送,是否通過一些通知進(jìn)行了信息傳遞。這這個(gè)過程中,我們發(fā)現(xiàn)有一個(gè)不一樣的通知出現(xiàn):PKPushIncomingCallReportedNotification。
然后讓我們試試不再調(diào)用reportNewIncomingCallWithUUID方法,而是發(fā)送這個(gè)通知呢?結(jié)果正是我們想要的!沒有CallKit的通話界面,App有沒有異常崩潰通知。
存在的問題
但是偶爾會出現(xiàn)無法再次收到VoIP的push通知。
高重現(xiàn)場景為:收到VoIP推送后長時(shí)間不處理,客戶端會被異常終止,之后就收不到了。但是收到時(shí)客戶端激活,就沒有問題。
寫在最后
目前工作有其他更緊急的插入進(jìn)來,暫時(shí)沒有繼續(xù)研究了(后面抽時(shí)間再看)。這里只是提供了一種解決問題的思路,我們不能因?yàn)檎J(rèn)為做不到就不去嘗試。
如果有朋友有更好的思路或者存在問題解決方案找到了,可以回復(fù)用來幫助更多的人學(xué)習(xí)。
同時(shí)呢,這種方式只是我們挑戰(zhàn)自己的方式,上架App還是要遵守蘋果規(guī)范的!