linphone-android-客戶端APP-工程解讀

 LinphoneLauncherActivity 是APP的入口組件,在這個組件裏,它會啓動LinphoneService這個後臺服務,而後不斷地判斷這個後臺服務是否已經啓動完畢,若是已經啓動完畢後,才讓APP進入直接的功能組件LinphoneActivity。android

        LinphoneService是標準的android後臺服務,這個後臺服務很是的關鍵,它須要完成的工做包括如下的內容。加載APP須要使用的資源,啓動LinphoneManager這個APP的全局管理器,LinphoneManager 這個全局管理器會一方面管理LinphoneService 的實例,另外一方面管理LinphoneCore這個核心實例,同時生成目前須要處理的事件通知的LinphoneCoreListenerBase實例並註冊到LinphoneCore這個核心實例的事件監聽器中。目前的LinphoneCoreListenerBase 實例只監聽callState,globalState,registrationState這三個事件。若是這個時候有電話呼入,那麼callState事件觸發,callState事件當中state會是LinphoneCall.State.IncomingReceived,APP須要切換到電話呼入的操做界面。registrationState這個事件反饋的是用戶的SIP帳號到SIP服務器的註冊狀態,是成功註冊仍是註冊失敗等。服務器

        LinphoneManager實現了LinphoneCoreListener, LinphoneChatMessage.LinphoneChatMessageListener這兩個接口的部分方法,負責系統須要使用的資源的管理與初始化,管理着LinphoneCore的實例,負責了LinphoneCore的初始化和它的整個生命週期,同時又響應接收到文件消息與文件消息的響應,感受它的總體職責是有點混亂的,可能做者開始是把它做爲全局的統一資源管理器的,但是後來開發着開發着就什麼東西都往裏面放,就成了這樣了。網絡

        LinphoneActivity是整個APP的核心界面組件,它採用了容器的結構模式來組織它所要包含的各個Fragment。它維護了一個專門用於存放各個Fragment實例的Fragment列表。它採用的佈局文件是main.xml,針對手機與平板電腦分別作了一套佈局文件,呵呵。這個佈局文件主要是分爲上下兩個部分,而後上邊部分主要是菜單與狀態欄,下邊那部分再分爲兩大個部分,一個部分是Fragment的容器,另外一個部分是表明功能模塊的TAB形式的工具欄。LinphoneActivity也會生成一個LinphoneCoreListenerBase的實例並註冊到LinphoneCore這個核心實例的事件監聽器中,它監聽的事件是messageReceived(有用戶給本身發信息,這個信息多是文件也多是文本),registrationState,callState。當有電話呼入的時候,這個時間當前的組件也會接收到這個事件,而後將界面切換到CallIncomingActivity這個界面組件。框架

        CallIncomingActivity界面組件就是提供一個界面給用戶選擇接聽仍是掛斷,並設置相關的接聽參數。這個界面組件當中也生成一個LinphoneCoreListenerBase的實例並註冊到LinphoneCore這個核心實例的事件監聽器中,它監聽的事件是callState,狀態是State.CallEnd,這樣在對方結束了電話呼入時好通知當前界面對方已經結束通話,再也不呼入,那個APP應該結束當前界面,回到主界面狀態。在CallIncomingActivity界面組件下,用戶選擇了接聽電話,那麼APP將切換到CallActivity這個界面組件下,同時判斷當前用戶是否接受視頻電話,從而決定是視頻通話,仍是語音通話。ide

    CallActivity這個界面組件是通話界面,這個界面組件當中也生成一個LinphoneCoreListenerBase的實例並註冊到LinphoneCore這個核心實例的事件監聽器中,它監聽的事件是callState,callEncryptionChanged。callState會通知新的來電呼入,對方暫停通話,對方更新通話設置等相應的事件消息,發便當前界面針對這些消息做出相應的反饋。這個通話界面主要是控制兩個Fragment的動態切換,一個是語音通話的CallAudioFragment,在這個Fragment裏,用戶能夠啓用不啓用麥克風和攝像頭等。同時還能夠向新的用戶發起電話呼叫,不過從目前的界面看是隻容許當前用戶向某一個用戶進行通話的,若是再邀請一個用戶進入通話的話,它是把上一個通話的用戶設置爲暫停通話狀態,而後當前用戶與多個用戶通話的話,就是不斷地切換當前通話的用戶。另外一個是視頻通話的CallVideoFragment,這個Fragment主要是展示兩個視頻流的窗口,一個是當前用戶本身的視頻在界面的右下角,另外一個是通話對方的視頻。默認是展示CallVideoFragment,當用戶點擊CallVideoFragment這個界面的時候,又切換回CallAudioFragment,這樣用戶才能看到功能欄方便操做。工具

        CallVideoFragment裏有兩個關鍵的SurfaceView,分別用戶展示當前用戶的視頻和對方用戶的視頻。private SurfaceView mVideoView; 這個是對方用戶的視頻展示控件。private SurfaceView mCaptureView;這個是當前用戶的視頻展示控件。首先CallVideoFragment 會生成一個androidVideoWindowImpl的實例,這個實例再經過LinphoneManager.getLc().setVideoWindow(androidVideoWindowImpl)傳入到linphone的核心當中,androidVideoWindowImpl的實例當中的相關事件監聽器後續就能接收到內核的想着事件消息通知,從而將視頻流傳遞到對應的SurfaceView當中,設置對方用戶視頻流到SurfaceView 當中的方法是LinphoneManager.getLc().setVideoWindow(vw),設置當前用戶視頻流到SurfaceView 當中的方法是LinphoneManager.getLc().setPreviewWindow(mCaptureView)。佈局

        DialerFragment界面組件,提供一個撥號的鍵盤,用來輸入須要呼叫的SIP號碼,而後進行呼叫。撥號呼叫調用的是LinphoneManager.getInstance().newOutgoingCall(mAddress)這個方法,傳遞的參數是對方的SIP號碼或是SIP地址。newOutgoingCall這個方法裏會先對當前使用的網絡類型進行檢測,用的是LinphoneUtils.isHighBandwidthConnection()方法。而後最終調用CallManager.inviteAddress()方法進行呼叫,這個方法最終又調用的LinphoneCore.inviteAddressWithParams(lAddress, params)方法進行呼叫。當LinphoneActivity 訂閱的callState事件的state == State.OutgoingInit || state == State.OutgoingProgress的時候,APP界面組件切換到CallOutgoingActivity,由這個界面來展示正在呼出的狀態。線程

   CallOutgoingActivity這個界面組件,當中也生成一個LinphoneCoreListenerBase的實例並註冊到LinphoneCore這個核心實例的事件監聽器中,它監聽的事件是callState,狀態是State=Connected或是StreamsRunning的時候,說明對方接聽成功,界面組件再切換回CallActivity,並顯示是語音通話界面仍是視頻通話界面。日誌

        CallManager是專門用來進行電話呼叫的管理者類,專門負責對進行呼叫,或是對當前進行的呼叫進行參數設置的更新。視頻

        PreferencesListFragment和SettingsFragment界面組件是負責APP的參數設置,設置的參數很是的豐富,有帳號,網絡,音頻,視頻等。它們採用的是android框架自帶的PreferenceScreen技術來創建整個參數設置的界面與功能,這樣就省去了本身來作界面一個個實現相應的參數設置的功能。定義PreferenceScreen最關鍵的就是編寫它對應的XML文件,這個XML文件編寫好後,系統會根據它的內容來生成相應的設置界面,很是的方便,相應的技術點能夠百度一下。一個PreferenceScreen裏還能夠嵌套多個PreferenceScreen,從而構建多層級的設置界面。系統裏自帶有多種類型的設置界面,如ListPreference,CheckBoxPreference等。可是這個PreferenceScreen它並不會保存相關的配置信息,因此這些配置參數的保存仍是得由外部來進行保存,隨後加載PreferenceScreen界面的時候,從新給裏面的各個組件設置上相應的狀態。目前在APP中是由LinphonePreferences這個類來負責了配置信息的保存的,而這個類又是依賴LpConfig這個具體負責讀寫配置文件的類來提供相應的功能,它真正的保存配置的文件是一個相似ini配置文件的文本文件,也就是講linphone是本身實現的配置保存與讀取功能,呵呵,沒有用系統自帶的,那咱們也就沿用它的吧。默認的配置文件就在工程的res/raw下邊,而PreferenceScreen配置文件就是在工程的res/xml下。

    HistoryListFragment是呼入呼出歷史列表的展示界面組件,這些呼入呼出的歷史記錄數據LinphoneCore是直接本身用數據記錄下來了的,因此APP不須要考慮記錄這些信息,除非須要本身定製地保存這些信息,不想用LinphoneCore的。經過LinphoneManager.getLc().getCallLogs()能夠得到呼入呼出的歷史記錄。

        LinphoneCore是整個linphone內核基於JNI的封裝接口,LinphoneCoreImpl是linphone內核針對JAVA開發語言的封裝。全部linphone內核的相關方法都是經過它來向android系統暴露。它裏面有方法很是的多,這裏須要關注幾個關鍵的方法。

public void iterate();最爲關鍵的主循環方法,應用程序應該常常調用它,由於它在後臺會完成多件事情,如接收SIP指令,註冊,認證,超時檢測等,它必需要運行在LihpnoCore其它的方法所運行的線程裏,說白了就是要保證LinphoneCore的方法運行在一至的線程裏,否則就出錯了。

public LinphoneCall invite(LinphoneAddress to)throws LinphoneCoreException;向對方發起一個電話呼叫請求。

public void terminateCall(LinphoneCall aCall);結束當前的電話呼叫。

public void declineCall(LinphoneCall call, Reason reason);直接掛斷當前正在呼入的電話請求。

public LinphoneCall getCurrentCall();獲取當前正在進行電話通話的實例。

public LinphoneAddress getRemoteAddress();獲取當前通話下對方的SIP地址或是SIP電話號碼。

public boolean isIncall();當前是否是處在通話狀態下,這個通話要麼在是進行的,也多是暫停的,但沒有掛斷,仍是鏈接着的。

public void acceptCall(LinphoneCall aCall) throws LinphoneCoreException;接收正在向本身電話呼入的通話。

public void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException;接收通話的另外一方對當前通話配置的修改,這樣就能保證本身的通話配置與對方的一至。

public void deferCallUpdate(LinphoneCall aCall) throws LinphoneCoreException;拒絕通話的另外一方對當前通話配置的修改,這樣本身的通話配置就不會自動被修改了。

public LinphoneCallLog[] getCallLogs();得到通話日誌列表。

public LinphoneCallLog getLastOutgoingCallLog();得到最近的通話日誌列表。

public boolean isNetworkReachable();獲取當前網絡鏈接狀態是否可鏈接。

void muteMic(boolean isMuted);禁用或是啓用麥克風。

void enableAdaptiveRateControl(boolean enable);啓用或禁用自適應速率控制,這個是根據網絡帶寬來自動調整傳輸速率的,當心慎用。

void enableEchoCancellation(boolean enable);啓用或禁用語音的回聲消除,這個是利用降噪的,echo limiter是回聲門限。

void enableSpeaker(boolean value);啓用或禁用揚聲器。

void setVideoDevice(int id);設置某個攝像頭爲當前使用的攝像頭。

int getVideoDevice();獲取攝像頭列表。

boolean isVideoSupported();檢測客戶是否支持視頻通話

void enableVideo(boolean vcap_enabled, boolean display_enabled);啓用或禁用視頻,能夠設置本身與對方視頻的狀態,可是若是通話已經創建正在通話中,那麼調用這個方法是沒有任何做用的,它必須在通話前調用。

int updateCall(LinphoneCall call, LinphoneCallParams params);修改已經創建的通話的狀態,可是這個並非能改通話的全部狀態,針對視頻在通話中的設置修改是無效的,如通話中不能修改視頻的分辨率。

int getUploadBandwidth();獲取最大上行網絡帶寬,單位是kbit/s.

 

void setUploadBandwidth(int bw);設置最大上行網絡帶寬,單位是kbit/s。

 

int getDownloadBandwidth();獲取最大下行網絡帶寬,單位是kbit/s。

 

void setDownloadBandwidth(int bw);設置最大下行網絡帶寬,單位是kbit/s.

boolean pauseCall(LinphoneCall call);暫停當前的通話。

 

boolean resumeCall(LinphoneCall call);恢復當前的通話。

 

boolean pauseAllCalls();暫停所有當前的通話。

void terminateAllCalls();結束所有的通話。

 

LinphoneCall[] getCalls();獲取當前的所有通話。

void transferCall(LinphoneCall call, String referTo);把當前與本身鏈接的通話轉接到別的用戶那裏,本身的通話結束掉。

 

void transferCallToAnother(LinphoneCall callToTransfer, LinphoneCall destination);把當前的通話轉接到另外一個正在進行的通話當中。

void setPlayFile(String path);設置播放給對方聽的音樂,通話還在呼入的狀態下。

相關文章
相關標籤/搜索