原文:http://android.eoe.cn/topic/android_sdkandroid
Android提供了一個支持會話發起協議(SIP)的API,這可讓你添加基於SIP的網絡電話功能到你的應用程序。Android包括一個完整的SIP協議棧和集成的呼叫管理服務,讓應用輕鬆無需管理會話和傳輸層的溝通就可設置傳出和傳入的語音通話,或直接音頻記錄或播放。服務器
如下類型的應用程序可能使用SIP API:網絡
如下是Android SIP API中包含的一些類和一個接口(SipRegistrationListener)的概述:
<!-- 表格開始 -->
{|style="border-spacing: 0px;margin: 4px 4px; width: 90%; border-left:1px solid #ccc;border-top:1px solid #ccc; "dom
<!-- 這段是表頭 -->
|-style="background:#DEE8F1; "
! style="border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px;" | 類/接口
! style="border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px;" | 描述ide
<!-- 這段是表格 -->
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipAudioCall
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 經過SIP處理網絡音頻電話
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipAudioCall.Listener
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 關於SIP電話的事件監聽器,好比接受到一個電話(on ringing)或者呼出一個電話(on calling)的時候
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipErrorCode
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 定義在SIP活動中返回的錯誤代碼
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipManager
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 爲SIP任務提供APIs,好比初始化一個SIP鏈接。提供相關SIP服務的訪問。
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipProfile
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 定義了SIP的相關屬性,包含SIP帳戶、域名和服務器信息
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipProfile.Builder
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 建立SipProfile的幫助類
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipSession
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 表明一個SIP會話,跟SIP對話框或者一個沒有對話框的獨立事務相關聯
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipSession.Listener
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 關於SIP會話的事件監聽器,好比註冊一個會話(on registering)或者呼出一個電話(on calling)的時候
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipSession.State
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 定義SIP會話的聲明,好比「註冊」、「呼出電話」、「打入電話」
|- style=" vertical-align:top;"
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | SipRegistrationListener
| style=" border-right:1px solid #ccc;border-bottom:1px solid #ccc; padding:5px 15px; " | 一個關於SIP註冊事件監聽器的接口
|}
<!-- 表格結束 -->測試
若是你開發一個用到SIP API的應用程序,記住它須要Android2.3(API9)或者更高版本的平臺的支持。因此在你的設備上要運行Android2.3(API9)或者更高的版本,並非全部的設備都提供SIP的支持。ui
爲了使用SIP,須要添加如下權限到你的manifest文件:
* android.permission.USE_SIP
* android.permission.INTERNET
爲了確保你的應用程序可以安裝到支持SIP的設備上,你須要添加如下內容到你應用程序的manifest文件裏:
* . 這個設置代表你的應用程序須要Android2.3或者更高版本的平臺。詳情請參考API Levels和元素相關的文檔。
爲了控制你的應用程序被那些不支持SIP的設備過濾掉(好比:在Google Play),你須要添加如下內容到你應用程序的manifest文件裏:
* . 這個設置聲明瞭你的應用程序用到了SIP API。這個聲明還應該包含一個android:required 屬性來代表你是否想讓你的應用程序被那些不提供SIP支持的設備過濾掉。其餘聲明你也可能須要,具體取決於你的實現,詳情請參考 元素相關的文檔。
若是你的應用程序設計用來接受呼叫,那麼你還必須在應用程序的manifest文件裏定義一個接收器(BroadcastReceiver 的子類):
*
如下是從SipDemo項目manifest文件中摘錄的內容:
<?xml version"utf-8"?>
...
...
...
this
要想使用SIP API,你的應用程序須要建立一個SipManager對象,這個SipManager對象在你的應用程序裏負責如下內容:
* 發起SIP會話
* 發起和接受呼叫
* 在SIP provider裏進行註冊和註銷
* 驗證會話的連通性
你能夠像下面同樣實例化一個新的SipManager對象:
public SipManager mSipManager = null;
...
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}spa
一個典型的Android SIP應用中包含一個或多個用戶,他們中的每一個人都有一個SIP帳戶。在Android SIP應用中,每個SIP帳戶表明一個SipProfile對象。設計
一個SipProfile對象定義了一個SIP的概要文件,包括SIP帳戶、域名和服務器信息。跟正在這個設備上運行應用的SIP帳戶相關聯的概要文件被稱之爲本地配置文件。與會話相鏈接的概要文件被稱之爲對應配置文件。當你的SIP應用經過本地SipProfile登陸到SIP服務器的時候,這就有效的註冊當前設備爲基站來發送SIP呼叫到你想呼叫的SIP地址。
本節展現瞭如何建立一個SipProfile,以及如何把剛建立的SipProfile註冊到SIP服務器上,而且跟蹤註冊事件。
你能夠像如下同樣建立一個SipProfile對象:
public SipProfile mSipProfile = null;
...
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();
接下來的代碼摘錄本地配置文件,用於呼出電話和/或接收通用的SIP電話。呼叫器能夠經過mSipManager.makeAudioCall來呼出後續電話。這段摘錄一樣設置了一個android.SipDemo.INCOMING_CALL行動,這個行動會被一個intent過濾器來使用,當前設備接收到一個呼叫(見Setting up an intent filter to receive calls)。如下是註冊步驟:
Intent intent = new Intent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pendingIntent, null);
最後這段代碼在SipManager上設置了一個SipRegistrationListener 監聽器,這個監聽器會跟蹤SipProfile是否成功的註冊到你的SIP服務提供者。
mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
當你的應用程序使用完一個profile的時候,你應該關閉它來釋放相關聯的對象到內存中以及從服務器上註銷當前設備。例如:
public void closeLocalProfile() {
if (mSipManager == null) {
return;
}
try {
if (mSipProfile != null) {
mSipManager.close(mSipProfile.getUriString());
}
} catch (Exception ee) {
Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
}
}
要想撥打一個語音電話,你須要準備以下條件:
* 一個發起呼叫電話的SipProfile對象(本地配置文件)和一個用來接收呼叫的有效的SIP地址(對應配置文件)
* 一個SipManager對象
要想撥打一個語音電話,你應該創建一個SipAudioCall.Listener監聽器。大部分客戶與SIP堆棧的交互都是經過監聽器來發生的。在這一小段你將會看到SipAudioCall.Listener監聽器是如何在呼叫制定以後創建事務的:
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override public void onCallEstablished(SipAudioCall call) { call.startAudio(); call.setSpeakerMode(true); call.toggleMute(); ... } @Override public void onCallEnded(SipAudioCall call) { // Do something. }
|
};
一旦你建立了這個SipAudioCall.Listener監聽器,你就能夠撥打電話了,SipManager對象裏的makeAudioCall方法接受如下參數:
* 一個本地SIP配置文件(呼叫方)
* 一個相對應的SIP配置文件(被呼叫方)
* 一個用來監遵從SipAudioCall發出的呼叫事件的SipAudioCall.Listener,這個參數能夠爲null,可是如上所說,一旦呼叫電話制定,這個監聽器將被用來建立事務
* 超時的值,以秒爲單位
例如:
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener, 30);
爲了接收呼叫,SIP應用程序必須包含一個BroadcastReceiver的子類,這個子類得有能力響應一個代表有來電的intent。所以你須要在你的應用程序裏作以下事情:
* 在AndroidManifest.xml文件中聲明一個元素。在SipDemo項目中,元素是這樣的
* 實現BroadcastReceiver的子類,在SipDemo中,這個子類是IncomingCallReceiver
* 經過掛起一個intent來初始化本地配置文件(SipProfile),當有人呼叫你的時候,這個掛起的intent會調用你的接收器。
* 建立一個intent過濾器,這個過濾器經過標誌着來電的行動來進行過濾。在SipDemo中,這個action是android.SipDemo.INCOMING_CALL。
爲了接收呼叫,你的SIP應用必須實現BroadcastReceiver的子類。當Android系統接收到一個呼叫的時候,他會處理這個SIP呼叫,而後廣播一個來電intent(這個intent由系統來定義),如下是SipDemo中實現BroadcastReceiver子類的代碼。若是想查看完整的例子,你能夠去SipDemo Sample項目,這個項目在SDK的samples文件夾中。關於下載和安裝SDK samples,請參考 Getting the Samples。
/* * * Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity.
* /
public class IncomingCallReceiver extends BroadcastReceiver {
/* *
* Processes the incoming call, answers it, and hands it over to the
* WalkieTalkieActivity.
* @param context The context under which the receiver is running.
* @param intent The intent being received.
* /
@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();
}
}
};
WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
wtActivity.updateStatus(incomingCall);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
當SIP服務接收到一個新的呼叫的時候,他會發送一個intent,這個intent會附帶一個由應用程序提供的action。在SipDemo項目中,這個action是android.SipDemo.INCOMING_CALL。
如下從SipDemo中摘錄的代碼展現瞭如何經過掛起一個基於android.SipDemo.INCOMING_CALL action的intent來建立SipProfile對象的。PendingIntent對象將執行一個廣播當SipProfile接收到一個呼叫的時候:
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
...
Intent intent = new Intent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pendingIntent, null);
上面被執行的廣播若是被intent過濾器攔截的話,這個intent過濾器將會啓動聲明過的Receiver(IncomingCallReceiver)。你能夠在你的應用程序裏的manifest文件中指定一個intent過濾器,或者經過代碼來指定一個intent過濾器,就像SipDemo項目中Activity中的onCreate()方法同樣:
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
...
public IncomingCallReceiver callReceiver;
...
1 2 3 4 5 6 7 8 9 10 |
@Override public void onCreate(Bundle savedInstanceState) { IntentFilter filter = new IntentFilter(); filter.addAction("android.SipDemo.INCOMING_CALL"); callReceiver = new IncomingCallReceiver(); this.registerReceiver(callReceiver, filter); ... } ...
|
}
要測試SIP應用程序的話,你須要如下條件:* 一個運行Android2.3或者更高版本的移動設備。SIP經過無線來運行,因此你必須在一個真正的設備上測試,在AVD上是測試是行不通的* 一個SIP帳戶,有不少不一樣的提供SIP帳戶的SIP服務提供商。* 若是你要打電話,這個電話必須是有效的SIP帳戶。測試一個SIP應用程序的步驟:* 讓你的設備鏈接到無線(設置>無線&網絡>Wi-Fi>Wi-Fi設置)* 設置你的移動設備進行測試,就像在Developing on a Device裏描述的同樣* 在你的移動設備上運行程序,就像在Developing on a Device裏描述的同樣* 若是你正在使用Eclipse,你能夠在Eclipse中查看應用程序的日誌輸出(* Window > Show View > Other > Android > LogCat* )。