码迷,mamicode.com
首页 > 移动开发 > 详细

android-NGN-stack中文文档

时间:2015-03-10 11:53:19      阅读:531      评论:0      收藏:0      [点我收藏+]

标签:

前言

android-ngn-stack是android2.x(或更高版本)NGN(下一代网络)软件栈。ngn基于doubango框架。doubango是目前世界上最先进的开源3GPP IMS/RCS嵌入式和桌面系统架构。其主要目的就是提供一个开放源码为开发者构建自己的VoIP应用。这一框架提供了一组独特的特征,从音频/视频呼叫,内容共享,消息,会议增强通信社交存在。所有这些功能都是按照GMSA RCS,3GPP IMS或VoLTE标准实施。

介绍

该文档由(Doubango电信)提供,以帮助开发人员快速构建新的android多媒体应用。如果你是一名开发人员,正在寻找开发NGN(网络电话,消息,视频会议,…)或丰富的android应用程序那么你选对地方了。如果你想获得帮助,或者想给我们一些反馈,那么请访问我们的网站http://code.google.com/p/imsdroid/

Doubango解决方案

android-ngn-stack是Doubango的解决方案,其中包括许多组件等部分;

客户端:

1、 Boghe:IMS/RCS Windows客户端

2、 IMSDroid:Android版IMS/RCS客户端采用android-ngn-stack

3、iDoubs:IOS(iPhone,iPad和iPod Touch)版IMS/RCS客户端

服务端:

4、OpenVCS:OpenVCS代表开源视频会议服务器和用于管理多点控制单元(MCU)。每个MCU(又称桥接器)最多可处理64个参与者

5、Flash2IMS:Adobe? 闪存SIP/IMS网管

亮点(支持特征):

6、SIP(RFC 3261,3GPP TS 24.229 Rel-9)

7、TCP和UDP IPv4或IPv6

8、信号压缩,SigComp(RFC3320,3485,4077,4464,4465,4896,5049,5112和1951)

9、加强版通讯录(XCAP存储,授权,presence)

10、发布第三版GSMA富通信套件

11、部分支持声音档案V1.0.0(GSMA VoLTE)

12、部分支持MMTEL UNI(GSMA RCS和GSMA VoLTE)

13、基本的IMS-AKA的注册(包括AKA-V1和AKA-V2),MD5

14、3GPP IMS早期安全性(3GPP TS33.978)

15、Proxy-CSCF使用DNS NAPTR+SRV

16、3GPP对SIP私有头(Headers)扩展

18、服务路由(Service Route discovery)

19、订阅注册事件包(履行网络发起(re/de/un)注册(registration)事件)

20、3GPP SMS IP(3GPP TS23.038,24.040,24.011,24.431和24.451)

21、语音呼叫(G729AB1, AMR-NB, iLBC, GSM, PCMA, PCMU, Speex-NB)

22、视频呼叫((H264, MP4V-ES, Theora, H.263, H.263-1998, H.261)

23、DTMF (RFC 4733)

24、使用前提QoS协商(RFC 3312, 4032 和5027)

25、SIP会话计时器(RFC4028)

26、临时响应确认( Provisional Response Acknowledgments)(PRACK)

27、保持通信(3GPP TS 24.610)

28、消息等待提示(3GPP TS 24.606)

29、使用ENUM协议调用E.164号码(RFC3761)

30、NAT穿越使用STUN2(RFC5389)与可能性自动发现服务器
      通过使用DNS SRV(TURN已经实现,ICE正在测试)

31、一对一和群聊

32、文件传输和内容共享

建立NGN项目

这部分内容解释如果使用Eclipse建立一个NGN项目

检出(Checking)源代码

要检出NGN源代码,您首先需要一个SVN客户端。使用此命令检出项目源代码:

svn checkout http://imsdroid.googlecode.com/svn imsdroid

该库的源代码在:

imsdroid/branches/2.0/android-ngn-stack

导入NGN项目到Eclipse

NGN项目是下一代网络库

1、打开eclipse

2、选择文件(File)—>导入(Import)—>常规(General)—>现有项目到工作区(Existing Project into workspace)

3、选择android-ngn-stack文件夹,然后单击完成(Finish)

使用Eclipse创建你的第一个NGN应用

1、打开Eclipse,然后选择文件(File)—>新建(New)—>Android Project(android项目)

2、从下一个窗口(”新建Android项目(New Android Project)”)填充如下文本字段:

项目名称(Project name):myFirstApp

路径(Location):<设置任意路径>

构建目标版本(Build Targe):至少Android 2.0

应用程序名称(Application name):myFirstApp

包名称(Package name):org.doubango.test

选中 ”create activity”并命名为”Main”

单击Finish(完成)创建项目

译者注:可能eclipse是操作页面有区别,但基本一致。

3、从Eclipse package explorer中,右键单击myFirstApp,选择”(属性)Properties”然后选择Android从属性窗口,选择“(添加)add”按钮,然后从列表中选择android-ngn-stack库

4、选择“Java编译器(Java Compiler)”从左边更改1.5版本到1.6

5、从左侧选择“Java构建路径(Java Build Path)”,然后选择”库(Libraries)”选项卡。单击“添加JAR文件…(Add JARS…)”然后选择文件”android-ngn-stack/libs/simple-xml-2.3.4.jar”然后“确认(OK)”关闭窗口

6、单击”确认(OK)”关闭窗口

设置Android权限

为了使用该框架你必须在AndroidManifest.xml清单文件添加一些用户权限。

打开myFirstApp/AndroidManifest.xml ,然后填充如下这些权限配置:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY" />

声明你的应用程序作为NGN

如果你的编程水平高建议你把应用程序声明为NGN

1、从”Eclipse package explorer”打开”AndroidManifest.xm“选择“Application”标签下点击浏览(上右Name)然后从列表选择”NgnApplication”

架构(Architecture )

该协议栈提供了三个层次的编程:低,中,高。

构建和运行项目之前,您一个看一看讲解如何设置一个NGN项目

底层

此级别允许您直接通过JNI来访问doubango功能。这个水平是最灵活的一个,但是很难控制(but is out of scoop)因为它太难管理。在这个级别所有的功能都在一个单一包:org.doubango.tinyWRAP例如,下面的代码演示了如果注册到SIP/IMS服务器:

         final String realm = "sip:doubango.org";
        final String privateIdentity = "001";
        final String publicIdentity = "sip:001@doubango.org";
        final String password = "my secret";
        final String proxyHost = "192.168.0.1";
        RegistrationSession registrationSession;

        // Sip Callback
        final SipCallback callback = new SipCallback() {
            @Override
            public int OnDialogEvent(DialogEvent e) {
                final SipSession sipSession = e.getBaseSession();
                final long sipSessionId = sipSession.getId();
                final short code = e.getCode();
                switch (code) {
                case tinyWRAPConstants.tsip_event_code_dialog_connecting:
                    if (registrationSession != null
                            && registrationSession.getId() == sipSessionId) {
                        // Registration in progress
                    }
                    break;
                case tinyWRAPConstants.tsip_event_code_dialog_connected:
                    if (registrationSession != null
                            && registrationSession.getId() == sipSessionId) {
                        // You are registered
                    }
                    break;
                case tinyWRAPConstants.tsip_event_code_dialog_terminating:
                    if (registrationSession != null
                            && registrationSession.getId() == sipSessionId) {
                        // You are unregistering
                    }
                    break;
                case tinyWRAPConstants.tsip_event_code_dialog_terminated:
                    if (registrationSession != null
                            && registrationSession.getId() == sipSessionId) {
                        // You are unregistered
                    }
                    break;
                }

                return 0;
            }

            @Override
            public int OnRegistrationEvent(RegistrationEvent e) {
                // low level events
                return 0;
            }
        };
        // Create the SipStack
        SipStack sipStack = new SipStack(callback, realm, privateIdentity,
                publicIdentity);
        // Set Proxy Host and port
        sipStack.setProxyCSCF(proxyHost, 5060, "UDP", "IPv4");
        // Set password
        sipStack.setPassword(password);
        if (sipStack.isValid()) {
            if (sipStack.start()) {
                registrationSession = new RegistrationSession(sipStack);
                registrationSession.setFromUri(publicIdentity);
                // Send SIP register request
                registrationSession.register_();
            }
        }

中级

这个水平是建立在低水平的。这个水平的主要特点是,它的灵活性,而不过于复杂,所有低级别的功能都封装在全面的API里。例如,如果你想实现一个多层次(multi-stack)(多账户(multi-account))的应用程序,这是不错的选择。

高层次

这个水平是建立在底层之上且以后容易得多。高级别由一组服务有单一的NGN引擎实例管理。每个服务负责特定任务。例如,你有一个服务SIP,一个用于联系人管理,一个网络等等

NGN引擎

该引擎是一个包含所有服务的一个黑盒子。你必须始终通过引擎检索服务。

你还必须通过NGN引擎启动/停止服务。

下面的代码演示了然后实例化一个引擎

//获取一个引擎实例。这个函数总是服务相同的实例
//这意味着,只要你想你可以从你的代码任何地方调用它
final NgnEngine mEngine = NgnEngine.getInstance();

下面的代码演示如何从引擎得到一些服务:

//获取配置服务
INgnConfigurationService mConfigurationService = mEngine.getConfigurationService();
//获取SIP/IMS服务
INgnSipService mSipService = mEngine.getSipService();
//等等等等

下面的代码演示如何启动/停止引擎。

  //启动引擎
  mEngine.start();
  //停止引擎
  mEngine.stop();
  //启动/停止所有基础服务引擎
  /**
  你应该在你的Android扩展类定义应用程序全局对象
  */

基础服务(Base Service)

所有的NGN服务都继承这个类

 联系服务(Contact Service)

联系服务用于检索来自本地地址薄中的联系人

HTTP/HTTPS服务(HTTP/HTTPS Service)

HTTP/HTTPS服务用于检索发送和接收来自远程服务HTTP/HTTPS协议的数据

网络服务(Network Service)

网络服务用于管理WiFi和3G/4G网络连接

声音服务(Sound Service)

该服务是用来播放(铃声,回铃音,警报,…)。使用它之前你必须启动NGN引擎服务。

     //获取和实例化NGN引擎
     NgnEngine mEngine = NgnEngine.getInstance();
    //播放回铃音
     mEngine.getSoundService().startRingBackTone();
    //停止回铃音
     mEngine.getSoundService().stopRingBackTone();

存储服务(Storage Service)

该服务用于管理存储功能

配置服务(Configuration Service)

配置服务用于存储用户偏好。保存所有喜好该服务是持久的,这意味着你可以在应用程序/设备重启找回它。你不应该自己创建或启动此服务。

这项服务的一个实例可以这样检索的:

     final INgnConfigurationService mConfigurationService =NgnEngine.getInstance().getConfigurationService();

历史服务(History Service)

该服务用于存储/检索历史事件(音频/视频,消息,…)。你不应该自己创建或启动此服务。

这项服务的一个实例是这样检索的:

     final INgnHistoryService mHistoryService = NgnEngine.getInstance().getHistoryService();

SIP/IMS服务(SIP/IMS Service)

该服务用于管理SIP/IMS栈。你不应该自己创建或启动此服务。

这项服务的一个实例可以这样检索:

    final INgnSipService mSipService = NgnEngine.getInstance().getSipService();

音频/视频通话(Audio/Video calls)

音频呼叫(Making audio call)

得到音频/视频通话有关通知状态请看这里

     final String remoteUri = "+33600000000";
    final String validUri = NgnUriUtils.makeValidSipUri(remoteUri); 
    // sip:+33600000000"@doubango.org
    NgnAVSession avSession = NgnAVSession.createOutgoingSession(
                                        mSipService.getSipStack(),
                                        NgnMediaType.Audio);
    if (avSession.makeCall(validUri)) {
        Log.d(TAG, "all is ok");
    } else {
        Log.e(TAG, "Failed to place the call");
    }

视频通话(Making video call)

得到音频/视频通话有关通知状态请看这里

     final String remoteUri = "+33600000000";
     final String validUri = NgnUriUtils.makeValidSipUri(remoteUri);
     // sip:+33600000000"@doubango.org
     NgnAVSession avSession = NgnAVSession.createOutgoingSession(
                                        mSipService.getSipStack(),
                                        NgnMediaType.AudioVideo);
     if (avSession.makeCall(validUri)) {
         Log.d(TAG, "all is ok");
     } else {
         Log.e(TAG, "Failed to place the call");
     }

短信与聊天(SMS and Chat)

3GPP Binary SMS

      // 短信中心
       final String SMSC = "sip:+3310000000@doubango.org"; 
      // 对方
       final String remotePartyUri = "sip:+336000000@doubango.org"; 
      final String textToSend = "hello world!";
      final NgnMessagingSession imSession =
      NgnMessagingSession.createOutgoingSession(mSipService.getSipStack(),remotePartyUri);
      if(!imSession.SendBinaryMessage(textToSend,SMSC)){
         Log.e(TAG,"Failed to send");
         }else{
         Log.d(TAG,"Message sent");
         }
      //发布会话
      NgnMessagingSession.releaseSession(imSession);

寻呼机模式IM(Pager Mode IM)

     final String textToSend = "hello world!";
     // 对方
     final String remotePartyUri = "sip:+336000000@doubango.org"; 
     final NgnMessagingSession imSession =
     NgnMessagingSession.createOutgoingSession(mSipService.getSipStack(),remotePartyUri);
     if(!imSession.sendTextMessage(textToSend)){
        Log.e(TAG,"Failed to send");
       }else{
        Log.d(TAG,"Message sent");
       }
      // 发布会话
      NgnMessagingSession.releaseSession(imSession);

监听事件(Listening to events)

SIP/IMS服务负责所有任务相关的SIP协议(注册,音频/视频通话,寻呼机模式IM),你可以订阅事件改变当注册状态变化,新的SIP消息被接收,新得到的通知,输入的音频/视频通话,…所有通知通过不止一次异步查询的方式发送给您。

监听状态注册状态改变(Listening for registration state change)

你可以监听得到当你登录/退出时注册状态变化通知

     final TextView mTvInfo = (TextView) findViewById(R.id.textViewInfo);
     final BroadcastReceiver mSipBroadCastRecv = new BroadcastReceiver() {
           @Override
           public void onReceive(Context context, Intent intent) {
                  final String action = intent.getAction();

                  // Registration Event
                  if (NgnRegistrationEventArgs.ACTION_REGISTRATION_EVENT.equals(action)) {
                      NgnRegistrationEventArgs args = intent.getParcelableExtra(NgnEventArgs.EXTRA_EMBEDDED);
                      if (args == null) {
                         Log.e(TAG, "Invalid event args");
                         return;
                      }
                      switch (args.getEventType()) {
                      case REGISTRATION_NOK:
                           mTvInfo.setText("Failed to register :(");
                           break;
                      case UNREGISTRATION_OK:
                           mTvInfo.setText("You are now unregistered :)");
                           break;
                      case REGISTRATION_OK:
                           mTvInfo.setText("You are now registered :)");
                           break;
                      case REGISTRATION_INPROGRESS:
                           mTvInfo.setText("Trying to register...");
                           break;
                      case UNREGISTRATION_INPROGRESS:
                           mTvInfo.setText("Trying to unregister...");
                           break;
                      case UNREGISTRATION_NOK:
                           mTvInfo.setText("Failed to unregister :(");
                           break;
                     }
                }
           }
      };
      final IntentFilter intentFilter = new IntentFilter();
      intentFilter.addAction(NgnRegistrationEventArgs.ACTION_REGISTRATION_EVENT);
      registerReceiver(mSipBroadCastRecv, intentFilter);

监听音频/视频通话状态变化(Listening for audio/video call state change)

你可以监听获得音频/视频呼叫状态变更通知,呼叫状态变更(呼入(incoming),正在呼叫(incall),外呼(outgoing),终止(terminated))

       final BroadcastReceiver mSipBroadCastRecv = new BroadcastReceiver() {
           @Override
           public void onReceive(Context context, Intent intent) {
               InviteState state;
               final String action = intent.getAction();
               if (NgnInviteEventArgs.ACTION_INVITE_EVENT.equals(action)) {
                   NgnInviteEventArgs args = intent.getParcelableExtra(NgnEventArgs.EXTRA_EMBEDDED);
                       if (args == null) {
                          Log.e(TAG, "Invalid event args");
                          return;
                        }
                        Log.d(TAG,"This is anevent for session number "+ args.getSessionId());
                        // Retrieve the sessionfrom the store
                        NgnAVSession avSession = NgnAVSession.getSession(args.getSessionId());
                        if (avSession == null) {
                        Log.e(TAG, "Cannot find session");
                        return;
                        }
                        switch ((state = avSession.getState())) {
                        case NONE:
                        default:
                             break;
                        case INCOMING:
                            Log.i(TAG, "Incoming call");
                             break;
                       case INPROGRESS:
                           Log.i(TAG, "Call in progress");
                             break;
                       case REMOTE_RINGING:
                           Log.i(TAG, "Remote party is ringing");
                            break;
                       case EARLY_MEDIA:
                           Log.i(TAG, "Early media started");
                            break;
                       case INCALL:
                            Log.i(TAG, "Call connected");
                            break;
                       case TERMINATING:
                            Log.i(TAG, "Call terminating");
                            break;
                       case TERMINATED:
                            Log.i(TAG, "Call terminated");
                            break;
                      }
                 }
            }
       };

配置(Configuration)

试图注册到SIP/IMS服务你必须配置你的凭证。配置服务负责这些任务。使用喜好配置服务都是持久的,这意味着应用程序/设备重新启动。配置信息,你必须得到一个实例这样一个引擎服务:

   final INgnConfigurationService mConfigurationService

域(Realm)

域是验证域的名称。它应该是一个有效的SIP URI(例如:sip:open-ims.test or sip:10.0.0.1 )。该域是强制性的,栈开始之前应该设置,一旦栈开始时你不能改变它的值。如果Proxy-CSCF的地址找不到,那么栈会自动使用DNS NAPTR+SRV/或用于动态搜索的DHCP机制。域的值将用作于DNS NAPTR查询的域名中。欲了解更多有关于如何设置CSCF IP地址和端口的信息,请参见第22.1.8

   final String myRealm = "sip:doubango.org";
   final boolean bSaveNow = true;
   mConfigurationService(ConfigurationEntry.NETWORK_REALM, myRealm, bSaveNow);

IMS 私有标识(IMPI)(IMS Private Identity (IMPI))

IMS私有标识(又名IMPI)是分配给一个家庭网络用户(或UE)的唯一标识符。它可以是一个SIP URI(例如:sip:bob@open-ims.test),一个电话URI(例如,电话:+33100000)或者如何字母数字字符串(例如:bob@open-ims.test 或 bob)它被用来验证UE(SIP授权/Proxy-Authorization用户名字段)。在现实世界中,应该存储在UICC(通用集成电路卡)。对于那些使用该IMS协议栈作为基本(IETF)的SIP协议栈,该IMPU验证名称应与他们一致。该IMPI是强制性的,栈开始之前,应该设置。你不应该在栈被启动去改变IMPI。

IMPI被栈启动

final String myIMPI = "33446677887";
 final boolean bSaveNow = true;
 mConfigurationService(ConfigurationEntry.IDENTITY_IMPI, myIMPI, bSaveNow);

IMS公共标识(IMPU)(IMS Public Identity (IMPU))

正如它的名字一样,它是你的公共可见的标识符,你愿意接听电话或者任何需求。一个IMPU可以是一个SIP或者URI(比如电话:tel:+33100000 或 sip:bob@openims.test)。在IMS中,用户可具有相关联的独特的IMPI个数的IMPU。对于那些使用该IMS栈基本的SIP协议栈,该IMPU应该与他们的SIP URI一直。该IMPU是强制性的,栈开始前,一个进行设置。你不应该在栈被启动去改变IMPU。

如果你想在栈开始改变IMPU(而不是,改变P-Preferred-Identity默认的公共标识符)

final boolean bSaveNow = true;
 final String myIMPU = "sip:33446677887@doubango.org";
 mConfigurationService(ConfigurationEntry.IDENTITY_IMPU, myIMPU, bSaveNow);

首选身份(Preferred Identity)

作为一个用户有多个IMPU,它可以为呼出每个请求,定义IMPU被使用设置首选身份。用户检查该IPMU没有禁止。一个是IMPU如果它没有出现在返回200和相关联的URL被禁止。缺省情况下,首选的身份是在相关联的标识列表中第一个URL。如果IMPU用于注册的用户被禁止,那么栈将使用URI返回默认SCSCF。

你不应该手动设置此SIP(P-Preferred-Identity)它是由栈

Proxy-CSCF 主机地址(Proxy-CSCF Host address)

Proxy-CSCF 主机是SIP的IP地址(192.168.0.1)或FQDN(doubango.org)注册商。你应该在必要时设置代理CSCF地址和IP。动态机制(DNS NAPTR/或DHCPv4/v6)应该被使用。

下面的代码演示了如何设置ProxyCSCF IP地址和端口。如果端口找不到,那么它的默认值是5060

// Sets IP address
 final String proxyHost = "192.168.0.1";
 mConfigurationService(ConfigurationEntry.NETWORK_PCSCF_HOST, proxyHost);
 // Sets port
 final int proxyPort = 5060;
 mConfigurationService.putInt(ConfigurationEntry.NETWORK_PCSCF_PORT, proxyPort);
 Save changes
 mConfigurationService.commit();

android-NGN-stack中文文档

标签:

原文地址:http://www.cnblogs.com/ProgrammerHelloWorld/p/4325388.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!