新建PJSIP类 - 基于Android的VoIP系统设计
为各个待实现的类新建一个包,可以命名为“com.android.voip.pjsip”,在该包中添加该系统相关的一些类,主要有如下6个类:
这些类分别为上节中原理各个步骤的实现。这部分仅仅是为C库的调用提供一个接口,因此具体的实现将放在本地C/C++程序中。
2.2.2 头文件的生成
C库与Java间还需通过一个后缀为“.h”的头文件来衔接,这个头文件可以手动编写,也可以通过“Javah”来生成,该工具包含在JDK中,是由SUN公司提供的。
Javah生产的头文件包含一定的规则,例如,本例中,它将生成的函数声明为“Java_com_android_IMSandroid_pjsip_**”的形式,以便在调用C库时能正确识别。
由于Java中的数据类型与C/C++不尽相同,因此还必须注意参数传递时参数类型的转换。本文所涉及到的Java数据类型有String和int型,Javah生成的头文件中会先定义好需要传递的参数类型以及函数返回类型,例如方法“add_account(String sip_user,Stringsip_dom-ain,String sip_passwd)”,在头文件中将定义函数的形式为“JNIEXPORT jint JNICALL Java_com_android_IMSandroid_pjsip_add_lac-count(JNIEnv*,jclass,jstring,jstring,jstring)”,其中JNIEXPORT为JNI外部函数声明,jint是“jni.h”中定义C语言中整形的对应类型,JNCALL是JNI关键字。比较特殊的是JNIEnv,它是一个指向类型为JNIEnv_的一个特殊JNI数据结构的指针,它的每个元素都指向一个JNI函数的指针,jclass会根据引用Java类的不同而不同,本文中“pjsip.class”是静态类,因此这里的jclass指的是类本身,如果是非静态类则指的是对象。后面几个就是pjsip类需要传递的参数,根据“jni.h”的定义,String类型对应jstring,int对应jint。然而这只是函数申明与类中方法的形式对应,参数的具体传递还需要相应的转化,具体实现将在下一节详细介绍。
2.2.3 JNI接口函数的实现
创建了pjsip库类和头文件之后,必须应用一个库接口函数,这部分是pjsip接口的实现,限于篇幅,本文只讲解几个重要函数的实现。
(1)init函数
首先是init函数,对应的接口函数为JNICALL Java_com_android_IMSandroid_pjsip_init。该函数在系统初始化时调用,其作用是配置相关参数,并发起一个pjsua应用。它先通过函数“pjsua_create()”创建一个“pjsua”应用,然后通过三个函数“pjsua_config_default
(&cfg)”,“pjsua_logging_config_default(&log_cfg”),“pjsua_media_config_default(&media_cfg)”配置其相关参数,其中cfg是pjsua的相关参数,主要是状态改变时的回调函数;log_cfg用来配置log级别;media_cfg中包含时钟频率、声道数目等相关参数。
完成配置之后就可以使用pjsua_init(&cfg,&log_cfg,&media_cfg)将先前配置的参数初始化。在初始化之后,还需为pjsua添加一个udp传输,这一步是通过pjsua_transport_create(PJSIP_TRANSPORT_UDP,&cfg,NULL)来实现的,cfg中包含指定的通讯端口,3GPP建议使用5060。
需要注意的是,配置完以上参数之后,还需指定SPEEX编码优先级,一般将其设为最大,可以通过函数pisua_codec_set_priority(&-speex_codec_id,255)来实现。所有配置完成之后,就可以发起pjsua,即最后调用pjsua_start()。成功的话,本函数的返回类型为PJ_SUCCESS。
(2)make_call函数
另一个很重要的函数是make_call,其在本接口文件中对应的函数为Java_com_android_IMSandroid_pjsip_make_lcall,这个函数一般在发起会话时调用,它与上一个函数在结构上最大的不同在于本函数需要传递一个字符串参数,前面提到,Java与C/C++在参数结构上并不完全相同,因此这里需要将Java传递过来的String类型的参数转化,可以通过“url_ptr=(char*)env->GetStringUTFChars(url,&iscopy)”来实现。env->GetStringUTFChars在“jni.h”中定义,其功能是将jsting类型(Java)的url复制到char*类型(C)的url_ptr中,以此来完成参数类型的转换。
为了保证传递地址的有效性,还需要使用pjsua_verify_sip_url(url_ptr)验证,这个函数主要验证url_ptr是符合SIP的规则,即是否是一个合法的SIP地址。然而char*型的地址pjsua中还是不能直接使用的,这是因为pjsua重新封装了参数类型,所以最后还需要将其转化成pj_ str_t类型,pjlib提供pj_str()函数可以完成转化。在完成了参数的转化后,调用“pjsua_call_make_call()”,将发起会话。
(3)hangup函数和pjsua_destroy函数
这两个函数用来销毁和挂断会话,一般在需结束的时候调用,它们在接口函数中对应Java_com_android_
IMSandroid_pjsip_hangup和Java_com_android_IMSandroid_pjsip_destroy,由于没有参数传递,也没有其他的调用,因此这两个函数非常简单,基本上直接调用pjsua提供的pjsua_call_hangup_all()和pjsua_destroy()就能实现。pisua中这两个函数将完成内存释放、账户注销等工作。
(4)add_account函数
该函数在基本的pjsua中并不是必须的,但如果要使用SIP服务器的话,就必须实现该函数,它在接口函数中对应“Java_com_android_I-MSandroid_pjsip_add_1account”,同“make_call”一样,也需要传递参数,不同的是,它传递三个参数,只是原理大体一样。
首先它将参数转化后保持到cfg,通过“pjsua_acc_add(&cfg,PJ_TRUE,&ace_id)”将参数添加到pjsua。pjsua将以其中的sip服务器为目的地址,注册会话发起申请,经过一系列的操作之后,与目的地址发起会话。
- 第 1 页:基于Android的VoIP系统设计
- 第 2 页:新建PJSIP类
- 第 3 页:主程序与用户界面
本文导航
非常好我支持^.^
(1) 100%
不好我反对
(0) 0%
相关阅读:
- [电子说] 社区说|多才多艺: 探索 Android 应用更多可能 2023-10-24
- [电子说] 浩辰软件正式登陆上交所科创板 2023-10-23
- [电子说] 鸿蒙原生应用,对开发者意味着什么? 2023-10-22
- [电子说] Android端自定义铃声 MobPush对安卓端自定义铃声的教程 2023-10-21
- [电子说] Android推送问题排查技巧 针对MobPush安卓端推送问题的解决办法 2023-10-21
- [电子说] 如何使用Proxyman抓取Android的https请求? 2023-10-19
- [编程语言及工具] 基于OkHttp 3.10.0的源码案例解析 2023-10-17
- [电子说] 基于MacroBenchmark的性能测试量化指标方案 2023-10-17
( 发表人:Spring )