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

來源:互聯網
上載者:User

標籤:讀取   視頻   全域   int   audio   指令   調整   系統   etc   

 LinphoneLauncherActivity 是APP的入口組件,在這個組件裡,它會啟動LinphoneService這個後台服務,然後不斷地判斷這個後台服務是否已經啟動完畢,如果已經啟動完畢後,才讓APP進入直接的功能組件LinphoneActivity。

        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這個介面組件下,同時判斷目前使用者是否接受視頻電話,從而決定是視訊通話,還是語音通話。

    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);設定播放給對方聽的音樂,通話還在呼入的狀態下。

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.