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(一))