简介

集成pjsip的HarmonyOS Next话机,不含额外编码工具和插件

在这里插入图片描述

交叉编译 pjsip-2.13.1 到HarmonyOSNext

编译环境要求

    HarmonyNext命令行工具 commandline-tools-linux-x64-5.0.3.800

    gcc-9.3.0

    glibc-2.31

    make-4.3

    pjproject-2.13.1

版本检查

# 检查gcc >= 9.3.0
gcc -v

# 检查make >= 4.3
make -v

# 检查GLIBC,>= 2.31
strings /lib64/libc.so.6 |grep GLIBC

编译

# 准备编译时的环境变量,将C/C++编译路径指向HarmonyOSNext提供的工具
export OHOS_SDK=/你的命令行工具路径/command-line-tools/sdk/default/openharmony
export AS=${OHOS_SDK}/native/llvm/bin/llvm-as
export CC="${OHOS_SDK}/native/llvm/bin/clang --target=aarch64-linux-ohos -march=armv8-a --sysroot=/home/HarmonyOS_NEXT/ohos-sdk/linux/native/sysroot"
export CXX="${OHOS_SDK}/native/llvm/bin/clang++ --target=aarch64-linux-ohos --sysroot=/home/HarmonyOS_NEXT/ohos-sdk/linux/native/sysroot"
export LD="${OHOS_SDK}/native/llvm/bin/ld.lld"
export STRIP=${OHOS_SDK}/native/llvm/bin/llvm-strip
export RANLIB=${OHOS_SDK}/native/llvm/bin/llvm-ranlib
export OBJDUMP=${OHOS_SDK}/native/llvm/bin/llvm-objdump
export OBJCOPY=${OHOS_SDK}/native/llvm/bin/llvm-objcopy
export NM=${OHOS_SDK}/native/llvm/bin/llvm-nm
export AR=${OHOS_SDK}/native/llvm/bin/llvm-ar
export CFLAGS="-fPIC -D__MUSL__=1"
export CXXFLAGS="-fPIC -D__MUSL__=1"

进入pjsip目录


cd pjproject-2.13.1

开始配置,生成 MakeFile,中间如有错误查看 pjproject-2.13.1/config.log

./configure --prefix=/编译完成后静态库生成路径/pjsip --host=aarch64-linux --disable-libwebrtc LD="$CXX"

开始编译

make dep
make
make install

编译完成之后结束之后,进入/编译完成后静态库生成路径/pjsip目录查看编译结果, include是头文件, lib是静态库

[root@localhost pjsip]> ls
include  lib

运行环境要求

编辑器版本DevEco Studio for Windows 5.0.3.810

编辑器内置SDK版本API Version 10 (4.0.10.16), 该SDK主要用于调试,不确定是否必须

真机系统HarmonyOS Next 0.0.66,因为上面pjsip只编译了aarch64架构的静态库,所以模拟器,预览(都是x86的)无法运行,必须真机,如果需要模拟器查看,需要编译对应的x86架构的pjsip

运行环境配置

使用编辑器创建一个全新的Native C++工程

在项目/lib/arm64-v8a/中新建目录libpjsip,将编译好的lib下静态库放入libpjsip

将编译好的include文件夹,包括头文件放到项目src/main/cpp目录下

修改CMakeLists.txt,参考下面

PJSIP宏

add_definitions(-DPJ_AUTOCONF=1)
add_definitions(-DPJ_IS_BIG_ENDIAN=0)
add_definitions(-DPJ_IS_LITTLE_ENDIAN=1)
add_definitions(-DPJ_LOG_MAX_LEVEL=6) # 设置最大日志等级
add_definitions(-DPJSUA2_ERROR_HAS_EXTRA_INFO=1)
add_definitions(-D__MUSL__=1)
# 在 add_library(entry SHARED napi_init.cpp) 之后链接PJSIP静态库到 entry, 如果你的不叫entry,请修改为对应名称
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libg7221codec-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjmedia-codec-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjsua2-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libgsmcodec-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjmedia-videodev-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libresample-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libilbccodec-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjnath-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libspeex-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpj-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjsip-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libsrtp-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjlib-util-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjsip-simple-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libyuv-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjmedia-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjsip-ua-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjmedia-audiodev-aarch64-unknown-linux-gnu.a)
target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/libpjsip/libpjsua-aarch64-unknown-linux-gnu.a)

点击编辑器右上角Sync Now同步CMakeLists.txt到编辑器

运行查看

修改napi_init.cpp在文件中使用pjsip提供的api
运行debug查看效果

测试使用的是pjsip官方的C++例子,进行话机注册,有一点需要注意,在HarmonyOS Next中运行C++,std::cout 输出日志是看不到的,必须使用HarmonyOS Next的hilog库提供的OH_LOG_Print方法进行日志输出,在pjsip中需要对日志方法进行重写

在napi_init.cpp中写的测试方法


// 自定义日志类
class MyLogWriter : public pj::LogWriter {
public:
    // 使用 OH_LOG_Print 代理打印pjsip日志,这里使用的是pjsua2,所以代理方式采用了pjsua2的代理方式,如果你用的普通的pjsip,需要使用另外一种代理方式,两种是分开的
    virtual void write(const pj::LogEntry &entry) {
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "PJSIP", "%{public}s", entry.msg.c_str());
    }
};


// 测试方法
void test_pjsip()
{
  // ...其他代码
  pj::EpConfig ep_cfg;
  pj::LogConfig log_config;
  MyLogWriter *mw = new MyLogWriter;
  log_config.writer = mw;
  // 把日志配置添加到EpConfig
  ep_cfg.logConfig = log_config;
  // 初始化前端配置
  ep.libInit( ep_cfg );
  // ...其他代码
}

查看控制台有发起注册的信令,不知道为什么官方的例子注册始终401,注册到我自己的sip服务就是正常的
在这里插入图片描述

pjsip发起注册

已经验证的系统

    HarmonyOS Next 0.0.66
    HarmonyOS Next 0.0.68 (目前最新版本)

鸿蒙Next(HarmonyOS NEXT)集成PJSIP库

在鸿蒙Next(HarmonyOS NEXT)中集成PJSIP库,可以通过以下步骤实现。PJSIP是一个开源的SIP协议栈,适用于嵌入式设备和移动平台。
在这里插入图片描述

步骤概述:

    获取PJSIP源码:从官方仓库(https://github.com/pjsip/pjproject)下载或克隆源码。
    配置交叉编译环境:鸿蒙Next使用ArkTS/JS开发,但PJSIP是C库,需通过NDK(Native Development Kit)编译为共享库(.so)。
    编写Native C代码:创建C/C++文件调用PJSIP API。
    使用NAPI桥接:通过HarmonyOS NAPI将C代码暴露给ArkTS层。
    在ArkTS中调用:在UI或服务中集成SIP功能。

详细步骤及代码示例:

  1. 下载并编译PJSIP

    下载PJSIP源码,解压到项目目录(如third_party/pjproject)。

    配置编译脚本(如config_site.h),针对鸿蒙架构(arm64-v8a)进行交叉编译。示例配置:

    // config_site.h
    #define PJ_CONFIG_ANDROID 1
    #include <pj/config_site_sample.h>
注意:需根据鸿蒙NDK调整配置,参考鸿蒙NDK文档设置工具链路径。

使用CMake或Makefile编译,生成libpjsip2.so等库文件。
  1. 创建Native C模块

在HarmonyOS Native层创建C文件(如sip_native.c),实现PJSIP初始化和基本调用:

#include <pjlib.h>
#include <pjsip.h>
#include <napi/native_api.h>

static napi_value InitPJSIP(napi_env env, napi_callback_info info) {
    pj_status_t status;
    pj_caching_pool cp;
    pj_pool_t *pool;

    // 初始化PJ库
    status = pj_init();
    if (status != PJ_SUCCESS) {
        napi_throw_error(env, NULL, "PJSIP初始化失败");
        return NULL;
    }

    // 创建内存池
    pj_caching_pool_init(&cp, NULL, 1024);
    pool = pj_pool_create(&cp.factory, "sip_pool", 4000, 4000, NULL);

    // 其他SIP初始化代码(如传输层、UA等)
    // ...

    napi_value result;
    napi_create_int32(env, status, &result);
    return result;
}

// NAPI模块注册
EXTERN_C_START
static napi_module sip_module = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = NULL,
    .nm_register_func = InitPJSIP,
    .nm_modname = "pjsip",
    .nm_priv = NULL,
};
EXTERN_C_END
  1. 配置NAPI和构建

    在build-profile.json5中配置Native依赖:

    "native": {
      "name": "sipnative",
      "sourceDir": "./src/main/cpp",
      "systemLibs": ["log"]
    }

将编译的PJSIP库(.so)放入libs/arm64-v8a/目录,并在CMakeLists.txt中链接:
   target_link_libraries(sipnative PUBLIC pjsip2 pjlib-util)

在这里插入图片描述

  1. ArkTS调用示例

在ArkTS中通过NAPI接口调用Native函数:

import native from 'libsipnative.so'; // 根据实际库名调整

let status = native.initPJSIP();
if (status === 0) {
  console.log('PJSIP初始化成功');
} else {
  console.error('PJSIP初始化失败');
}

注意事项:

权限配置:在module.json5中添加网络权限:

    "requestPermissions": [
      { "name": "ohos.permission.INTERNET" }
    ]

线程安全:PJSIP需在独立线程运行,避免阻塞UI。
错误处理:检查PJSIP API返回状态,确保资源释放。
测试验证:使用SIP服务器(如Asterisk)测试注册和呼叫功能。

通过以上步骤,可在鸿蒙Next中集成PJSIP实现SIP通信。具体API调用参考PJSIP文档(https://www.pjsip.org)。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐