SIP终端
SIP协议及其发展:
sip(session initiation protocal)称为会话发起协议,是由ietf(internet engineering task force)组织于1999年提出的一个在基于ip网络中,特别是在internet这样一种结构的网络环境中,实现实时通讯应用的一种信令协议。而所谓的会话(session),就是指用户之间的数据交换。在基于sip协议的应用中,每一个会话可以是各种不同的数据,可以是普通的文本数据,也可以是经过数字化处理的音频、视频数据,还可以是诸如游戏等应用的数据,应用具有巨大的灵活性。
作为一个ietf提出的标准,sip协议在很大程度上借鉴了其他各种广泛存在的internet协议,如>打开SIP功能的方法,适用于JB2,JB3,JB5:
请在alps\mediatek\config\product_nam\ProjectConfigmk中,将MTK_SIP_SUPPORT置为yes即可
打开SIP功能的方法,适用于JB2之前的版本:
1 在文件alps\mediatek\config\product_name\androidsoftwaresipvoipxml中添加如下代码
<permissions>
<feature name="androidsoftwaresip" />
<feature name="androidsoftwaresipvoip" />
</permissions>
2 在文件alps\mediatek\config\product_name\androidsoftwaresipxml
<permissions>
<feature name="androidsoftwaresip" />
</permissions>
允许SIP使用GPRS,仅针对GB, GB2,GB3:
在文件alps\frameworks\base\core\res\res\values\Configxml中将
<bool name="config_sip_wifi_only">true</bool>
修改为
<bool name="config_sip_wifi_only">false</bool>
注:JB2,JB3,JB5版本中SIP call功能与OP02互斥,不可以同时开启。
原因是由于运营商的某些原因不允许开启Sip功能。
如希望同时使用,可以修改mk去除互斥条件:
/alps/mediatek/build/addon/core/android_dep_rulemak中去掉以下内容
############################################################
ifneq ($(filter OP02%, $(OPTR_SPEC_SEG_DEF)),)
ifeq ($(strip $(MTK_SIP_SUPPORT)),yes)
$(call dep-err-common, Please do not set OPTR_SPEC_SEG_DEF as OP02 or set MTK_SIP_SUPPORT as no)
endif
endif
1、VOIP基于SIP协议,SDK23包含一个SIP协议栈和框架API
2、VOIP位于androidnetsip包中,最重要的为SipManager类,可开发基于SIP的VOIP应用。使用时要包含androidpermissionINTERNET和androidpermissionUSE_SIP权限
3、如果在market中显示仅支持VOIP API幸好的手机的话,发布时需要在androidManifestxml中加入<uses_feature android:name = "androidsoftwaresip" android:required = "true">和<uses_feature android:name = "androidsoftwaresipvoip">
4、要支持SIP API
(1)仅Android23或更高版本平台支持
(2)不是所有设备都提供SIP支持,确保你的APP只安装在支持SIP的装置上
5、根据GOOGLE官方DEMO项目来扩展的概念
二、类及方法描述
1、一个基本的VOIP项目至少需要三个类SIPSettings(对SIP的基本设置身份验证)、WalkieTalkieActivity(登录到SIP设备供应商,注册device去处理来电,拨打电话,在通话过程中用户界面管理)、IncomingCallReceiver(监听传入的SIP电话,然后传递这些SIP电话给WalkieTalkieActivity控制)
2、
WalkieTalkieActivity
A、SipManagernewInstance()-->此方法中首先判断context是否支持SIP API,若支持则new SipManager。SipManager构造函数中,实例化了一个ISIPService(运用的公式:
IBinder b =ServiceManagergetService(ContextSIP_SERVICE); //获取系统相应的服务
ISipService service = ISipServiceStubasInterface(bIBinder);)
上面这两句代码其实是使用了AIDL,就以SipService为例,步骤如下
Service端
1、编写aidl文件:ISipServiceaidl,并定义使用的接口(就等同于interface一样)
2、使用makefile生成与之同名的JAVA文件,SipServicejava,此类继承extends ISipServiceStub并实现接口定义的方法或者在SipService extends Service,并代码中加入
ISipServicestub sipImpl = new ISipServicestub(){
//实现其接口方法,在SipServicejava中是实现了一个名为start()的方法,里面有句是ServiceManageraddService("sip",newSipService(context));表示SipService已经交给ServiceManager统一管理了
}
Client端
一(以SIPService为例)
1、而在需要用到SipService时,也就是我们构造SipManager的时候,就通过ServiceManagergetService(ContextSIP_SERVICE)获得SIP的服务(类型为IBinder)
2、并调用 ISipServiceStubasInterface(IBinder);去获取一个SipService实例(前提是该Service一定是通过ServiceManageraddService的方式添加进去管理的,这样才能找到此Service)
二(以普通Activity为例)
1、利用Intent intent = new Intent(Activitythis,SipServiceclass);-->bindService(intent, serviceConnection, ContextBIND_AUTO_CREATE);来绑定SERVICE,在serviceConnection的onServiceConnected方法中,使用IServicestubasIntentface(IBinder);来获取实例
B、SipManager创建好后,先从SharedPreference中获取username,domain及pwd,如果第一次进来没有设置这些的话则需要先创建账户,这里用EditTextPreference来保存用户信息,好处是当填写信息并返回后,EditTextPreference会自动将值放入SharedPreference中。我们假设username="woody";domain="1921681230";pwd="910913"
C、这时,我们的SipManager以及用户信息已经设定好了,接下来使用了这句SipProfileBuilder builder = new
SipProfileBuilder(username, domain);我们去看看SipProfileBuilder中做了些什么:
SipURI mUri =mAddressFactorycreateSipURI(username,serverDomain);
SipProfile mProfilemDomain=serverDomain; //设置domain
(在mAddressFactorycreateSipURl方法中,我选取了一些核心代码)
StringBuffer uriString=new StringBuffer("sip:");
uriStringappend(user);
uriStringappend("@");
//if host is an IPv6 string we should enclose it in sq brackets
if(hostindexOf(':') !=hostlastIndexOf(':')&&hosttrim()charAt(0) !='[')
host='['+host+']';
uriStringappend(host);
StringMsgParser smp=new StringMsgParser();
SipUrl sipUri=smpparseSIPUrl(uriStringtoString());
return sipUri;
从以上代码可以看出其实就是在Format SipURL罢了,里面多加了个if host为IPV6的判断(IPv4为为32位,十进制;IPv6为128位,16进制)。urlString最后为"sip:woody@1921681230",smpparseSIPUrl()方法中,有关于是如何parse的就不做阐述了,总之最后返回了一个SipUri
D、接下来就是SipProfile sipProfile = SipProfileBuilderbuild(); //返回一个SipProfile object
在SipProfileBuilderbuild()中,设置了sipProfile的pwd值,删除了之前SipUrl对象里的
password(mUrisetUserPassword(null);)、将sipProfile的address属性设置为AddressImpl类型的对象值、调用AddressFactorycreateURI返回一个SipUri,并sipProfilemProxyAddress=sipUrigetHost();
E、创建PendingIntent对象:(Intent与PendingIntent区别在于Intent是及时启动,而PendingIntent是不立刻反应,在特定的情况或通知下才启动,适用于AlertClock等)
Intent i = new Intent();
isetAction("androidSipDemoINCOMING_CALL");
PendingIntent pi = PendingIntentgetBroadcast(this, 0, i, IntentFILL_IN_DATA);
F、
SipManageropen(sipProfile,PendingIntent,null); //(实际是SIPService在做 *** 作)设置localSIPProfile的callingID-->建立SIP连接(算是注册至SIP Server)-->打开receiveCall
其中建立SIP连接,最后能追溯到是在SipSessionGroupjava的reset()方法中通过是注册服务器实现的,
注册服务器的步骤为:
(1)设置服务器的属性,例如服务器的地址(IP_ADDRESS_PROP)、栈名(javaxsipSTACK_NAME)、发出去的路径(localProfile中的javaxsipOUTBOUND_PROXY)、线程池的大小(govnistjavaxsipTHREAD_POOL_SIZE)等,并且将这些属性加载到服务器中
(2)通过SipFactory的静态方法取得一个实例,然后通过SipFactory实例sipfactory
(3)创建一个SipStack实例sipstack(这一步获得IP_ADDRESS_PROP,String address = PropertiesgetProperty("javaxsipIP_ADDRESS");)
(4)用sipstack创建一个SipProvider实例sipProvider
(5)注册SipListener
G、A~F步骤都是在做准备工作,大致的步骤如下:new SIPService-->new SIPManager-->设定用户信息-->new SIPURI-->new SIPProfile-->new PendingIntent-->set sipProfile callingID-->(if profilegetAutoRegistation)open toReceiveCalls-->register SipService
现在是call someone~呼叫的工作是SipAudioCall类来完成(可用sipManagermakeAudioCall或takeAudioCall来实例化,SipAudioCallstartAudio时需要 RECORD_AUDIO, ACCESS_WIFI_STATE, and WAKE_LOCK permissions,
化,SipAudioCallstartAudio时需要 RECORD_AUDIO, ACCESS_WIFI_STATE, and WAKE_LOCK permissions,setSpeakerMode() 时需要MODIFY_AUDIO_SETTINGS permission)
1当需要呼叫时,使用sipManagermakeAudioCall(String localProfileURI, String peerProfileURI, SipAudioCalllistener,int timeout);来创建一个SipAudioCall,其中timeout以seconds为单位,过了timeout表示打电话超时。需要打给别人时使用makeAudioCall创建,接听电话用takeAudioCall来创建sipAudioCall
2SipAudioCall中有一个嵌套的class:SipAudioCallListener(此类主要用于监听SIP CALL,when[呼叫电话 or 接听电话])
SipAudioCallListener listener = new SipAudioCallListener() {
@Override
public void onCallEstablished(SipAudioCall call) { //呼叫建立
callstartAudio(); //启动音频
callsetSpeakerMode(true); //调整为可讲话模式
calltoggleMute(); //触发无声
updateStatus(call);
}
};
SipAudioCall call = managermakeAudioCall(megetUriString(), sipAddress, listener, 30);
(以上例子为makeAudioCall)
3我们看看makeAudioCall()方法(makeAudioCall requires 2 sipProfile):
SipAudioCall call =new SipAudioCall(mContext, localProfile);
callsetListener(listener); //这两句很简单就是创建一个local的sipAudioCall
SipSession s = createSipSession(localProfile, null); -->mSipServicecreateSession(localProfile, null);// sipService来创建session,并保存在SipSessionGroupExt中
callmakeCall(peerProfile,s,null); //这句就是呼叫,最后追溯到实际是SipSessionmakecall
总结:在发起通话中
首先是创建SipAudioCalllistener,以便监听对话建立和对话结束,然后做相应的 *** 作
然后是SipManagermakeAudioCall(localAdd,llistener,XXXX),在makeAudioCall方法中
A、创建一个sipAudioCall(localProfile)
B、创建SipSession以建立起会话
C、SipSessionmakeCall(peerProfile,XXXX); //SipSession呼叫远程profile
4关于接电话道理都差不多,takeAudioCall
通过之前设置的callingID来查找mSipServicegetPendingSession(callId);来获得SipSession。并创建SipAudioCall,然后attachCall就算接受电话了SIP响应码为空的原因可能有很多,例如:1 网络连接问题,可能是网络连接不稳定,或者网络连接被阻止;2 SIP服务器问题,可能是SIP服务器出现故障,或者SIP服务器没有正确配置;3 SIP客户端问题,可能是SIP客户端没有正确配置,或者SIP客户端出现问题;4 SIP协议问题,可能是SIP协议版本不兼容,或者SIP协议出现问题。总之,SIP响应码为空的原因可能有很多,需要根据具体情况进行排查和解决。一、SIP消息
SIP消息是SIP客户终端和服务器之间通信的的基本信息单元。SIP消息基于文本,采用UTF-8编码(RFC 2279)中的ISO 10646字符集。SIP协议借鉴了>SIP( 会话初始协议)的开发目的是用来帮助提供跨越因特网的高级电话业务。因特网电话(IP电话)正在向一种正式的商业电话模式演进,SIP就是用来确保这种演进实现而需要的NGN(下一代网络)系列协议中重要的一员。支持H264协议。
SIP是IETF标准进程的一部分,它是在诸如SMTP(简单邮件传送协议)和>
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)