概述:

Android提供了支持SIP(SessionInitiation Protocol)协议的API. 这让我们可以向APP中添加基于SIP的网络电话功能. Android包括了完整的SIP协议栈并集成了呼叫管理服务, 它可以让APP经过简单的设置就可以支持呼入和呼出, 而不用必须管理会话, 传输级别, 通信或者音频记录或者直接播放. 这里有两种APP可能使用到的SIP API: Video conferencing和Instant messaging.

要求和限制:

这是开发SIP APP的要求:

1.      必须有个移动设备并且配备Android2.3及更高版本.

2.      SIP通过一个无线数据连接来运行,所以设备必须有一个数据连接(通过移动数据服务或者WiFi). 这意味着我们不能用AVD来测试--只能在物理设备上测试.

3.      每个APP连接会话的参与者必须拥有一个SIP账号. 有很多不同的SIP提供者提供SIP账号.

SIPAPI类和接口:

下面是Android SIP API中类和接口的概述:

类/接口

描述

SipAudioCall

通过SIP处理一个网络音频呼叫.

SipAudioCall.Listener

SIP呼叫相关的事件监听器, 比如什么时候收到呼叫(on ringing)或者发出呼叫(on calling).

SipErrorCode

定义SIP操作期间返回的错误码.

SipManager

提供SIP任务的API, 比如启动SIP连接, 提供相关SIP服务的访问.

SipProfile

定义一个SIP配置文件, 包括SIP账户, 域和服务器信息.

SipProfile.Builder

创建SIP配置文件的帮助类.

SipSession

代表一个SIP会话. 该会话与一个SIP dialog相关联或者不与dialog关联的独立的事务.

SipSession.Listener

SIP会话相关的监听器, 比如当一个会话将要注册的时候(on registering)或者将要呼出的时候(on calling).

SipSession.State

定义SIP会话状态, 比如”注册”, “呼叫”, “呼入”.

SipRegistrationListener

一个接口, 是SIP注册事件的监听器.

创建Manifest:

如果我们要开发一个使用SIP API的APP, 需要记得该功能只有在Android2.3及以上版本才能支持. 同样, 在运行Android2.3及以上版本的设备中, 并非所有设备都提供对SIP的支持. 想要使用SIP, 要增加下列的权限到APP的manifest中:

l  android.permission.USE_SIP

l  android.permission.INTERNET

要确保APP可以只被安装在支持SIP的设备上, 需要增加如下权限:

l  <uses-sdk android:minSdkVersion=”9” />. 这表示我们的APP需要Android2.3及更高的版本.

要控制APP如何过滤不支持SIP的设备(比如在Google Play上), 增加下列权限到manifest中:

l  <uses-feature android:name=”android.hardware.sip.voip” />. 这声明了APP使用SIP API. 声明应该包含一个android:required属性, 表示我们是否希望APP被从不支持SIP的设备中过滤.

如果APP被设计来接收呼叫, 我们必须在manifest中定义一个接收器(BroadcastReceiver的子类):

l  <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>

创建一个SipManager:

想要使用SIP API, 我们的APP必须创建一个SipManager对象. SipManager可以实现这些功能:

l  初始化SIP会话.

l  初始化并接收会话.

l  使用SIPprovider注册和注销.

l  验证会话连接.

我们可以这样初始化一个SipManager:

public SipManager mSipManager = null;
...
if(mSipManager == null) {mSipManager = SipManager.newInstance(this);
}

注册一个SIP服务器:

一个典型的Android SIP APP涉及到一个或者多个用户, 他们中的每一个都有一个账户. 在一个Android SIP APP中, 每个SIP账户通过SipProfile对象来表示.

一个SipProfile定义了了一个SIP配置文件, 包括一个SIP账户, 一个域和服务器信息.跟SIP账户关联的配置文件叫做本地配置文件. 远端的设备的配置文件叫做peer配置文件. When your SIP application logs into the SIP server with the localSipProfile, this effectively registers the device as the location to send SIPcalls to for your SIP address.

本小节展示了如何创建一个SipProfile, 注册它到一个SIP server, 并跟踪注册事件. 我们可以这样创建一个SipProfile对象:

public SipProfile mSipProfile = null;
...SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();

下面的代码为呼叫和/或接收通用SIP呼叫打开了本地配置文件. 呼叫者可以通过mSipManager.makeAudioCall做后续调用. 这段代码还设置了actionandroid.SipDemo.INCOMING_CALL, 它将会在设备接受一个呼叫的时候被intent filter使用:

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服务provider.

mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {

public void onRegistering(String localProfileUri) {
    updateStatus("Registeringwith SIP Server...");
}

public void onRegistrationDone(String localProfileUri, long expiryTime) {
    updateStatus("Ready");
}
   
public void onRegistrationFailed(String localProfileUri, int errorCode,
    String errorMessage) {
    updateStatus("Registrationfailed.  Please check settings.");
}

当我们的APP用完了Profile的时候, 它应该被关闭, 并释放相关对象和从服务器注销设备:

public void closeLocalProfile() {
    if (mSipManager == null) {
       return;
    }
    try {
       if (mSipProfile != null) {
          mSipManager.close(mSipProfile.getUriString());
       }
     } catch (Exception ee) {
       Log.d("WalkieTalkieActivity/onDestroy", "Failed toclose local profile.", ee);
     }
}

启动一个音频呼叫:

想要启动一个音频呼叫, 我们必须已经定制这些内容:

l  一个SipProfile负责启动呼叫(localprofile), 和一个可用的SIP地址来接收呼叫(peer profile).

l  一个SipManager对象.

要启动一个音频呼叫, 我们应该设置一个SipAudioCall.Listener. 大部分客户端的交互发生在listener中. 下面的代码段里, 我们将看到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需要下面的参数:

l  一个本地SIP配置文件(caller).

l  一个peer SIP配置文件(userbeing called).

l  一个SipAudioCall.Listener来监听从SipAudioCall来的呼叫事件. 可以为空, 但是就像上面讲的, 监听器是一旦呼叫建立了就可以设置了.

l  超时的单位是秒

栗子:

call = mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener, 30);

接收呼叫:

想要接收呼叫, 一个SIP APP必须包含一个BroadcastReceiver的子类, 它要有能力响应呼入的intent. 所以必须做下面这几件事:

l  在AndroidManifest.xml中, 声明一个<receiver>.在SipDemo中, 它长这样: <receiver android:name=".IncomingCallReceiver"android:label="Call Receiver"/>.

l  实现receiver, 它是BroadcastReceiver的子类. 在SipDemo中, 这个类是IncomingCallReceiver.

l  用一个pendingintent初始化本地配置文件(SipProfile).

l  设置一个intentfilter来过滤代表呼入的action. 在SipDemo中, 这个action是android.SipDemo.INCOMING_CALL.

实现BroadcastReceiver的子类:

想要接收呼入, SIP APP必须继承BroadcastReceiver的子类. 当有呼叫接入的时候Android系统处理SIP呼入并广播一个呼入intent. 下面是SipDemo中实现BroadcastReceiver的代码:

/*** 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.*/@Overridepublic void onReceive(Context context, Intent intent) {SipAudioCall incomingCall = null;try {SipAudioCall.Listener listener = new SipAudioCall.Listener() {@Overridepublic 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();}}}
}

设置一个Intent filter来接收呼入:

当SIP服务器收到了一个新的呼入, 它将发出一个带有action string的intent. 在SipDemo中, 这个action是android.SipDemo.INCOMING_CALL.

下面来自SipDemo的代码片段展示了SipProfile对象如何通过一个基于action为android.SipDemo.INCOMING_CALL的pending intent创建的. 当SipProfile收到一个呼入的时候PendingIntent对象将会执行一个广播:

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中指定一个intentfilter, 或者在APP的onCreate()方法中来指定.

public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {...public IncomingCallReceiver callReceiver;...@Overridepublic void onCreate(Bundle savedInstanceState) {IntentFilter filter = new IntentFilter();filter.addAction("android.SipDemo.INCOMING_CALL");callReceiver = new IncomingCallReceiver();this.registerReceiver(callReceiver, filter);...}...
}

测试SIP APP:

要测试SIP APP, 需要这些:

l  一个Android2.3或以上的移动设备. SIP通过无线网运行. 我们必须在真机上测试, 虚拟设备无效.

l  一个SIP账户. 有很多不同的SIP提供者可以提供SIP账户.

l  如果我们要发起一个呼叫, 那么对方必须也是一个可用的SIP账户.

要测试一个SIP APP需要这样干:

1.      设备要连接无线网.

2.      设置移动设备为测试模式, 就像在Developingon a Device中描述的那样.

3.      在移动设备上运行APP.

4.      如果使用Android Studio, 我们可以通过Event log console查看APP的log输出.

5.      启动APP并查看日志…..囧

参考: https://developer.android.com/guide/topics/connectivity/sip.html

Android 中的SIP协议相关推荐

  1. android sip协议栈,基于Android平台及SIP协议的软电话系统的研究

    摘要: 随着互联网通信技术不断发展以及智能手机的日益流行,VoIP(Voice Over InternetProtocol)技术得到了越来越广泛的应用.VoIP技术能结合这两者改变传统长途电话费用高昂 ...

  2. android 网络通信方式,Android中基于TCP协议的网络通信

    一.Android网络简介 Android与服务器的通信方式主要有两种,一种是Http通信,另一种是Socket通信. HTTP通信:Android中内置HttpClient,这样可以发方便的发送Ht ...

  3. Android中的TCP协议与UDP协议

    TCP和UDP在网络传输中非常重要,在Android开发中同样重要. 什么是TCP? TCP:Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的 ...

  4. Android中基于TCP协议的网络通信之使用Socket进行通信

    TCP协议被称为一种端到端的协议.这是因为它为两台计算机的连接起到了重要作用:当一台计算机需要与另一台计算机进行接连时,TCP协议会他们之间建立一个连接:用于发送和接收数据的虚拟链路. TCP协议负责 ...

  5. Android中使用CoAP协议

    什么是CoAP协议 CoAP(Constrained Application Protocol)协议是一种物联网协议.与传统的PC.智能手机相比,物联网设备大多是资源限制型的,有限的CPU.RAM.F ...

  6. android 软电话 开发包-JNI 封装 SIP 协议,可进行二次开发应用于VOIP

    android 软电话 开发包-JNI 封装 SIP 协议,可进行二次开发应用于VOIP 该开发包为android平台下的JNI开发包,符合标准SIP协议,支持G729语音编码. 下载地址:源代码地址 ...

  7. android sip服务器,android sip协议通话实现

    android sip协议通话代码实现 简介 android里面的VOIP网络通话基于sip(Session initiation protocol)协议:android已经集成了sip协议栈,并提供 ...

  8. ipp协议 打印机 c语言,使用IPP(Internet打印协议)或LPR(行式打印机远程)在android中打印文件...

    我的要求是在不使用任何基于云的服务的情况下从 Android设备打印文件. 我已经能够使用"Raw"打印协议实现它,即只需将文件发送到端口9100的打印机IP地址.以下是代码片段: ...

  9. (SIP-1-话机注册)关于IP话机通过SIP协议注册到PBX电话交换机的全过程解析-如何看wireshark中的报文

    识别wireshark中各个报文所对应的表示含义 我们以第一个SIP包为例子. 该包发送的场景为:IP话机注册到PBX上所发送的第一个报文.我们点开可以看到,该报文一共被封装了五层.我们都知道TCP/ ...

最新文章

  1. 去大厂面试,说了没高并发经验,面试官还是抓着这个问!
  2. 随机森林算法参数解释及调优 转胡卫雄 RF模型可以理解成决策树模型嵌入到bagging框架,因此,我们首先对外层的bagging框架进行参数择优,然后再对内层的决策树模型进行参数择优
  3. 灵玖Nlpir Parser语义智能系统精准汉语分词
  4. 知识体系地图模型:你是如何有效地学习?
  5. UVA 572 BFS 图论入门
  6. 计算机专业office,2011 级计算机专业 Office 办公软件期末考试.doc
  7. 【Spring-AOP-学习笔记-3】@Before前向增强处理简单示例
  8. Hdu 1496 Equations
  9. java求最大子数组 (分治算法)
  10. 190407每日一句
  11. python编程机械_机器人Python编程与开发
  12. idea导入项目框架的方法
  13. C语言编写游戏的程序教程,用C语言写贪吃蛇游戏图文教程
  14. VS2013打包teamtalk
  15. Android Studio连接夜神模拟器
  16. 手机抓包之fiddler工具使用记录
  17. 操作系统之调度 (十) --- 处理机调度、高级调度、中级调度、低级调度...
  18. 多网卡多网关设置错误:RTNETLINK answers: File exists
  19. 为什么1KB=1024B,而不等于1000B?
  20. 湘潭大学信息安全课作业答案7

热门文章

  1. (问卷星)自动填写问卷星脚本python、selenium
  2. Netflix Movies and TV Shows --- 探索性数据分析
  3. 百度地图POI兴趣点查询
  4. linux删除用户及其所在工作目录
  5. 三峡风光计算机作业课程,三峡(郦道元).ppt
  6. python的opencv的图像对象存储的颜色通道_OpenCV大型阵列类型Mat类
  7. 微型贴片倾斜角度开关,防倒开关水平常开倾斜导通助力智能物流
  8. 金庸的小说人生(2)
  9. 我的理想600字作文计算机方面,我的理想作文600字
  10. 华安财险加大学贷险力度