上一篇大体说明了服务器的搭建,这一篇就开始单对单的语音聊天说明。
就像上一篇中介绍的一样,客户端利用的是开源的pjsip客户端进行语音通信,pjsip中本身也提供了大量的demo让我们进行功能调试和使用,所以我们可以直接利用它本身的demo来修改进而达到我们客户端语音通信的目的。
另:在尝试过程中发现,pjsip客户端不注册服务器直接进行端对端拨打,在同一局域网下依旧是可以的,这边由于需要后期穿越,而nat穿越需要服务器,而且第一篇也已经说了server的布置,所以这篇还是以需要注册为基础。
一、环境:
ubutun 14 AS3.0 android-ndk-r14
二、软件:
pjsip,opensips,restund
首先,我用的修改的demo是pjsip中自带一个安卓的demo,具体路径在/home/pjsip/pjproject-2.7.2/pjsip-apps/src/pjsua/android
这个demo用的是swing进行jni的编译,我这边使用的是NDK,所以后面也做了比较大的改动,背景就到这里,接下来开始说开发流程。
三、pc端的端对端聊天
1、在pjsip官网上面下载对应的pjsip版本
install libasound2-dev
# tar -jxvf pjproject-2.7.2.tar.bz2
# cd pjproject-2.7.2
# ./configure
# make dep
# make
2、在你的安装目录下的pjsip-apps/bin下会生成对应的可执行文件
pjsua-x86_64-unknown-linux-gnu是对应的pc端运行demo,接受参数输入,来驱动对应的功能,具体的参数在你运行此可执行文件之后会出现提醒信息。
四、移动端端对端通话
1、参考/home/pjsip/pjproject-2.7.2/pjsip-apps/src/pjsua/android目录下得安卓工程,新建自己的安卓项目,并暴露native方法,自己根据jni的规则(此处对于jni的构建目录和规则不做详述)对对应的native方法生成.h文件
2、编译安卓使用的.a库,并安装,说明:
<1>NDK:
理论上越新越好,但需要看对应版本的交叉编译器,因为本次使用pjsip2.7.2,官方对应交叉编译器为arm-android-linux-4.9
使用android-ndk-r14b-linux-x86_64.zip
https://developer.android.google.cn/ndk/downloads/older_releases#ndk-14b-downloads
1)在/opt/目录下解压android-ndk-r14b-linux-x86_64.zip
unzip android-ndk-r14b-linux-x86_64.zip
2)修改环境变量
1.编辑.bashrc;
如果需要全局生效请修改/etc/profile
vim ~/.bashrc
2.在文件末尾添加如下内容
export NDK=/opt/android-ndk-r14b/
export PATH=$PATH:$NDK
# this is pjsip env config for configure-andriod
export ANDROID_NDK_ROOT=/opt/android-ndk-r14b/
3.使之生效
source ~/.bashrc
4.openh264:
这个比较复杂,后面再说,支持的是视频相关的东西
<2>编译PJSIP静态依赖库
1.新建config_site.h
vim your-pjproject-path/pjlib/include/pj/config_site.h
2.给config_site.h加入如下内容(先屏蔽视频相关编译项)
/* Activate Android specific settings in the 'config_site_sample.h' */
#define PJ_CONFIG_ANDROID 1
//To enable video
//#define PJMEDIA_HAS_VIDEO 1
//To enable libyuv
//#define PJMEDIA_HAS_LIBYUV 1
//To enable TCP transport
//#define PJ_HAS_TCP 1
#include
3.终端输入如下参数(未测试是否真实生效)
NDK_TOOLCHAIN_VERSION=4.9 //交叉编译器版本(必须指定,ndk13以上不指定会默认用clang编译导致出错)
TARGET_ABI+=armeabi
TARGET_ABI+=armeabi-v7a //Andriod机器CPU
APP_PLATFORM=android-24 //自己需要运行的Android版本
4.设置编译配置
./configure-android
5.编译PJSIP
make dep
make clean
make
6.安装PJSIP(注意:非常关键)
make install
执行后,会将对应的pjsip静态库安装。
<3>配合前面自己的jni文件编译PJSUA动态库
1.创建目录结构
pjtest_jni
|-------jni
|-------res
|-------src
2.在jni目录下编写Andriod.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE += pjtest-jni
LOCAL_SRC_FILES += your_jni_file.c pjsua_app.c pjsua_app_cli.c pjsua_app_common.c pjsua_app_config.c pjsua_app_legacy.c
LOCAL_CFLAGS += -I./ -I/usr/local/include -shared --sysroot=/opt/android-ndk-r14b//platforms/android-24/arch-arm -fexceptions -frtti -I/usr/local/include -DPJ_AUTOCONF=1 --sysroot=/opt/android-ndk-r14b//platforms/android-24/arch-arm -I/opt/android-ndk-r14b//sources/cxx-stl/gnu-libstdc++/4.9/include -I/opt/android-ndk-r14b//sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include -DPJ_IS_BIG_ENDIAN=0 -DPJ_IS_LITTLE_ENDIAN=1
LOCAL_LDLIBS += -L/usr/local/lib -lpjsua2-arm-unknown-linux-androideabi -lstdc++ -lpjsua-arm-unknown-linux-androideabi -lpjsip-ua-arm-unknown-linux-androideabi -lpjsip-simple-arm-unknown-linux-androideabi -lpjsip-arm-unknown-linux-androideabi -lpjmedia-codec-arm-unknown-linux-androideabi -lpjmedia-arm-unknown-linux-androideabi -lpjmedia-videodev-arm-unknown-linux-androideabi -lpjmedia-audiodev-arm-unknown-linux-androideabi -lpjmedia-arm-unknown-linux-androideabi -lpjnath-arm-unknown-linux-androideabi -lpjlib-util-arm-unknown-linux-androideabi -lsrtp-arm-unknown-linux-androideabi -lresample-arm-unknown-linux-androideabi -lgsmcodec-arm-unknown-linux-androideabi -lspeex-arm-unknown-linux-androideabi -lilbccodec-arm-unknown-linux-androideabi -lg7221codec-arm-unknown-linux-androideabi -lyuv-arm-unknown-linux-androideabi -lwebrtc-arm-unknown-linux-androideabi -lpj-arm-unknown-linux-androideabi -lm -lc -lgcc -lOpenSLES -llog -lGLESv2 -lEGL -landroid
LOCAL_LDLIBS += -L/opt/android-ndk-r14b/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(TARGET_ARCH_ABI) -lgnustl_static
include $(BUILD_SHARED_LIBRARY)
3.在jni目录下编写Application.mk
APP_PLATFORM := android-24
APP_ABI := armeabi
APP_ABI += armeabi-v7a
NDK_TOOLCHAIN_VERSION=4.9
4.根据编译报告取.so库
执行:
ndk-build clean
ndk-build
至此支持单对单语音聊天的动态库已经生成,根据自己的native方法,在自己的方法中调用拨打电话的函数即可以进行通话(同一局域网)。拨打的方式为sip:ip
五、NAT穿越
上面实现的是局域网内聊天,这边加上nat穿越之后就可以在不同局域网内中进行nat穿孔,此时就需要注册服务器,由服务器将对应映射的ip给到请求方,还需要增加一个restund服务器,来进行nat穿透。
步骤如下:
1、安装restund服务器
参照以下博客
http://nil.uniza.sk/sip/installing-and-configuring-restund-stunturn-server
主要是修改etc/restund.conf文件中的配置
如下:
将tcp_listen和udp_listen都修改为自己的ip,module模块按照如图所示进行注释。
配置完成后,在restund目录下,我本地是在/opt/restund-0.4.12目录下,运行
./restund /etc/restund.conf
至此restunserver服务起来。
2、利用pjsip客户端注册opensips服务器和restund服务器
首先应该在启动的时候根据命令行注册到restund服务器(在启动客户端的时候回去调用pjsua的命令行,默认是支持telnet方式的,具体参考源码pjsua_app_config.h),此处我的命令行参数有:
{ "pjsua", "--use-ice", "--use-turn", "--turn-srv", "20.97.6.62:3478", "--turn-tcp", "--turn-user", "10000", "--turn-passwd", "secret", NULL };
参数说明:
--use-ice --use-turn --turn-srv 这三个应该同时存在,紧跟着是restundserver的ip:port
--turn-tcp 这个很重要必须添加,否则可以打通电话但是没有声音
--turn-user 用户名
--turn-passwd restund认证明文密码
注册函数源码:
自己的demo示例:
注册opensips服务器的参数如上图所示
以上注册成功后,可以尝试用nat穿越进行通话,拨打方式与没穿越之前有点区别:sip:账号@serverip
至此,单对单聊天完成并可以支持nat穿越方式通话