轉(zhuǎn)載文章來自: http://www.cnblogs.com/jhzhu/p/3416305.html
蘋果官方原文:
There are several requirements for implementing a VoIP app: Add the UIBackgroundModes key to your app’s Info.plist file. Set the value of this key to an array that includes the voip string. Configure one of the app’s sockets for VoIP usage. Before moving to the background, call the setKeepAliveTimeout:handler: method to install a handler to be executed periodically. Your app can use this handler to maintain its service connection. Configure your audio session to handle transitions to and from active use. To ensure a better user experience on iPhone, use the Core Telephony framework to adjust your behavior in relation to cell-based phone calls; see Core Telephony Framework Reference. To ensure good performance for your VoIP app, use the System Configuration framework to detect network changes and allow your app to sleep as much as possible.
1.IOS允許App的一個Socket在App切換到后臺后仍然保持連接. 這樣,當(dāng)有通話請求的時候,App能及時處理. 這個socket需要在應(yīng)用第一次啟動的時候創(chuàng)建, 并標(biāo)記為"此socket用于VoIP服務(wù)". 這樣當(dāng)App切換到后臺的時候,IOS會接管這個標(biāo)記為"用于VoIP服務(wù)"的socket. 這個socket的響應(yīng)函數(shù)(比如,一個delegate,或者是個block)會正常的響應(yīng), 就像App還在前臺一樣. 2.10s魔咒. 當(dāng)socket有任何數(shù)據(jù)從服務(wù)端傳來, 你在app里為socket寫的響應(yīng)函數(shù)都會做處理.但是, 你只有最多10s的時間來干你想干的事情. 也就意味著你在響應(yīng)函數(shù)里新建一個大于10s的timer是沒有意義的. 并且IOS并不保證給你足夠10s的時間,視系統(tǒng)情況而定. 3.在socket的響應(yīng)函數(shù)里, 你能通過NSLocalNotification來通知用戶"電話來了". 除此之外, 你沒法做其他任何視覺上的動作來提醒用戶, 因為你的app還處于某個不知道的次元, 甚至連window都還沒創(chuàng)建. 4.你永遠(yuǎn)也沒有辦法知道或者決定NSLocalNotification的樣式是banner還是alert. 你也許鐘愛后者, 但是決定權(quán)在用戶手里. 5.允許在后臺定期執(zhí)行一段代碼. 你可以設(shè)定一個大于等于10分鐘的時間t, 和一個定期執(zhí)行的handler, IOS系統(tǒng)會在每次經(jīng)過t時間的時候調(diào)用一次這個handler. 但是IOS不保證這個handler會準(zhǔn)時運行, 只保證在時間t范圍內(nèi)的某個點會執(zhí)行一次. 6.我們通常用樓上的handler處理socket的斷線重連操作. 因為網(wǎng)絡(luò)不穩(wěn)定, 或者用戶開啟飛行模式等原因, 我們用于voip服務(wù)的socket會斷開連接. 在這個handler里,如果發(fā)現(xiàn)連接斷開,我們只需要跟條目1一樣的創(chuàng)建socket,設(shè)置一樣的socket響應(yīng)函數(shù),一切又會恢復(fù)正常. 7.不建議這個handler做太多事情, 因為它也有10s魔咒.(據(jù)不完全統(tǒng)計,蘋果所有的后臺處理都有這個10s限制. 不保證絕對正確哈, 僅供參考) 8.自啟服務(wù). 當(dāng)IOS重新啟動, 或者你的app因為其他原因退出時, IOS會馬上啟動你注冊為voip的app, 你可以很迅速的恢復(fù)socket連接. 但是, 從底部多任務(wù)欄中手動關(guān)閉應(yīng)用除外.更"code"的說明是:當(dāng)程序退出的exitcode != 0,IOS會重啟你的app.經(jīng)試驗發(fā)現(xiàn),從底部多任務(wù)欄關(guān)閉的時候,程序的exitcode == 0. 9.如果你親愛的用戶是一個典型的"app終結(jié)者",那么你還剩最后一條路來通知來電提醒:NSRemoteNotification. 你也許會被NSRemoteNotification的可靠性和實時性折騰的抓狂, 但是, 誰讓你選了IOS? 你享受了封閉帶來的傳世體驗, 也得承受封閉的限制. 10.當(dāng)條目8描述的情況發(fā)生之后,app的application:didFinishLaunchingWithOptions:會被調(diào)用. 但是,請時刻提醒自己我們的app仍然處于后臺. 我們以前總在這里創(chuàng)建window創(chuàng)建rootController, 但現(xiàn)在不必了. 現(xiàn)在我們需要的就是把可愛的socket連上, 像在條目1里一樣,讓一切回歸正常(我不去寫歌詞真浪費了^_^). 11.在application:didFinishLaunchingWithOptions:里你能通過[application applicationState] == UIApplicationStateBackground來判斷是正常啟動應(yīng)用還是系統(tǒng)自動啟動, 然后決定該創(chuàng)建window還是創(chuàng)建voip的socket.
VoIP類的app允許用戶使用Internet網(wǎng)絡(luò)而不是手機的蜂窩網(wǎng)絡(luò)打電話,因此這一類的app需要保持同它相關(guān)的服務(wù)的網(wǎng)絡(luò)連接,用以厚道來電消息和其他數(shù)據(jù)财骨。IOS系統(tǒng)不是通過一直讓app處于激活狀態(tài)來達(dá)到這個目的仑氛,而是同樣也會將這類的app掛起洛搀,但同時會在app被掛起期間接管它的sockets雷猪,當(dāng)這個sockets有數(shù)據(jù)通信時纵隔,系統(tǒng)會再次喚醒處于掛起狀態(tài)的app暮现,同時將sockets的控制權(quán)交還給app席函,以讓其正常的處理來去電事件和其他數(shù)據(jù)铐望。
一、voip應(yīng)用需要有下面幾個要求:
1茂附、在Info.plist中增加UIBackgroundModes鍵正蛙,并將值設(shè)為voip;
2、為該app配置sockets营曼,并注冊到系統(tǒng)上乒验,以便app切到后臺時系統(tǒng)會接管這個sockets;
3、在app切到后臺之前蒂阱,要調(diào)用setKeepAliveTimeout:handler:方法來注冊一個周期性執(zhí)行的handler锻全,用于保持app和服務(wù)器的連接;
4录煤、配置一個音頻會話(audio session)鳄厌。
二、UIBackgroundModes鍵的voip值有三個功能:
1妈踊、告知系統(tǒng)在app切到后臺的時候接管它的sockets部翘;
2、這個鍵值的另外一個功能是允許app在后臺播放音頻响委,跟UIBackgroundModes的audio值起到的作用相同。
3窖梁、后臺狀態(tài)的app在系統(tǒng)確定voip服務(wù)可用的時候會立即重新加載(relaunched)
三赘风、配置keep-alive handler
一個voip類的app需要周期性的被喚醒以防止失去跟服務(wù)器的連接。為了達(dá)到這個目的纵刘,iOS系統(tǒng)允許我們通過setKeepAliveTimeout:handler:方法來實現(xiàn)保持連接邀窃。通常我們都在軟件切到后臺以后,也就是在applicationDidEnterBackground:才需要實現(xiàn)保持連接的方法。Handler配置完后瞬捕,系統(tǒng)會根據(jù)需要在time out設(shè)置的時間到期之前喚醒處于掛起狀態(tài)的app鞍历,至少被調(diào)用一次handler中的方法。
1肪虎、 handler
需要說明的是劣砍,這個handler在后臺執(zhí)行的時候需要盡可能快的返回,因為系統(tǒng)只給了最多10s的時間去執(zhí)行它扇救。如果10s內(nèi)沒有執(zhí)行完刑枝,而且沒有去申請額外的執(zhí)行時間,系統(tǒng)將會吧app掛起迅腔。
2装畅、timeout
設(shè)置handler時,需要指定app需要的最大超時時間沧烈。IOS系統(tǒng)允許的最小值是600s掠兄,如果想設(shè)置個小點的值,handler的設(shè)置就會失敗锌雀。系統(tǒng)在執(zhí)行handler內(nèi)容的時候蚂夕,只保證超時時間到之前會執(zhí)行,而不保證準(zhǔn)確的執(zhí)行時間點汤锨,系統(tǒng)是會根據(jù)當(dāng)時的任務(wù)情況等系統(tǒng)條件確定一個合適的時間點双抽,已達(dá)到延長電池壽命的目的。