目录[隐藏]
|
Android提供了一个支持会话发起协议(SIP)的API,这可以让你添加基于SIP的网络电话功能到你的应用程序。Android包括一个完整的SIP协议栈和集成的呼叫管理服务,让应用轻松无需管理会话和传输层的沟通就可设置传出和传入的语音通话,或直接音频记录或播放。
以下类型的应用程序可能使用SIP API:
以下是开发一个SIP应用程序的条件:
以下是Android SIP API中包含的一些类和一个接口(SipRegistrationListener)的概述:
类/接口 | 描述 |
---|---|
SipAudioCall | 通过SIP处理网络音频电话 |
SipAudioCall.Listener | 关于SIP电话的事件监听器,比如接受到一个电话(on ringing)或者呼出一个电话(on calling)的时候 |
SipErrorCode | 定义在SIP活动中返回的错误代码 |
SipManager | 为SIP任务提供APIs,比如初始化一个SIP连接。提供相关SIP服务的访问。 |
SipProfile | 定义了SIP的相关属性,包含SIP账户、域名和服务器信息 |
SipProfile.Builder | 创建SipProfile的帮助类 |
SipSession | 代表一个SIP会话,跟SIP对话框或者一个没有对话框的独立事务相关联 |
SipSession.Listener | 关于SIP会话的事件监听器,比如注册一个会话(on registering)或者呼出一个电话(on calling)的时候 |
SipSession.State | 定义SIP会话的声明,比如“注册”、“呼出电话”、“打入电话” |
SipRegistrationListener | 一个关于SIP注册事件监听器的接口 |
如果你开发一个用到SIP API的应用程序,记住它需要Android2.3(API9)或者更高版本的平台的支持。所以在你的设备上要运行Android2.3(API9)或者更高的版本,并不是所有的设备都提供SIP的支持。
为了使用SIP,需要添加以下权限到你的manifest文件:
为了确保你的应用程序能够安装到支持SIP的设备上,你需要添加以下内容到你应用程序的manifest文件里:
为了控制你的应用程序被那些不支持SIP的设备过滤掉(比如:在Google Play),你需要添加以下内容到你应用程序的manifest文件里:
如果你的应用程序设计用来接受呼叫,那么你还必须在应用程序的manifest文件里定义一个接收器(BroadcastReceiver 的子类):
以下是从SipDemo项目manifest文件中摘录的内容:
<?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对象,这个SipManager对象在你的应用程序里负责以下内容:
你可以像下面一样实例化一个新的SipManager对象:
public SipManager mSipManager = null; ... if(mSipManager == null) { mSipManager = SipManager.newInstance(this); }
一个典型的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); } }
要想拨打一个语音电话,你需要准备如下条件:
要想拨打一个语音电话,你应该建立一个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方法接受以下参数:
例如:
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener, 30);
为了接收呼叫,SIP应用程序必须包含一个BroadcastReceiver的子类,这个子类得有能力响应一个表明有来电的intent。因此你需要在你的应用程序里做如下事情:
为了接收呼叫,你的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; ... @Override public void onCreate(Bundle savedInstanceState) { IntentFilter filter = new IntentFilter(); filter.addAction("android.SipDemo.INCOMING_CALL"); callReceiver = new IncomingCallReceiver(); this.registerReceiver(callReceiver, filter); ... } ... }
要测试SIP应用程序的话,你需要以下条件:
测试一个SIP应用程序的步骤: