Android提供支持Session Initiation Protocol(SIP)协议的一套API。可以让你为你的应用添加基于SIP的互联网电话功能。Android包含了完整的SIP协议栈和集成呼叫管理服务,能够让应用在不管理回话的情况下很容易地建立输入或输出的语音呼叫,传输层的通信,音频记录或直接播放。
下面是有可能需要使用SIP Api的应用类型:
·视频会议
·即时通讯
下方是开发SIP应用的要求:
·必须有运行Android2.3及其更高版本的移动设备
·SIP通过无线数据连接进行通信,因此你的设备必须要有数据连接(采用移动数据服务或WIFI)。这意味着你不能再AVD(模拟器)上测试SIP应用,而只能在物理设备上测试,参见测试SIP应用。
·在这个应用通信会话中的每个参与者都必须有一个SIP账号。有很多提供SIP账号的不同的SIP账号提供者。
下方是在Android SIP API中包含的所有类和一个接口(SipRegistrationListener)的摘要
类或接口 |
描述 |
SipAudioCall |
通过SIP处理互联网音频呼叫 |
SipAudioCall.Listener |
与SIP呼叫相关的事件的监听器,例如当呼叫正在被接受(“在响铃”)或正在发出(“在呼叫”)。 |
SipErrorCode |
定义了在SIP活动期间的错误代码。 |
SipManager |
对SIP tasks提供APIs,例如创建SIP链接,以及提供对相关SIP服务的访问。 |
SipProfile |
定义SIP profile,包括SIP账号,域名或服务器信息。 |
SipProfile.Builder |
创建SipProfile的辅助类。 |
SipSession |
代表一个与SIP dialog或没有dialog的单独操作相关的SIP会话。 |
SipSession.Listener |
与SIP会话相关的监听器,例如当会话正在被注册(“在注册”)或呼叫正在发出(“在呼叫”)。 |
SipSession.State |
定义SIP会话状态,例如“正在注册”,“正在呼出”,以及“通话中”。 |
SipRegistrationListener |
这个接口是一个对SIP登记事件的监听器。 |
如果你要使用SIP API开发应用,需要记住的是这个功能只在Android2.3(API Level 9)及更高版本的Android平台上才被支持。也就是说,它运行在Android2.3及更高版本中,并非所有Android设备中。
为了使用SIP,你需要在应用的Manifest中添加下面的权限:
·android.permission.USE_SIP
·android.permission.INTERNET
为了保证你的应用只能被安装在可支持SIP的设备中,需要在你应用的manifest中添加如下代码:
·<uses-sdk android:minSdkVersion="9"/> 这表示你的应用需要在Android2.3及更高版本中使用。关于这个的更多信息,参见API Level和针对这个<use-sdk>元素的文档。
为了将你的应用从不支持SIP的设备中过滤出来(例如,在Google Play中),需要在你应用的manifest中添加如下代码:
·<uses-featureandroid:name="android.hardware.sip.voip" /> 这表明你的应用使用SIP API。这个声明应该包含android:required属性,这个属性表明是否你想将这个应用从不支持SIP的设备中过滤出来。其他的<uses-feature>声明也可以不需要,这个依赖于你的实现。关于更多信息,参加针对<uses-feature>元素的文档。
如果你应用被设计用来接收呼叫,你也必须在应用的manifest中定义一个接收器(BroadcastReceiver的子类)。
·<receiverandroid:name=".IncomingCallReceiver" android:label="CallReceiver"/>
下方是SIPDemo的部分相关引用:
<?xmlversion="1.0" encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.sip">
...
<receiver android:name=".IncomingCallReceiver"android:label="Call Receiver"/>
...
<uses-sdk android:minSdkVersion="9" />
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.INTERNET" />
...
<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" />
</manifest>
为了使用这个SIP API,你的应用必须创建SIPManager对象。在你的应用中这个SIPManager将管理如下操作:
·创建SIP会话
·创建和接收呼叫
·使用SIP Provider注册与取消注册
·检查会话通信
你能采用如下方式创建SIPManager
public SipManagermSipManager = null;
...
if(mSipManager == null) {
mSipManager =SipManager.newInstance(this);
}
典型的Android SIP应用包含一个或多个用户,他们每个都要有一个SIP账号。在Android SIP应用中,每个SIP账号都由SIPProfile对象来表示。
SIPProfile定义了SIP profile,包括SIP账号,域名和服务器信息。这个同在设备上运行的应用SIP账号相关的profile被叫做local profile。这个会话连接到的profile被看做同级profile。当你的SIP应用通过这个local profile登录SIP服务器的时候,这个有效登记的设备对SIP地址来说就会被看作是发出呼叫的地方。
下面显示了如何创建SIPProfile,通过SIP服务器进行登记,以及跟踪登记事件。
采用如下方式创建SIPProfile对象:
public SipProfilemSipProfile = null;
...
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();
下面的代码片段针对打电话和或接听通用的SIP电话打开本地Profile。接下来呼叫者能通过mSipManager.makeAudioCall进行呼叫。当设备接收一次呼叫时,android.SipDemo.INCOMING_CALL将通过Intent过滤器被使用。下方是登记步骤:
Intent intent = newIntent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent,Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pendingIntent, null);
最后,这个代码通过SipManager设置SipRegistrationListener。这将监听这个profile是否成功登记到你的SIP服务提供商:
mSipManager.setRegistrationListener(mSipProfile.getUriString(),new SipRegistrationListener() {
public void onRegistering(StringlocalProfileUri) {
updateStatus("Registeringwith SIP Server...");
}
public void onRegistrationDone(StringlocalProfileUri, long expiryTime) {
updateStatus("Ready");
}
public void onRegistrationFailed(StringlocalProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Pleasecheck 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);
}
}
为了拨打音频电话,你必须满足以下条件:
·拨电话的Profile(the local profile),以及接受呼叫的有效的地址(the peer profile)。
·SipManager对象。
为了能够拨打音频电话,你应当设置SipAudioCall.Listener。很多同SIP协议栈通信的客户端的交互都通过这个监听器来操作。在下面的代码段中,你将看到在呼叫建立后SipAudioCall.Listener如何处理事情:
SipAudioCall.Listenerlistener = new SipAudioCall.Listener() {
@Override
public void onCallEstablished(SipAudioCallcall) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
...
}
@Override
public void onCallEnded(SipAudioCall call) {
// Dosomething.
}
};
一旦你设置了SipAudioCall.Listener,你就能打电话了。SipManager的makeAudioCall有如下几个参数:
·A local Profile(调用者)
·A peer profile(被呼叫的用户)
·一个监听来自SipAudioCall的呼叫事件的监听器。这项也可为null,然正如上所说,一旦呼叫建立那么这个监听器就能用来处理事情。
·超时时间,以秒为单位
例如:
call =mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener,30);
为了接电话,SIP应用必须包含有能力响应接电话Intent的BroadcastReceiver的子类。因此,你必须在你的应用中做如下事情:
·在AndroidManifest.xml中,定义<receiver>。在SIPDemo中,也就是<receiverandroid:name=".IncomingCallReceiver" android:label="CallReceiver"/>。
·实现receiver,也就是BroadcastReceiver的子类。在SIPDemo中,也就是IncomingCallReceiver。
·当需要使用local profile的时候,使用启动receiver的pending intent创建local profile。
·设置Intent过滤器来过滤表示接电话的动作,在SIPDemo中,也就是android.SipDemo.INCOMING_CALL。
为了接电话,你的SIP应用必须继承自BroadcastReceiver。当手机来电时,Android系统处理SIP来电呼叫并广播“来电”intent(由这个应用定义)。下面是来自SIPDemo中的继承自BroadcastReceiver的代码。为了看清完整的例子,下载SIPDemo Sample,它包含在SDK Sample中。
/*** Listens for incoming SIP calls,intercepts and hands them off to WalkieTalkieActivity.
*/
public class IncomingCallReceiverextends 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 voidonRinging(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。在SIPDemo中,这个动作串是android.SipDemo.INCOMING_CALL。
下方来自SIPDemo中的代码片段显示了,当这个SIPProfile接收呼叫时,这个PendingIntent将执行一个broadcast:
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 filter截获,然后将启动receiver(IncomingCallReceiver)。你也能在你应用的manifest文件中指定intent filter,或者通过代码来完成:
public class WalkieTalkieActivityextends Activity implements View.OnTouchListener {
...
public IncomingCallReceiver callReceiver;
...
@Override
public void onCreate(Bundle savedInstanceState) {
IntentFilter filter = newIntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver,filter);
...
}
...
}
为了测试SIP应用,你需要做如下事情:
·运行Android2.3或更高版本的移动设备。SIP通过无线网来运行,因此你必须在真实的设备上进行测试,而不能使用模拟器来测试。
·SIP账号。有很多不同的SIP提供商来提供SIP账号。
·如果你要打电话,也必须要有可用的SIP账号。
测试SIP应用:
1. 让你的设备连接到无线(Settings > Wireless& networks > Wi-Fi > Wi-Fi settings)。
2. 为了测试设置的设备。
3. 在你的移动设备上运行SIP应用。
4. 如果你使用的是Eclipse,那么你能在Eclipse中使用LogCat来浏览应用的输出日志(Window > Show View> Other > Android > LogCat)。