1. 程式人生 > >android sip協議通話程式碼實現

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功能才行.