linphone是一款老牌的全平臺的多人語音視頻通話業(yè)務的軟件(始自2001年)背捌,不僅支持視頻和語音通話,還支持即時消息(可惜只支持文本和圖片)固蚤。
當然,重要的是:linphone是開源的烈钞,畢竟linphone的sip服務和媒體數(shù)據(jù)處理也大量使用開源框架泊碑;更重要的是,linphone官網(wǎng)提供免費的sip服務毯欣,這也意味著你不需要自己手動搭建sip服務即可享受voip業(yè)務蛾狗,這對于有voip需求的前端來說無疑是最佳的選擇。但是雖然開源仪媒,linphone的工程比較龐大,依賴項較多谢鹊,編譯的過程中容易出現(xiàn)問題算吩,那么下面,我將介紹自己linphone-iphone的安裝歷程佃扼。
linphone-iphone的下載
首先進入官網(wǎng)偎巢,可以看到linphone的多個產(chǎn)品線,最感興趣的肯定是liblinphon了兼耀,但是這是個坑压昼,一方面,開發(fā)文檔幾乎沒有瘤运,根本無從下手窍霞;另一方面,編譯的過程相當痛苦拯坟,成功率不高但金,就算編譯出來了也沒有成就感可言,不僅需要花費大量的時間寫Demo做測試郁季,你還要考慮如何搭建SIP服務器冷溃。
如果想體驗并快速學習相關(guān)的接口,我建議去linphone這一欄梦裂,在downloads目錄下似枕,你可以看到所有平臺的產(chǎn)品都是可以下載源碼的,這里選擇iphone版年柠。你有兩種選擇凿歼,要么選擇官網(wǎng)的git://git.linphone.org/linphone-iphone.git
,要么選擇github上的git://git.linphone.org/linphone-iphone.git
彪杉,其實效果差不多毅往,但是記住不要手動下載,而是使用git命令clone
到本地派近,因為模塊中的很多依賴庫代碼都沒有放在項目中攀唯,需要通過git鏈接下載。
打開終端渴丸,有iTerm2更好侯嘀,cd到項目放置的目錄另凌,輸入
git clone git://git.linphone.org/linphone-iphone.git
命令開始下載,你會發(fā)現(xiàn)一切順利戒幔,很快便下載完成吠谢,你很高興的cd進linphone-iphone
,輸入"./prepare.py"诗茎,以為腳本會為你解決剩下的一切工坊,然而出現(xiàn)了下面的提示:這時打開
submodules
文件夾就會發(fā)現(xiàn)里面的模塊全部是空的,看工程所依賴的模塊都沒下載過來敢订,只是下載了前端的這個空殼王污。那就照著它說的做好了,輸入命令git submodule update --init --recursive
楚午,嗯昭齐,下載進度又開始了,剛開始也許一切正常矾柜,但是過一段時間會發(fā)現(xiàn)大多卡在了libxml2
這個xml解析模塊的下載上了阱驾,我用了比較笨的方法:請再來一次...,之前下載失敗的部分只需要再輸入一次git submodule update --init --recursive
就可以繼續(xù)下載怪蔑,可惜不支持斷點續(xù)傳里覆,模塊需要重頭下載,TOT缆瓣。但是有更好的解決辦法租谈,實際上github是有
libxml2
分支的,想辦法把git中的鏈接替換掉就行捆愁,下面我們通過git命令來修改git配置中的鏈接來實現(xiàn)下載:首先在工程目錄下割去,終端中輸入
git config -l
,看到如下信息:可以看到libxml2用的源是
git://git.gnome.org/libxml2
昼丑,我們需要換一個能下的呻逆,運行git config -e
就可以用vim編輯git配置文件了,替換后的樣子如下所示:修改后保存菩帝,運行git submodule update --init --recursive
就可以繼續(xù)下載了咖城,最終所有源碼下載成功,可以開心的編譯了呼奢,是的宜雀,托腳本的福,編譯無壓力握础。
linphone-iphone的編譯
下面的工作進行的比較順利辐董,無非照著readme一步一步來,缺哪個就去裝哪個禀综。
- 首先简烘,為了支撐腳本順利運行苔严,我們需要安裝[HomeBrew]((http://brew.sh),有了它編譯缺少依賴的日子一去不復返了孤澎。
-
./prepare.py
這個時候可以運行該命令來安裝linphone-iphone的依賴項了届氢,提示我們需要使用brew安裝coreutils
automake
autoconf
libtool
intltool
wget
pkgconfig
cmake
yasm
nasm
doxygen
ImageMagick
optipng
libantlr3c
gettext
,這時homebrew派上了用場覆旭,運行命令brew install coreutils automake autoconf libtool intltool wget pkgconfig cmake yasm nasm doxygen ImageMagick optipng libantlr3c gettext
就可以自動安裝完成退子,不需要手動配置環(huán)境。 - 再次運行``./prepare.py`型将,嗯絮供,提示我們要安裝java JDK,那就去裝一下好了茶敏。這個更簡單,直接去網(wǎng)上下載java SE開發(fā)套裝的軟件安裝就可以了缚俏。
- 終于可以開始
./prepare.py
了,腳本做的比較智能,只要前面步驟都完成了屠升,這一步成功率較高蜻牢。 - 完成這些準備工作后,可以開始重頭戲亚茬,編譯了酪耳,運行
./prepare.py -c && ./prepare.py && make
,大概20分鐘左右就可以編譯好刹缝⊥氚担可以看到子目錄下多出了一個liblinphone-sdk
文件夾,里面是編譯好的liblinphone在各個平臺下的靜態(tài)庫梢夯。 - 打開
linphone.xcodepro
言疗,工程文件夾中自帶了企業(yè)推送證書,可以實現(xiàn)推送,連接真機后颂砸,按?R
就可以享受了噪奄。
linphone_iphone的調(diào)試
是的,其實到這里基本就結(jié)束了人乓。但是我們費這么大功夫不是為了裝個Voip玩一玩了事的勤篮,而是借鑒里面對接口的調(diào)用方式。這里主要了解通話業(yè)務相關(guān)的代碼色罚。
工程目錄結(jié)構(gòu)
可能是工程維護時間較長的原因碰缔,但說實話,現(xiàn)在還在用xib實在是...不過好處是UI結(jié)構(gòu)簡單一看就懂戳护。
與工程相關(guān)的類全部放在Classes
中手负,子目錄有各頁面的ViewController以及l(fā)iblinphone的中間件涤垫,而LinphoneUI
中存放自定義的各種控件,Utils
中存放用到的工具類和第三方視圖類竟终,都不是什么著名的蝠猬,引起注意的一個是XMLRPC,遠程過程調(diào)用的一個ios框架统捶;另一個TPMultiLayoutViewController比較重要榆芦,工程中幾乎所有的UIViewController都繼承自它,嗯喘鸟,似乎它的目的是早年(5年前)用來解決一種布局方式的UIViewController可以同時適用橫向和豎向的問題匆绣,也是夠老了。
跟通話相關(guān)的類型主要有:
-
CallIncomingView
:電話打入的視圖什黑; -
CallOutgoingView
:電話打出的視圖崎淳; -
CallView
:電話接通后的視圖、包括語音聊天愕把、視頻聊天拣凹、會議電話的視圖; -
PhoneMainView
: 電話視圖的容器恨豁,單例模式嚣镜;監(jiān)聽大部分的通話狀態(tài)變化,負責管理不同通話視圖間的跳轉(zhuǎn)和主要業(yè)務邏輯橘蜜; -
LinphoneManager
:對liblinphone中各種狀態(tài)的封裝以及功能的補充(音頻播放菊匿、音頻設備設置,音頻設備占用處理计福,低電量跌捆,新消息處理,前后臺處理)象颖,中間件疹蛉。
運行與調(diào)試
- 注冊與使用
我們來運行一下這個demo(完成度很高,已上架)力麸,終于看到了Xcode的"Build success"可款,程序進入后長這個樣子:
選擇CREAT ACCOUNT
進行帳號的注冊,注冊完成即可享受免費的sip服務克蚂,進入注冊頁面后闺鲸,建議用戶名最好填寫電話號碼或者純數(shù)字帳號,因為sip地址是根據(jù)用戶名來定義的埃叭,例如用戶名為username的用戶的sip地址為username@sip.linphone.org
摸恍,而撥號盤只能輸入數(shù)字...這意味著如果你想直接通過撥號盤或者手機聯(lián)系人來撥打sip電話(這些sip帳號都是跟電話號碼綁定的),就必須是純數(shù)字帳號。雖然也可以通過添加聯(lián)系人的方式來添加帶字母的sip帳號立镶,但這并不方便壁袄。注冊后在郵箱收到郵件并點擊鏈接驗證后帳號注冊完成,可以向另一臺注冊了帳號的設備發(fā)送voip通話了媚媒。 - 代碼分析
- UI
與通話相關(guān)的頁面一共有3個:CallIncomingView
嗜逻、CallOutgoingView
、CallView
缭召,分別為打入電話栈顷、呼出電話與通話期間的視圖。沒有特別難懂的地方嵌巷,用通知來進行UI更新萄凤。
而"PhoneMainView"則比較特殊,該單例不僅起到業(yè)務層的作用搪哪,而且是上面3個頁面的容器靡努,通過它來進行通話頁面之間的切換和管理。 - 業(yè)務晓折,位于
linphoneManager
中-
基本業(yè)務:
- 撥號
- 判斷網(wǎng)絡狀況
- 檢查是否在GSM通話中
- 檢測提供的addr是否合法
- 2g網(wǎng)絡下是否使用low_bandwidth模式
- linphone_core_invite_address_with_params
- 接聽
- 2g網(wǎng)絡是否是同low_bandwidth模式
-
linphone_call_params_enable_video
是否允許視頻流 -
linphone_core_accept_call_with_params
接電話
狀態(tài)監(jiān)聽:
voip通話狀態(tài)改變的監(jiān)聽是通過通知kLinphoneCallUpdate
下發(fā)的惑朦,注冊該通知后,就可以從userInfo
中的keycall
和state
中分別拿到當前通話的實例以及通話狀態(tài)碼已维。
那么,該通知又是怎么來的呢已日,看了voipManager.m
便知垛耳,在linphonecore.h
文件中有一個void (*LinphoneCoreCallStateChangedCb)(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message)
類型的blockcall_state_changed
,該回調(diào)會在通話狀態(tài)改變時觸發(fā)飘千,所以將方法static void linphone_iphone_call_state(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState state, const char *message)
賦值給了該blcok堂鲜,在該方法中會對各種state進行處理,最后將state护奈、call缔莲、message封裝到dict后發(fā)送通知。-
音頻設備相關(guān)
需要處理兩個問題:- 音頻設備占用霉旗,這里又分為GSM電話和普通音頻應用的占用痴奏;
- 音頻設備監(jiān)測,主要針對藍牙設備的接入厌秒。
-
前臺與后臺
為了保證應用進入后臺也能長時間通話读拆,做了如下處理:- 觸發(fā)
applicationDidEnterBackground
時:enterBackgroundMode
- refreshRegisters
- 設置超時處理
[[UIApplication sharedApplication] setKeepAliveTimeout: 600 handler:^{ linphone_core_iterate }
- 有通話則延長后臺存活時間
startCallPausedLongRunningTask
- [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler
- 停止視頻預覽
linphone_core_stop_dtmf_stream
- 如果不進入后臺模式,destroy voip socket if any
- 觸發(fā)
applicationDidBecomeActive
時:調(diào)用becomeActive
- refreshRegisters
- 停止后臺任務
pausedCallBgTask
和incallBgTask
linphone_core_start_dtmf_stream
- 觸發(fā)
-
其他部分就不一一列舉了鸵闪,說的不夠清楚檐晕,建議如果感興趣的話自己實際編譯調(diào)試一遍,從而對linphone的ios端接口有更深的了解。