Android 語音通話模塊介紹(三) CSipSimple介紹

語音通話模塊介紹(三) CSipSimple介紹

 

CSipSimple簡介

      CSipSimple是基於PJSIP開源協議庫實現的Android程序,這裏主要圍繞CSipSimple的功能實現講解。凡是在CSipSimple中涉及到的Android知識點以PJSIP相關內都會進一步的分析。

項目中主要有幾個包:

api包下主要是一些靜態的常量,關於sip的管理。
db包當然是數據庫了,它也使用了標準的ContentProvider,其中一些建表的語句還是用api包中的類。
pjsip就是這個庫相關的類了,具體沒有研究。在編譯jni前,這部分是有問題的,因爲它需要jni的調用,工程也會報錯。編譯後生成一些jni對應的調用文件就正常了,生成的文件在org.pjsip下。
utils包就是一些幫助類,比如配置管理,音頻自動聚焦。聯繫人,剪切版。
widgets包是一些自定義的控件。
wizards包是輔助用戶的引導用的。
plugins包是插件,沒看出有什麼用處。
service包也是這裏的重點:
MediaManager音頻管理的,控制不同的音頻流,來電時的音頻,藍牙,靜音等。
OutgoingCall是呼出接收器,先通過這個攔截,可以攔截到系統電話的呼叫,與程序內的呼叫。然後自定義了選擇器。
Downloader處理下載的,更新的時候就是用這個下載的。默認使用的是cacheDir目錄。
SipNotifications是一個通知類,主要管理了通知。
SipService這裏的主要服務。
  
ui包下就是關於界面的一些類了,account是添加帳戶的。filters是關於帳戶的過濾的,還使用了拖動排序的ListView
calllog就是通話日誌了。日誌有選擇保存在系統的通話中還是軟件中。
incall就是來電的,與通話界面了。
dialpad是撥號面板
還有一個包是org.webrtc.videoengine,這裏是視頻通話時用到的,一看名字就知道了camera
暫時沒有找到視頻的插件的源碼在哪裏下載。但有編譯好的apk。使用x264編碼。

CSipSimple框架介紹

      CSipSimple由應用層,JNI層,驅動層等組成。其中應用層和JNI層是該程序的核心,而驅動層根據設備提供。在應用層中,主要圍繞了Android四大組件進行。其中:

     Activity:完成界面UI顯示;

     Intent:主要是實現在ActivityActivity之間的切換

     Service:完成activity和後臺之間的聯繫以及進程間的通信

     ContentProvider:完成數據保存及共享,主要保存一些設置,用戶狀態,好友等信息

     Broadcast:主要完成在系統內信息的廣播,一般會和ContentProvider結合,如當數據改變了,就攜帶信息發送廣播,當所有已註冊的廣播接收器接收到內容之後進行解析之後進行相應的操作。

     在JNI層,因爲PJSIP核是基於C語言的,如果要用java調用,就必須封裝本地的JNI庫,從而實現從上到下的調用。

1 主界面

    主界面是SipHome這個Activity在該Activity中,引入了Andriod版本纔有的actionBarActionBar的作用可以統一頁面導航和切換方式,可以突出顯示一些重要的操作,而把一些不那麼重要的或者使用頻率低的放在overflow中。所以這裏引入了4Tab分別對應DialerFragment ,CallLogListFragmentFavListFragListFragmentConversationFragment後通過使用ViewPager實現多頁面切換就可以實現這幾個activity的呈現。如圖1.1

 

2一些基本參數設置

  在進行相關操作,如添加用戶,打電話,發送信息之前。一些必要的設置如,只使用WIFI,開啓ICE功能,開啓STUN功能等參數設置必不可少。所以在剛開始使用時,一般我們會打開上面介紹的設置菜單項,其路徑爲:com.csipsimple.ui.prefs.hc.MainPrefs這個MainPrefs。 這裏講解MainPrefs這個Acitivty是如何實現的。首先該activity使用“headers”來進行屏幕顯示。其界面如圖2所示,共有6header。而通過xml文件下進行相關的xml編寫然後在MainPrefs中的onBuilder方法進行加載即可。而各個header都有相應的class。如圖1.2Andriod使用ContentProvider來保存數據。這裏參數保存,文件配置在DBProvider.classPreference中,其中DBProvider中主要和添加用戶註冊,信息,filter等關聯。

3 添加用戶(註冊用戶)

1 AccountsEditListFragment中設置完相關參數信息後,跳轉到BasePrefsWizardIntent攜帶wizardId,我們這裏使用的是Basic類型),可根據wizardId進行相應wizard的實例顯示
 
2 當設置好註冊用戶的相關數據之後,點擊保存按鈕之後進入BasePrefsWizard下的saveAccount函數,在該函數中進行了getContentResolver().insert語句,即關於操作ContentProvider的語句。這裏根據Uri查詢後進入DBProviderinsert方法,進而執行廣播命令getContext().sendBroadcast(publishIntent).
 
3 Csipsimple在這裏註冊了兩個廣播,一個AccountWidgetProviderDynamicReceiver4,我們這裏只用到DynamicReceiver4,其註冊方式爲動態註冊(在SipService註冊了DynamicReceiver4廣播接收器  )
 
4 當上面第二點分析的發出廣播信息後,主要有兩個reciever會做出相應的操作,分別DynamicReceiver4AccountWidgetProvider
 
5 DynamicReceiver4中重寫了onReceive即也是接收信息的函數。然後進入判斷語句,上面發送的廣播所攜帶的信息爲ACTION_SIP_ACCOUNT_CHANGED這樣的action根據這個action執行了SipService.setAccountRegistration()這個函數,從而跳轉到service中執行。這裏也就是用戶開始註冊的位置。
 
6 PJSUA操作:在上面的添加用戶操作中,其實已經和底層的JNI打交道了,如執行SipService.setAccountRegistration()這個函數之後就會調用底層的JNI庫。而在執行這些JNI庫之前。又關於PJSUA的一些初始化設置。這一節主要說明這個。在說明進行初始化之前,先說明下PJSIP庫框架(語音通話模塊介紹())
 
7 通過SipServiceonStart()函數,加載JNI(會跳到PjSipServicetryToLoadStack方法執行) ,而何時進行PJSUA初始化,CSipSimple中,在SipService開始,當註冊完廣播接收器之後還進行了這一步:deviceStateReceiver.startMonitoring(),程序進入DynamicReciever4startMonitoring()函數,進而在onConnectivityChanged()函數中調用了SipServicerestartSipStack函數,從而進入startSipStack()函數並調用了pjService.sipStart()方法。而這個sipStart()函數就是PJSUA初始化的所在處。
 
8 在sipStart函數中,結合PJSIP開發文檔。從開發文檔中我們知道,基礎的PJSUA-API控制PJSUA的創建,初始化,啓動,同時還提供各種輔助功能。在sipStart函數中,通過status = pjsua.create();完成pjsua的創建,除其他事項外,還初始化PJLIBPJLIB-UTIL,並創建了一個SIP endpoint。在調用任何PJLIB功能之前這是至關重要的一步。
 
9  進行了上面的初始化之後,並進行一些General Configure。一般情況下,應用程序都將通常需要執行一些任務,使用pjsua_transport_create()方法(該方法是C語言)來創建SIP傳輸。故在CSipSimple中有createTransport這樣的方法來創建SIP傳輸。完成這些初始化之後,應用程序必須調用status = pjsua.start()開始PJSUA,此函數將檢查所有的配置是否正確,如果沒有則採用默認配置
 
10 在前面步驟中,用戶添加是從接收器DynamicReceiver4執行了SipService.setAccountRegistration這個函數開始的,確切的講,連接底層JNI庫的都在PjSipService中進行,此處也是這樣。進入到PjSipService中的setAccountRegistration方法。然後根據account的不同情況進行不同的操作,首次添加用戶將會進行這一步status = pjsua.acc_add(account.cfg,pjsuaConstants.PJ_FALSE,accId)這裏acc_add即調用了底層的JNI庫的pjsuaJNI.acc_add從而返回添加成功與否的狀態。根據該狀態進行相應狀態的改變,從而改變顯示界面,這個是內容觀察者ContentObserver的作用,下面這個步驟分析下這個內容觀察器。
 
11 在CSipSimple中很多地方使用了ContentObserver進行更新。ContentObserver是個內容觀察者。看過HeadFirst模式的話就知道,其實ContentObserver正是基於觀察者模式實現的。所謂觀察者,目的就是觀察(捕捉)特定的Uri引起的數據庫變化,當其所觀察的Uri發生改變了,便進行觸發。正是因爲ContentObserver的實現是基於觀察者模式的,所以其使用顯得尤其簡單,我們只需創建一個特定的ContentObserver派生類(如圖),重載父類構造函數以及onChang()方法處理回調後的功能實現(即觀察者模式中某一事件發生變化之後進行notify),然後要進行相應的註冊,即註冊內容觀察者和取消註冊的步驟即基本完成操作

4 撥打電話

Java 層接口調用的是placeCall()函數,進入placeCall函數之後,如判斷爲SIP用戶,則進行SipService方法調用,否則直接進行基本用戶撥打,如圖程序:

這裏只說明使用SIP電話撥打情況。程序調用了SipServicemakeCallWithOptions方法。進而進入SipServicemakeCallWithOptions方法。如圖所示:      

這樣,最終調用PJsipServicemakeCall。如圖所示:      

 

 

米糊軟件開發室:http://shop62437931.taobao.com/?spm=0.0.0.0

 

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章