简介
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/ RCSiOS客户端(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 usingPreconditions (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 / 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_();
}
}
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栈
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:+3310000000@doubango.org"; // SMS Center
final String remotePartyUri = "sip:+336000000@doubango.org"; // 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:+336000000@doubango.org"; // 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);