项目中使用Pjsip封装成自己的SO文件,所以先编译Pjsip,然后编译自己的动态库,都使用到NDK环境。
一、编译Pjsip
刚开始使用Pjsip,通过官网指定的方式编译,我环境变量中配置的android 的NDK版本是:
ANDROID_NDK_ROOT=/home/XXXX/Documents/Android_Env/android-ndk-r14b
根据配置脚本的自动读取,NDK选择了android-24这个API-LEVEL进行NDK的编译,编译的过程中没有出现问题,一切顺利。
二、编译自己使用的SO文件
我使用编译出来的.a文件,加上自己的代码,写了一个动态库提供给安卓调用。编译使用了Cmake
cmake -DCMAKE_TOOLCHAIN_FILE=/home/XXX/Documents/android-cmake/android.toolchain.cmake\ -DANDROID_NDK=${ANDROID_NDK_ROOT} \ -DCMAKE_BUILD_TYPE=Release \ -DANDROID_NATIVE_API_LEVEL=android-24 \ -DANDROID_ABI="armeabi-v7a" \ -f ../src
编译的代码,通过JNI接口调用到安卓使用.
三、安卓工程的配置
安卓工程使用Android Studio编译,编译版本有关的配置:
defaultConfig { minSdkVersion 19 targetSdkVersion 25 }
根据上面的配置,可以知道我们的目标运行版本是25,最小版本是19.
其中和NDK编译有关的版本使用在Application.mk中配置,开始我并没有配置:
APP_PLATFORM := //默认未指定
问题现象:
程序安装到Android 6.0上运行正常。
安装到一个台Androdi 4.4上设备崩溃,崩溃信息如下:
../src/pj/rand.c:27: error: undefined reference to 'srand'
../src/pj/rand.c:33: error: undefined reference to 'rand'
解决方法:
1、pjsip编译时指定 NDK使用的APP_PLATFORM=android-19 。具体的编译选项在我上一篇博客有罗列。
2、自己编译动态SO文件时,也指定APP_PLATFORM=19,如:
cmake -DCMAKE_TOOLCHAIN_FILE=/home/XXX/Documents/android-cmake/android.toolchain.cmake\ -DANDROID_NDK=${ANDROID_NDK_ROOT} \ -DCMAKE_BUILD_TYPE=Release \ -DANDROID_NATIVE_API_LEVEL=android-19 \ -DANDROID_ABI="armeabi-v7a" \ -f ../src
问题原因:
“srand”和"rand"函数属于libc.so的标准库的函数,在linux系统平台上是没有问题的,系统层libc.so都包含这两个函数。
问题在于Android使用的是自己写的libc.so库,更要命的是这些库是不向前兼容的。比如,srand函数 app_platform=19版本上是没有的,在app_platform=24是有的。也就是说,你用24版本的libc.so文件编译成功了,真正运行的系统是19版本的,APP去libc.so文件中调用“srand”函数时,发现根本没有这个函数,然后就奔溃了!!!
android-ndk-r14b下对应的动态库罗列:
android-ndk-r14b/platforms/android-19/arch-arm/usr/lib/├── crtbegin_dynamic.o├── crtbegin_so.o├── crtbegin_static.o├── crtend_android.o├── crtend_so.o├── libandroid.so├── libc.a├── libc.so├── libdl.so├── libEGL.so├── libGLESv1_CM.so├── libGLESv2.so├── libGLESv3.so├── libjnigraphics.so├── liblog.so├── libm.a├── libm_hard.a├── libm.so├── libOpenMAXAL.so├── libOpenSLES.so├── libstdc++.a├── libstdc++.so└── libz.so