SIP 之 imsdroid学习-----阿冬专栏

简介

imsdroid 是全功能的SIP / IMS的客户端,它基于doubango框架开发的app,doubango是目前世界上最好的3GPP IMS/RCS 嵌入式桌面系统框架,该框架提供了一套独特的功能,包括音频/视频通话、内容共享、消息、会议、通讯录等。

官网地址:http://code.google.com/p/imsdroid/

组件

1、Boghe 

IMS/ RCS Windows客户端

2、IMSDroid

IMS/ RCS Android客户端(使用NGN堆栈)

3、iDoubs

IMS/ RCS iOS客户端(iPhone,iPad和iPod Touch)

4、OpenVCS

开源视频会议服务器,用于管理多点控制单元(MCU),每个MCU可以处理多达64人参与

5、Flash2IMS

使用Adobe Flash 的SIP/ IMS网关

支持功能

1、SIP ( RFC 3261 3GPP TS 24.229 REL- 9 )

2、 IPv4 IPv6  TCP UDP

3、信号编码  SigComp (RFC 3320 、3485、 4077 、4464 、4465、4896、5049、5112、1951)

4、通讯录

5、GSMA 通信

6、 语音(GSMA VoLTE)

7、GSMA RCS and GSMA VoLTE

8 、IMS 登陆 MD5加密

9、3GPP

10、服务路由探索

11、注册事件监听(注册事件、拨打事件、来电事件、消息事件。。。)

12、3GPP IP ( 3GPP TS 23.038 、24.040 、 24.011、 24.341、24.451短信)

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

14、视频通话( H264、MP4V - ES 、Theora、 H.263 、 H.263 -1998 、H.261 )

15、双音多频DTMF ( RFC 4733 )

16、解决网络延迟和阻塞技术QoS negotiation using Preconditions (RFC 3312, 4032 and 5027)

17、SIP会话定时器( RFC 4028 )

18、临时响应( PRACK )

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

20、消息等待指示( 3GPP TS 24.606 )

21、E.164号码呼叫通过使用ENUM协议( RFC 3761 )

22、NAT穿越

23、一对一和群组聊天


项目如图

SIP 之 imsdroid学习-----阿冬专栏_第1张图片

效果如图

SIP 之 imsdroid学习-----阿冬专栏_第2张图片SIP 之 imsdroid学习-----阿冬专栏_第3张图片SIP 之 imsdroid学习-----阿冬专栏_第4张图片SIP 之 imsdroid学习-----阿冬专栏_第5张图片SIP 之 imsdroid学习-----阿冬专栏_第6张图片SIP 之 imsdroid学习-----阿冬专栏_第7张图片SIP 之 imsdroid学习-----阿冬专栏_第8张图片SIP 之 imsdroid学习-----阿冬专栏_第9张图片SIP 之 imsdroid学习-----阿冬专栏_第10张图片SIP 之 imsdroid学习-----阿冬专栏_第11张图片SIP 之 imsdroid学习-----阿冬专栏_第12张图片SIP 之 imsdroid学习-----阿冬专栏_第13张图片

项目分析

如何注册一个SIP / IMS服务器?如下:

 final String realm = "sip:doubango.org";
 final String privateIdentity = "001";
 final String publicIdentity = "sip:[email protected]";
 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_();
                }
 }


初始化引擎:

final NgnEngine mEngine = NgnEngine.getInstance();
获取配置服务:

 INgnConfigurationService mConfigurationService = mEngine.getConfigurationService();
获取SIP / IMS服务:

 INgnSipService mSipService = mEngine.getSipService();
启动/停止引擎:

 // Starts the engine
 mEngine.start();
 // Stops the engine
 mEngine.stop();
Contact Service
服务用于检索从本地地址簿

HTTP/HTTPS Service
HTTP / HTTPS服务用来发送和检索数据到/从远程服务器使用HTTP / HTTPS协议

Network Service
网络服务是用来管理WiFi和3G/4G网络连接

Sound Service
铃声,彩铃业务,警报

 //获取和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 Service
管理SIP/IMS栈

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

Audio/Video calls
音频/视频通话


得到有关的音频/视频呼叫状态如下:
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");
 }

拨打电话如下:
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短信流
 final String SMSC = "sip:[email protected]"; // SMS Center
 final String remotePartyUri = "sip:[email protected]"; // remote party
 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");
 }
 // release session
 NgnMessagingSession.releaseSession(imSession);

IM寻呼模式
final String textToSend = "hello world!";
 final String remotePartyUri = "sip:[email protected]"; // remote party
 final NgnMessagingSession imSession = NgnMessagingSession.createOutgoingSession(mSipService.getSipStack(), 
 remotePartyUri);
 if(!imSession.sendTextMessage(textToSend)){
                Log.e(TAG,"Failed to send");
 }
 else{
 Log.d(TAG,"Message sent");
 }
 // release session
 NgnMessagingSession.releaseSession(imSession);

监听事件
SIP/IMS服务负责对SIP协议相关的所有任务(登记,音频/视频电话,寻呼机模式IM…)等都有监听,所有的通知都是异步方式。

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
 You can listen to the audio/video call state change in order to get notified when the 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 an event for session number 

"+args.getSessionId());                         
                                                                // Retrieve the session from 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;
                                                                }
                                                }
                                }
                };

Realm
这个领域是身份验证的域名称,一个有效的SIP URI(sip:open-ims.test  or sip:10.0.0.1),程序开始之前设置信息,如果Proxy-CSCF的地址丢失,那么堆栈将自动使用DNS SRV NAPTR 和DHCP机制动态发现。
 final String myRealm = "sip:doubango.org"; 
 final boolean bSaveNow = true;
 mConfigurationService(ConfigurationEntry.NETWORK_REALM, myRealm, bSaveNow);

SIP 之 imsdroid(二)

上篇简单分析imsdroid项目,本篇继续上一篇继续分析。


继续分析

IMS Private Identity (IMPI) 身份认证 用户的id 例如:banketree
IMS Public Identity (IMPU) 公共认证 如:sip:[email protected]


服务设置:

[java]  view plain copy
  1. // Sets IP address  
  2. final String proxyHost = "192.168.0.1";  
  3. mConfigurationService(ConfigurationEntry.NETWORK_PCSCF_HOST, proxyHost);  
  4. // Sets port   
  5. final int proxyPort = 5060;  
  6. mConfigurationService.putInt(ConfigurationEntry.NETWORK_PCSCF_PORT, proxyPort);  
  7. Save changes  
  8. mConfigurationService.commit();  

类接口

org.doubango.ngn.sip.NgnAVSession

[java]  view plain copy
  1. boolean makeCall (String remoteUri)  
  2. boolean makeVideoSharingCall (String remoteUri)  
  3. Context getContext ()  
  4. void setContext (Context context)  
  5. final View startVideoConsumerPreview ()  
  6. final View startVideoProducerPreview ()  
  7. boolean isSendingVideo ()  
  8. void toggleCamera ()  
  9. void setRotation (int rot)  
  10. void setSpeakerphoneOn (boolean speakerOn)  
  11. void toggleSpeakerphone ()  
  12. void setState (InviteState state)  
  13. boolean acceptCall ()  
  14. boolean hangUpCall ()  
  15. boolean holdCall ()  
  16. boolean resumeCall ()  
  17. boolean isLocalHeld ()  
  18. boolean isRemoteHeld ()  
  19. boolean sendDTMF (int digit)  
  20. Static Public Member Functions  
  21. static NgnAVSession createOutgoingSession (NgnSipStack sipStack, NgnMediaType mediaType)  
  22. static NgnAVSession getSession (long id)  
  23. static int getSize ()  
  24. static boolean hasSession (long id)  
  25. static boolean hasActiveSession ()  
  26. static NgnAVSession getFirstActiveCallAndNot (long id)  
  27. static boolean makeAudioCall (String remoteUri, NgnSipStack sipStack)  
  28. static boolean makeAudioVideoCall (String remoteUri, NgnSipStack sipStack)  

[java]  view plain copy
  1. boolean org.doubango.ngn.sip.NgnAVSession.acceptCall () //接受一个传入的音频/视频呼叫  
  2. Returns:  
  3. true is succeed and false otherwise   
  4. See also:  
  5. hangUpCall()    
  6.   
  7. static NgnAVSession org.doubango.ngn.sip.NgnAVSession.createOutgoingSession (NgnSipStack sipStack, NgnMediaType mediaType)   
  8.   
  9. [static]  
  10. 创建一个去电音频/视频会话  
  11. Parameters:  
  12. sipStack    the IMS/SIP stack to use to make the call   
  13. mediaType   the media type.   
  14. Returns:一个去电音频/视频会话  
  15.   
  16. Context org.doubango.ngn.sip.NgnAVSession.getContext ()//获取此会话相关的上下文   
  17. Returns:上下文   
  18.    
  19. static NgnAVSession org.doubango.ngn.sip.NgnAVSession.getFirstActiveCallAndNot (long id) [static]  
  20. 根据指定ID获取不同于第一有源音频/视频会议  
  21.   
  22. Parameters:会话id  
  23. Returns:一个会议  
  24.   
  25.   
  26. static NgnAVSession org.doubango.ngn.sip.NgnAVSession.getSession (long id) [static]  
  27. 检索音频/视频会话的ID  
  28.   
  29. Parameters:会议id  
  30. Returns:一个会议  
  31.   
  32. static int org.doubango.ngn.sip.NgnAVSession.getSize () [static]  
  33. 获取一些暂停的音频/视频会议  
  34. Returns:会议  
  35.   
  36. boolean org.doubango.ngn.sip.NgnAVSession.hangUpCall ()  
  37. 通话结束  
  38. Returns:  
  39.   
  40. static boolean org.doubango.ngn.sip.NgnAVSession.hasActiveSession () [static]  
  41. 一个活动的音频/视频会议  
  42. Returns:  
  43.   
  44. static boolean org.doubango.ngn.sip.NgnAVSession.hasSession (long id) [static]  
  45. 是否有会议  
  46.   
  47. Parameters:会议id  
  48. Returns:  
  49.   
  50. boolean org.doubango.ngn.sip.NgnAVSession.holdCall ()  
  51. 检查是否有保持呼叫  
  52. Returns:  
  53.   
  54. boolean org.doubango.ngn.sip.NgnAVSession.isLocalHeld ()  
  55. 是否为内部电话  
  56. Returns:  
  57.   
  58. boolean org.doubango.ngn.sip.NgnAVSession.isRemoteHeld ()  
  59. 是否为远程电话  
  60. Returns:   
  61.   
  62. boolean org.doubango.ngn.sip.NgnAVSession.isSendingVideo ()  
  63. 是否发送视频  
  64.   
  65. static boolean org.doubango.ngn.sip.NgnAVSession.makeAudioCall (String remoteUri, NgnSipStack sipStack) [static]  
  66. 音频呼叫   
  67.   
  68. Parameters:  
  69. remoteUri   the remote party uri. Could be a SIP/TEL uri, nomadic number, MSISDN number, ... example:   
  70.   
  71. sip:test@doubango.org, tel:+3360000000078888667, ...   
  72. sipStack    the SIP/IMS stack to use    
  73.   
  74. static boolean org.doubango.ngn.sip.NgnAVSession.makeAudioVideoCall (String remoteUri, NgnSipStack sipStack) [static]  
  75. 同上  
  76.   
  77. boolean org.doubango.ngn.sip.NgnAVSession.makeCall (String remoteUri)  
  78. 创建一个会话  
  79.   
  80. Parameters:  
  81. remoteUri   the remote party uri. Could be a SIP/TEL uri, nomadic number, MSISDN number, ... example:   
  82.   
  83. sip:test@doubango.org, tel:+3360000000078888667, ...   
  84.   
  85. boolean org.doubango.ngn.sip.NgnAVSession.makeVideoSharingCall (String remoteUri)  
  86. 开始视频分享  
  87.   
  88. Parameters:  
  89. remoteUri   the remote party uri. Could be a SIP/TEL uri, nomadic number, MSISDN number, ... example:   
  90.   
  91. sip:test@doubango.org, tel:+3360000000078888667, ...   
  92.   
  93. boolean org.doubango.ngn.sip.NgnAVSession.resumeCall ()  
  94. 恢复会议  
  95.   
  96. boolean org.doubango.ngn.sip.NgnAVSession.sendDTMF (int digit)  
  97. 发送dtmf数字信息  
  98. Parameters:数字  
  99.   
  100. void org.doubango.ngn.sip.NgnAVSession.setContext (Context context)  
  101. 设置句柄  
  102.   
  103. void org.doubango.ngn.sip.NgnAVSession.setRotation (int rot)  
  104. 设置本地视频的旋转角度  
  105.   
  106. void org.doubango.ngn.sip.NgnAVSession.setSpeakerphoneOn (boolean speakerOn)  
  107. 设置是否开启扬声器  
  108.   
  109. void org.doubango.ngn.sip.NgnAVSession.setState (InviteState state)  
  110. 设置会议状态  
  111.   
  112. final View org.doubango.ngn.sip.NgnAVSession.startVideoConsumerPreview ()  
  113. 启动视频  
  114.   
  115. final View org.doubango.ngn.sip.NgnAVSession.startVideoProducerPreview ()  
  116. 同上  
  117.   
  118. void org.doubango.ngn.sip.NgnAVSession.toggleCamera ()  
  119. 切换相机  
  120.   
  121. void org.doubango.ngn.sip.NgnAVSession.toggleSpeakerphone ()  
  122. 切换扬声器  

org.doubango.ngn.NgnEngine

[java]  view plain copy
  1. synchronized boolean start ()  
  2. synchronized boolean stop ()  
  3. synchronized boolean isStarted ()  
  4. void setMainActivity (Activity mainActivity)  
  5. Activity getMainActivity ()  
  6. INgnConfigurationService getConfigurationService ()  
  7. INgnStorageService getStorageService ()  
  8. INgnNetworkService getNetworkService ()  
  9. INgnHttpClientService getHttpClientService ()  
  10. INgnContactService getContactService ()  
  11. INgnHistoryService getHistoryService ()  
  12. INgnSipService getSipService ()  
  13. INgnSoundService getSoundService ()  
  14. Classextends NgnNativeService > getNativeServiceClass ()  
  15. Static Public Member Functions  
  16. static NgnEngine getInstance ()  
  17. Protected Member Functions  
  18. NgnEngine ()  
[java]  view plain copy
  1. org.doubango.ngn.NgnEngine.NgnEngine () [protected]  
  2. 默认构造  
  3.   
  4. INgnConfigurationService org.doubango.ngn.NgnEngine.getConfigurationService ()  
  5. 获取配置服务  
  6.   
  7. INgnContactService org.doubango.ngn.NgnEngine.getContactService ()  
  8. 获取联系人服务  
  9.   
  10. INgnHistoryService org.doubango.ngn.NgnEngine.getHistoryService ()  
  11. 获取记录服务  
  12.   
  13. INgnHttpClientService org.doubango.ngn.NgnEngine.getHttpClientService ()  
  14. 获取http交互服务  
  15.   
  16. static NgnEngine org.doubango.ngn.NgnEngine.getInstance () [static]  
  17. 获取ngn引擎实例  
  18.   
  19. Activity org.doubango.ngn.NgnEngine.getMainActivity ()  
  20. 获取主activity  
  21.   
  22. Classextends NgnNativeService> org.doubango.ngn.NgnEngine.getNativeServiceClass ()  
  23. 获取本地服务  
  24.   
  25. INgnNetworkService org.doubango.ngn.NgnEngine.getNetworkService ()  
  26. 获取网络服务  
  27.   
  28. INgnSipService org.doubango.ngn.NgnEngine.getSipService ()  
  29. 获取sip服务  
  30.   
  31. INgnSoundService org.doubango.ngn.NgnEngine.getSoundService ()  
  32. 获取声音服务  
  33.   
  34. INgnStorageService org.doubango.ngn.NgnEngine.getStorageService ()  
  35. 获取存贮服务   
  36.   
  37. synchronized boolean org.doubango.ngn.NgnEngine.isStarted ()  
  38. 是否开始  
  39.   
  40. void org.doubango.ngn.NgnEngine.setMainActivity (Activity mainActivity)  
  41.   
  42. synchronized boolean org.doubango.ngn.NgnEngine.start ()  
  43. 开启引擎  
  44.   
  45. synchronized boolean org.doubango.ngn.NgnEngine.stop ()  
  46. 停止引擎  


推荐文章:

http://www.cnblogs.com/DreamSea-for-Jimmy/archive/2011/07/28/2119877.html


你可能感兴趣的:(IMSDroid)