android sip协议通话实现

android sip协议通话代码实现

  • 简介
    • android里面的VOIP网络通话基于sip(Session initiation protocol)协议;android已经集成了sip协议栈,并提供了相应的API给应用开放使用,开发者不需要了解具体的协议内容

  • 基于sip的网络通话基本过程

    1. 建立SIP服务器,关于如何建立SIP服务器,请参考这篇文章
    2. 需要所有参与通话的客户端注册用户到SIP服务器
    3. 一个客户端发起SIP通话到另一个客户端,这个消息首先发到SIP服务器,sip服务器收到消息后转发到目的客户端
    4. 目的客户端接收电话

  • 关于SIP网络通话的主要类和描述如下表所示:




      







    类/接口 描述
    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注册事件监 听器的接口


    • 在应用的AndroidManifest.xml中需要声明下面权限和特征

        
        
        
        
        
        
        
        
        
        
        
      

    • 构造一个SipManager实例.

        SipManager manager = SipManager.newInstance(this);
        //必须调用此方法创建,这是因为该方法会判断设备是否支持sip协议PackageManager.FEATURE_SIP
        如果有的android设备不支持,可以添加android.software.sip.voip.xml和android.software.sip.xml到/system/etc/permissions/下
      

    • 下面代码是注册一个账户到SIP服务器
        SipProfile.Builder builder = new SipProfile.Builder(username, domain); 
        //uesrname表示注册用户名,domain表示域,实际就是sip服务器ip
        builder.setPassword(password); //注册用户密码
        SipProfile me = builder.build(); //构造一个SipProfile对象,也就是相当于一个账户信息
        Intent i = new Intent();
        i.setAction("android.SipDemo.INCOMING_CALL");
        PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA); 
        //构造一个PendingIntent对象,这样当sip Service收到一个通话请求时,
        //例如收到一个来电时,SipService会调用PendingIntent的send方法发送相应广播消息给调用者,也就是当前的SipProfile对象.
        manager.open(me, pi, null); //此处就是用于注册一个账户到sip服务器
    
    //注册一个监听器,用于获取注册账户时的通知状态,当然也可以不注册.
    
            manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
            public void onRegistering(String localProfileUri) { //正在注册
            }
    
            public void onRegistrationDone(String localProfileUri, long expiryTime) {//注册成功
            }
    
            public void onRegistrationFailed(String localProfileUri, int errorCode,
                    String errorMessage) {
            }
        });
    

    • 开始拨号,从一个设备拨打电话到另一个设备,前提是两个设备都已注册,且知道目的设备的sip账户信息.

        try {
            SipAudioCall.Listener listener = new SipAudioCall.Listener() {
                // Much of the client's interaction with the SIP Stack will
                // happen via listeners.  Even making an outgoing call, don't
                // forget to set up a listener to set things up once the call is established.
                @Override
                public void onCallEstablished(SipAudioCall call) { //当网络通话建立了之后,会收到此通知
                    call.startAudio(); //启动音频
                    call.setSpeakerMode(true); //设置为扬声器模式,也就是开启回声抑制
                    call.toggleMute(); //切换静音,注意默认为非静音,调用此方法后变为静音了
                }
        
                @Override
                public void onCallEnded(SipAudioCall call) {
                }
            };
        
            //注意此处的makeAudioCall方法就是打网络电话的,localProfile就是本地设备的SipProfile对象,
            //PeerProfile就是目标设备的SipProfile对象,listener是监听器
                SipAudioCall call = manager.makeAudioCall(localProfile.getUriString(),
                 PeerProfile, listener, 30);}catch (Exception e) {    }
      
      • 注意,此处的SipProfile的内容格式,例如,LocalProfile的url格式为"sip:[email protected]",PeerProfile的url格式为"sip:[email protected]",url内容也就是sip账户,
        其中:

          (1)  sip: 表示采用sip协议
          (2) abcde123和abcde234是用户名, 也称为帐号.  用字母和数字均可。
          (3) 10.0.149.240是sip账户所属的服务器地址(当然也可以用域名来表示)
          (4)  SIP协议默认端口为5060,  默认采用UDP传输,如果需要指定端口为5678,可以修改为sip:[email protected]:5678,
        

    从localProfile和peerProfile指定的内容可以看出,账户名作为唯一标识,由sip服务器来解析账户名,从而找到对应的目的主机.

    • 目的端接收通话
      • 根据前面的分析,一个设备拨打电话到目的设备时,在目的设备的sip服务(SipService)会发送一个广播消息给当前的目的设备。因此必须提前注册一个广播接收器来接收此消息,这样才知道有来电通知,可以在AndroidManifest.xml静态注册,也可以在应用程序中动态注册,因此下面代码必须放在广播接收器的onReceive()方法中:

      • 案例:

        try {

          SipAudioCall.Listener listener = new SipAudioCall.Listener() {
              @Override
              public void onRinging(SipAudioCall call, SipProfile caller) {
                  try {
                      call.answerCall(30);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          };
        
          //takeAudioCall就表示需要为接听电话创建一个SipAudioCall对象.
          SipAudioCall incomingCall = manager.takeAudioCall(intent, listener);
          incomingCall.answerCall(30); //接听电话
          incomingCall.startAudio(); //启动音频
          incomingCall.setSpeakerMode(true);
        
        • 注意点:

                1.所有参与网络通话的设备和sip服务器的网络必须是连接的,网络类型可以是以太网,wifi,mobile等都可以.
                如果通话过程有问题,可以检测设备网络收发包是否正常.
                2.对应的设备必须支持sip,voip功能才行.

你可能感兴趣的:(android sip协议通话实现)