SIP(Session Initiation Protocol)服務(wù)在Android 2.3中正式引入,能夠支持VOIP,當(dāng)然在早期版本中,也有不少第三方成功的將SIP服務(wù)移植到Android中。比較著名的客戶端包括sipdroid等。在Android中,SIP客戶端的實現(xiàn)位于android.net.sip包中,主要的類包括SipAudioCall、SipManager、SipProfile、SipSession等。
使用SIP,要求"android.permission.INTERNET"和"android.permission.USE_SIP"權(quán)限?紤]到即使軟件平臺采用了Android 2.3,在硬件配置上也可能不能完全支持SIP,所以在AndroidManifest.xml還應(yīng)聲明"android.hardware.sip.voip"、"android.hardware.wifi"、"android.hardware.microphone"等。
1.SipManager
SipManager用于初始化SIP鏈接和接入SIP服務(wù)等。能夠創(chuàng)建SIP會話。比較常用的方法包括:
createSipSession() //創(chuàng)建SIP會話
getCallId() //獲得呼叫ID
makeAudioCall() //發(fā)起語音呼叫
newInstance() //創(chuàng)建一個SipManager實例
register() //注冊帳號
takeAudioCall() //接聽電話
open() //打開SIP會話
另外支持SIP并不意味著一定支持VOIP,是否支持SIP協(xié)議棧和是否支持VOIP功能與硬件設(shè)備有關(guān),在基于SIP發(fā)起語音呼叫前,還需判斷支持SIP和語音呼叫,方法為isVoipSupported()和isApiSupported()。
2.SipAudioCall
SipAudioCall用來處理基于SIP的網(wǎng)絡(luò)語音呼叫,通過SipManager的makeAudioCall()方法和
takeAudioCall()方法可以獲得SipAudioCall的實例。
但需要注意的是,SipAudioCall要求"android.permission.INTERNET"和
"android.permission.USE_SIP"權(quán)限。
另外其startAudio()方法還要求"android.permission.ACCESS_WIFI_STATE"、"android.permission.WAKE_LOCK"、
"android.permission.RECORD_AUDIO"權(quán)限。其setSpeakerMode()方法還要求"android.permission.MODIFY_PHONE_STATE"權(quán)限。
SipAudioCall的常用方法包括:
startAudio() //在一個已建立的SIP鏈接中發(fā)起通話
setSpeakerMode() //設(shè)置通話模式
toggleMute() //進(jìn)行靜音模式
getPeerProfile() //獲取對方的信息
endCall() //結(jié)束一個語音呼叫SIP鏈接
answerCall() //應(yīng)答一個語音呼叫SIP鏈接
makeCall() //發(fā)起一個語音呼叫SIP鏈接
sendDtmf() //發(fā)送DTMF音
另外通過設(shè)置SipAudioCall.Listener()監(jiān)聽器可以監(jiān)聽到SIP鏈接建立和結(jié)束的信息。在SIP語音呼叫鏈接建立后,就可以傳輸RTP(Real-time Transport Protocol)流了。在RFC 3551中對SDP(Session Description
Protocol)采用的RTP流進(jìn)行了明確的定義。其語音流為AMR格式。
3.SipProfile
SipProfile包含了一個SIP賬戶的帳戶名、密碼、端口、SIP域和SIP服務(wù)器地址等信息。
通過SipProfile.Builder可以構(gòu)建一個SipProfile實例,另外也可以從SipSession中獲取本地和對方的SipProfile實例。
SipProfile的常用方法包括:
getPassword() //獲得密碼
getUriString() //獲得URI
getSipDomain() //獲得SIP域
getDisplayName() //獲得顯示名
getUserName() //獲得賬戶名
4.SipSession
SipSession意味著一個SIP會話。通過SipManager的createSipSession()方法可以獲得發(fā)起呼叫時的SIP會話,通過SipManager的getSessionFor()方法可以獲得收到呼叫時的SIP會話。
通過SipSession.Listener監(jiān)聽器可以監(jiān)聽到會話的信息如呼叫忙、呼叫結(jié)束、呼叫建立、注冊請求、鈴聲等。
同SipSession.State監(jiān)聽器可以監(jiān)聽到會話的狀態(tài),SIP會話的狀態(tài)目前有DEREGISTERING、INCOMING_CALL、INCOMING_CALL_ANSWERING、IN_CALL、NOT_DEFINED、OUTGOING_CALL、OUTGOING_CALL_CANCELING、OUTGOING_CALL_RING_BACK、PINGING、READY_TO_CALL、REGISTERING等。
SipSession的常用方法包括:
getPeerProfile() //獲取對方的信息
setListener() //設(shè)置SipSession.Listener監(jiān)聽器
register() //注冊到SIP服務(wù)器
下面是發(fā)起SIP呼叫的一般過程:
public void initiateCall()
{
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
}
@Override
public void onCallEnded(SipAudioCall call) {
……
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
}
catch (Exception e) {
if (me SipProfile!= null) {
try {
meSipManager.close(me.getUriString());
}
catch (Exception ee) {
ee.printStackTrace();
}
}
if (call != null)
{
call.close();
}
}
}
下面是收到SIP呼叫的一般處理過程:
public class IncomingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
@Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};
incomingCall = meSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
在框架層,SIP協(xié)議棧的具體實現(xiàn)位于frameworks\base\voip中,和其他服務(wù)一樣,在框架上采用的同樣是C/S架構(gòu),其框架層服務(wù)為SipService。