android sip協議通話程式碼實現
android裡面的voip(voice over internet protocol)網路通話基於sip(session initiation protocol)協議,關於voip和sip協議的瞭解,請感興趣的讀者參考其它相關文件,本文不做解釋.
基於sip的voip網路通話基本過程是:(1),建立sip伺服器,關於如何搭建sip伺服器,請參考我的部落格點選開啟連結 (2)需要參與通話的所有客戶端註冊使用者到sip伺服器(3)一個客戶端發起sip通話到另一個客戶端,這個訊息首先發到sip伺服器,sip伺服器收到訊息後轉發到目的客戶端(4)目的客戶端接收電話.
android已經集成了sip協議棧,並提供了相應的api給應用開放使用,開發者不需要了解具體的協議內容.
關於sip網路通話的主要類和描述入下表所示.
類/介面 |
描述 |
SipAudioCall | 通過SIP處理網路音訊電話 |
SipAudioCall.Listener | 關於SIP電話的事件監聽器,比如收到一個電話(on ringing)或者撥出一個電話(on calling) |
SipErrorCode | 定義在SIP活動中的錯誤程式碼 |
SipManager | 為SIP任務提供APIs,比如初始化一個SIP連線,提供相關SIP服務的訪問。 |
SipProfile | 定義了SIP的相關屬性,包含SIP賬戶、域名和伺服器資訊 |
SipProfile.Builder |
建立SipProfile的幫助類 |
SipSession | 代表一個SIP會話,跟SIP對話方塊或者一個沒有對話方塊的獨立事務相關聯 |
SipSession.Listener | 關於SIP會話的事件監聽器,比如註冊一個會話(on registering)或者撥出一個電話(on calling)的時候 |
SipSession.State | 定義SIP會話的宣告,比如“註冊”、“撥出電話”、“打入電話” |
SipRegistrationListener | 一個關於SIP註冊事件監 聽器的介面 |
Android sdk中提供了一個SipDemo應用程式,關於使用Sip類開發語音通話功能的.本文也是針對這個demo講解基本通話的實現流程:
1.在應用的AndroidManifest.xml中需要宣告下面許可權和特徵.
<uses-permission android:name="android.permission.USE_SIP" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-feature android:name="android.hardware.sip.voip" android:required="true" /> <uses-feature android:name="android.hardware.wifi" android:required="true" /> <uses-feature android:name="android.hardware.microphone" android:required="true" />
2.構造一個SipManager例項.
SipManager manager = SipManager.newInstance(this); //必須呼叫此方法建立,這是因為該方法會判斷裝置是否支援sip協議PackageManager.FEATURE_SIP
如果有的android裝置不支援,可以新增android.software.sip.voip.xml和android.software.sip.xml到/system/etc/permissions/下.
3.下面程式碼是註冊一個賬戶到sip伺服器.
SipProfile.Builder builder = new SipProfile.Builder(username, domain); //uesrname表示註冊使用者名稱,domain表示域,實際就是sip伺服器ip
builder.setPassword(password); //註冊使用者密碼
SipProfile me = builder.build(); //構造一個SipProfile物件,也就是相當於一個賬戶資訊Intent i = new Intent();i.setAction("android.SipDemo.INCOMING_CALL");PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA); //構造一個PendingIntent物件,這樣當sip Service收到一個通話請求時,
例如收到一個來電時,SipService會呼叫PendingIntent的send方法傳送相應廣播訊息給呼叫者,也就是當前的SipProfile物件.
manager.open(me, pi, null); //此處就是用於註冊一個賬戶到sip伺服器 //註冊一個監聽器,用於獲取註冊賬戶時的通知狀態,當然也可以不註冊. manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() { public void onRegistering(String localProfileUri) { //正在註冊 } public void onRegistrationDone(String localProfileUri, long expiryTime) {//註冊成功 } public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage) { } });
4.開始撥號,從一個裝置撥打電話到另一個裝置,前提是兩個裝置都已註冊,且知道目的裝置的sip賬戶資訊.
try { SipAudioCall.Listener listener = new SipAudioCall.Listener() { // Much of the client's interaction with the SIP Stack will // happen via listeners. Even making an outgoing call, don't // forget to set up a listener to set things up once the call is established. @Override public void onCallEstablished(SipAudioCall call) { //當網路通話建立了之後,會收到此通知 call.startAudio(); //啟動音訊 call.setSpeakerMode(true); //設定為揚聲器模式,也就是開啟回聲抑制 call.toggleMute(); //切換靜音,注意預設為非靜音,呼叫此方法後變為靜音了 } @Override public void onCallEnded(SipAudioCall call) { } }; //注意此處的makeAudioCall方法就是打網路電話的,localProfile就是本地裝置的SipProfile物件,
//PeerProfile就是目標裝置的SipProfile物件,listener是監聽器
SipAudioCall call = manager.makeAudioCall(localProfile.getUriString(), PeerProfile, listener, 30);}catch (Exception e) { }
注意,此處的SipProfile的內容格式,例如,LocalProfile的url格式為"sip:[email protected]",PeerProfile的url格式為"sip:[email protected]",url內容也就是sip賬戶,
其中:
(1) sip: 表示採用sip協議
(2) abcde123和abcde234是使用者名稱, 也稱為帳號. 用字母和數字均可。
(3) 10.0.149.240是sip賬戶所屬的伺服器地址(當然也可以用域名來表示)
(4) SIP協議預設埠為5060, 預設採用UDP傳輸,如果需要指定埠為5678,可以修改為sip:[email protected]:5678,
從localProfile和peerProfile指定的內容可以看出,賬戶名作為唯一標識,由sip伺服器來解析賬戶名,從而找到對應的目的主機.5.目的端接收通話
根據前面分析,一個裝置撥打電話到目的裝置時,在目的裝置的sip服務(SipService)會發送一個廣播訊息給當前目的裝置,因此必須提前註冊一個廣播接收器來接收此廣播訊息,這樣才知道有來電通知.可以在AndroidManifest.xml靜態註冊,也可以在應用程式中動態註冊,因此下面程式碼必須放在廣播接收器的noReceive()方法中.
try { SipAudioCall.Listener listener = new SipAudioCall.Listener() { @Override public void onRinging(SipAudioCall call, SipProfile caller) { try { call.answerCall(30); } catch (Exception e) { e.printStackTrace(); } } };
//takeAudioCall就表示需要為接聽電話建立一個SipAudioCall物件. SipAudioCall incomingCall = manager.takeAudioCall(intent, listener); incomingCall.answerCall(30); //接聽電話 incomingCall.startAudio(); //啟動音訊 incomingCall.setSpeakerMode(true);
注意點:
1.所有參與網路通話的裝置和sip伺服器的網路必須是連線的,網路型別可以是乙太網,wifi,mobile等都可以.
如果通話過程有問題,可以檢測裝置網路收發包是否正常.
2.對應的裝置必須支援sip,voip功能才行.