Android提供支持会话发起协议(SIP)的API。这让你可以把基于SIP的互联网电话功能添加到你的应用程序中。Android包含了一个完整的SIP协议栈,并且集成了呼叫管理服务,这样应用程序可以容易的建立呼入和呼出的连接,而不需要去管理会话、传输层的通信、音频记录、回拨等操作。
以下是开发SIP应用程序的要求
你必须要有一部运行Android2.3以上版本的移动设备;
SIP是运行在无线数据连接之上的,因此你的设备必须要有一个数据连接(如移动数据服务或Wi-Fi)。这就意味着你不能在AVD上测试---你只能在物理设备上测试。
每个应用应用程序通信会话的参与者都必须要有一个SIP账号。有很多不同的SIP提供商提供SIP账号。
以下是Android SIP API中所包含的类和一个接口(SipRegistrationListener)的概要:
类/接口 | 介绍 |
---|---|
SipAudioCall | 处理基于SIP的互联网音频呼叫。 |
SipAudioCall.Listener | 监听与SIP呼叫相关的事件,如呼叫被接入(“on ringing”)或呼出(“on calling”)时。 |
SipErrorCode | 定义SIP操作期间返回的错误代码。 |
SipManager | 提供针对SIP任务的API,如发起SIP连接,并提供对相关SIP服务的访问。 |
SipProfile | 定义SIP配置,包括SIP账号、域名和服务器信息。 |
SipProfile.Builder | 创建SipProfile类型对象的辅助类。 |
SipSession | 代表一个跟SIP对话框或没有对话框的独立事务相关联的SIP会话。 |
SipSession.Listener | 监听与SIP会话相关的事件,如注册会话(“on registering”)或呼出(“on calling”)的时候。 |
SipSession.State | 定义SIP会话的状态,如“registering”,“outgoing call”和“in call” |
SipRegistrationListener | 监听SIP注册事件的接口。 |
如果你正在开发一个使用SIP API的应用程序,那么一定要记住,该功能只在Android2.3(API Level 9)以后的版本上才被支持。还有,不是所有的运行Android2.3(API Level 9)以后版本的设备都提供对SIP的支持。
把下列权限添加到你的应用程序清单中,以便使用SIP
android.permission.USE_SIP
android.permission.INTERNET
要确保你的应用程序只能被安装子提供SIP能力的设备上,就要在你的应用程序清单中添加<uses-sdk android:minSdkVersion=”9”>
。这个声明指明你的应用程序要求Android2.3以上的版本。更多的信息请看API级别和<uses-sdk>
元素相关的文档。
要控制你的应用程序能够被那些不支持SIP的设备过滤掉(例如,在Google Play上),还要把下列声明添加到你的应用程序的清单中:
<uses-feature android:name=”android.hardware.sip.voip” />
。这就声明了你的应用程序所使用的SIP API。这个声明应该包含一个android:required数据,用它来指示你是否希望你的应用程序被不提供SIP支持的设备过滤掉。其他的<uses-feature>
声明也可能需要,这依赖与你的实现。更多的信息请看<uses-feature>
元素的文档。
如果你的应用程序被设计成要接收呼叫,你还必须在应用程序的清单中定义一个接收器(BroadcastReceiver类的子类)。
<receiver android:name=”.IncomingCallReceiver” android:label=”Call Receiver” />
以下是SipDemo示例清单中的摘要:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns: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对象,在你的应用程序中,该对象负责以下工作:
启动SIP会话;
启动并接受呼叫;
注册和注销SIP服务提供商;
验证会话的联通性。
用下列方式实例化一个新的SipManager对象:
public SipManager mSipManager = null;
…
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
典型的Android SIP应用程序要涉及到一个或多个用户,每个用户都要有一个SIP账号。在一个Android SIP应用程序中,每个SIP账号由一个SipProfile对象来代表。
一个SipProfile对象定义了一个SIP配置,包括:一个SIP账号、域名和服务器信息。跟运行应用程序的设备上的SIP账号相关联的配置(profile)被叫做本地配置(local profile)。用于连接会话的配置被叫做对等配置(peer profile)。当你的SIP应用程序使用本地的SipProfile对象登录到SIP服务器时,这实际上是用注册设备所用的SIP地址来发送SIP呼叫。
本段向你介绍如何创建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过滤器来使用,以下是注册的步骤:
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);
最后,这段代码把SipRegistrationListener监听器设置到SipManager对象上。这样就跟踪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.");
}
当你的应用程序完成对一个配置的使用时,它应该被关闭,以便释放跟这些对象关联的内存,并从服务器上注销该设备的连接,如:
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() {
@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.Listener监听器,用于监听来自SipAudioCall的呼叫事件。这个监听器可以是null,但是如上述代码所示,一旦建立了呼叫,这个监听器就被用于做一些事情。
超时值,以秒为单位。
例如:
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener,30);
SIP应用程序必须包含一个BroadcastReceiver类的子类来接收呼叫,这个类具有响应指明呼叫源的Intent对象的能力。因此,你的应用程序要做以下事情:
在AndroidManifest.xml中声明一个<receiver>
元素。在SipDemo中的声明是:<receiver Android:name=".IncomingCallReceiver" android:label="Call Receiver"/>
.
实现该接收器,它是BroadcastReceiver的一个子类。在SipDemo中,这个类是IncomingCallReceiver。
用呼叫本地配置文件时,触发你的接收器的PendingIntent对象来初始化本地的配置对象(SipProfile)。
建立一个Intent过滤器来过滤代表呼入的操作。在SipDemo中,这个操作是android.SipDemo.INCOMING_CALL。
要接收呼叫,你的SIP应用程序就必须实现一个BroadcastReceiver的子类。Android系统处理SIP的呼入,并且在收到呼入的时候广播一个“incoming call”的Intent对象(由应用程序定义的)。以下是来自SipDemo的BroadcastReceiver的子类的代码。要看完整的例子,请看SipDemo sample,它包含在SDK的示例中。
/*** 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对象。在SipDemo中,这个操作字符串是android.SipDemo.INCOMING_CALL。
以下来自SipDemo的代码摘要显示了如果用基于操作字符串android.SipDemo.INCOMING_CALL所获得的PendingIntent对象来创建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过滤器截获,然后触发接收器(IncomingCallReceiver)。你可以在你的应用程序清单文件中指定一个Intent过滤器,或者是像SipDemo示例那样在应用程序的Activity的onCreate()方法中用代码来做这件事:
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
...
public IncomingCallReceiver callReceiver;
...
@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应用程序:
在你的设备上,接入无线(Setting->Wireless&networks->Wi-Fi->Wi-Fi settings)
把你的移动设备设置为用于调试,设置方法在Developing on a Device中进行了介绍。
在你的移动设备上运行你的应用程序,运行方法在Developing on a Device中进行了介绍。
如果你使用的是Eclipse,你可以使用Eclipse中LogCat来查看应用程序的日志输出(Window->Show View->Other->Android->LogCat)。