原文: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* )。