PJSIP Android 原生库与 Java 绑定编译指南

适用于 PJProject 2.13+,NDK r25+(本文以 NDK r28 为例)


📌 目标

生成可用于 Android Studio(Java/Kotlin)项目 的:

  • libpjsua2.so 原生库
  • org.pjsip.pjsua2.* Java 绑定类

根据 PJSIP 官方文档,以下是 直接使用 configure-android 脚本编译出 .so 文件 的完整步骤(适用于 NDK r28,并满足 16KB 页面对齐要求):


✅ 前提条件

  • 已安装 Android NDK r28(路径如 /path/to/ndk/28.0.12916984
  • 已克隆 pjproject 源码
  • (可选)已编译 OpenSSL 和 Oboe(若不需要 TLS 或高级音频可跳过)

🛠️ 编译步骤

1️⃣ 创建 config_site.h

pjlib/include/pj/ 目录下创建文件 config_site.h,内容如下:

1
2
3
4
5
6
/* 启用 Android 特定配置 */
#define PJ_CONFIG_ANDROID 1
#include <pj/config_site_sample.h>

/* 启用视频支持(如需 OpenH264) */
#define PJMEDIA_HAS_VIDEO 1

2️⃣ 配置构建(自动满足 16KB 对齐)

1
2
3
4
5
6
7
8
9
10
11
12
13
# 进入 pjproject 根目录
cd /path/to/pjproject

# 设置 NDK 路径(替换为你的实际路径)
export ANDROID_NDK_ROOT=/path/to/ndk/28.0.12916984

# 清理旧构建(重要!)
make distclean

# 配置构建(NDK r28+ 默认支持 16KB 对齐,无需额外参数)
./configure-android \
--with-ssl=/path/to/openssl \ # 可选:OpenSSL 路径
--with-oboe=/path/to/oboe # 可选:Oboe 路径

💡 关键说明

  • NDK r27+ 已默认启用 16KB 对齐,官方文档明确说明无需手动添加 -Wl,-z,max-page-size=16384
  • 若使用旧版 NDK(<r27),才需要额外加 CFLAGS="-D__BIONIC_NO_PAGE_SIZE_MACRO" LDFLAGS="-Wl,-z,max-page-size=16384"

3️⃣ 编译原生库

1
2
# 编译所有组件(包括 libpjsua2.so)
make dep && make clean && make

4️⃣ 编译 Java JNI 接口(生成最终 .so)

1
2
3
4
5
6
# 设置 JAVA_HOME(指向 Android Studio 的 JBR)
export JAVA_HOME=/path/to/android-studio/jbr

# 进入 SWIG 目录并编译
cd pjsip-apps/src/swig
make

若用swig编译报错

1. 系统依赖

1
2
3
4
5
# Ubuntu/Debian
sudo apt install build-essential automake libtool swig openjdk-11-jdk

# 验证 SWIG ≥ 3.0.8(推荐 4.0+)
swig -version

2. 环境变量(根据你的路径调整)

1
2
export ANDROID_NDK_HOME=/data/Android/Sdk/ndk/28.0.12674087
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

3. 已成功编译 PJProject 原生库

确保以下目录存在 .a 静态库:

1
2
3
pjproject/pjlib/lib/
pjproject/pjsip/lib/
...(其他组件)

🔧 编译步骤

步骤 1:进入 SWIG Java 目录

1
cd ~/projects/pjproject/pjsip-apps/src/swig/java

步骤 2:清理旧构建(可选)

1
make clean

步骤 3:执行编译

1
make

💡 若提示 swig: command not found,请先安装 SWIG(见前置条件)


📂 输出文件位置

编译成功后,关键文件位于:

文件类型 路径
Java 绑定类 android/pjsua2/src/main/java/org/pjsip/pjsua2/
原生库 (.so) android/pjsua2/src/main/jniLibs/arm64-v8a/
C++ STL 库 android/pjsua2/src/main/jniLibs/arm64-v8a/libc++_shared.so

支持的 ABI:默认 arm64-v8a,如需 armeabi-v7ax86_64 等,需修改 Makefile


📦 集成到 Android Studio 项目

1. 复制原生库

将整个 jniLibs 文件夹复制到 App 模块:

1
2
3
4
5
6
7
your-app/
└── src/
└── main/
└── jniLibs/ ← 直接覆盖
└── arm64-v8a/
├── libpjsua2.so
└── libc++_shared.so

2. 复制 Java 绑定代码

org/pjsip/pjsua2/ 整个包复制到:

1
your-app/src/main/java/org/pjsip/pjsua2/

3. 配置 build.gradle (Module: app)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
android {
compileSdk 34

defaultConfig {
minSdk 23
targetSdk 34

ndk {
abiFilters 'arm64-v8a' // 与你编译的架构一致
}
}

// 确保不压缩 .so 文件
packagingOptions {
doNotStrip "*/arm64-v8a/*.so"
}
}

4. 在代码中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.pjsip.pjsua2.*;

public class MyPjsipApp {
private Endpoint ep;

public void init() {
ep = new Endpoint();
try {
ep.libCreate();
EpConfig epConfig = new EpConfig();
ep.libInit(epConfig);
ep.libStart();
} catch (Exception e) {
e.printStackTrace();
}
}
}

⚠️ 常见问题

Q1: 编译时报 swig: No such file or directory

解决:安装 SWIG 4.1(推荐):

1
2
3
4
wget https://github.com/swig/swig/archive/refs/tags/rel-4.1.0.tar.gz
tar -xzf rel-4.1.0.tar.gz && cd swig-rel-4.1.0
./autogen.sh && ./configure --prefix=/usr/local
make -j$(nproc) && sudo make install

Q2: 运行时崩溃 UnsatisfiedLinkError

原因:缺少 libc++_shared.so 或 ABI 不匹配
解决

  • 确保 jniLibs/arm64-v8a/ 包含两个 .so 文件
  • 检查设备 CPU 架构:adb shell getprop ro.product.cpu.abi

Q3: 如何编译其他 ABI(如 armeabi-v7a)?

方法:修改 pjsip-apps/src/swig/java/Makefile 中的 TARGET_ABI 变量,或通过环境变量指定:

1
make TARGET_ABI=armeabi-v7a

📚 附录:SWIG 子目录说明

目录 用途 适用场景
java/ ✅ 标准 Android Java/Kotlin 绑定 Android Studio 原生开发
pjsua2xamarin/ Xamarin.Forms C# 绑定 老 Xamarin 项目
pjsua2maui/ .NET MAUI C# 绑定 新 .NET 跨平台项目

🚨 普通 Android 开发者只需关注 java/ 目录!


文档版本:v1.0
最后更新:2024年
适用于 PJProject 2.13+ / NDK r25+