1.编译 在git 上找了下 https://github.com/juha-h/libbaresip-android 这个测试不错 相关的下载sdk和r19的ndk 并参考执行就行了 注意修改ndk路径和输出目录
make download-sources 如果执行不成功 则自己下载包 重命名和他的一样就可以了 地址在Makefile里面
(如果觉得麻烦可以去https://item.taobao.com/item.htm?id=606696026272购买个维护好的)
2.编译完成后 输出目录结构
有对应的头文件和.a文件
如果你是精通安卓的直接参考他的项目就行了https://github.com/juha-h/baresip-studio
3.在studio创建一个c++的安卓工程将上面这个目录考到cpp下修改![](https://i-blog.csdnimg.cn/blog_migrate/af3ad9c5f607f1a0db1cc2d862b65b50.png)
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
set(distribution_DIR ${CMAKE_SOURCE_DIR}/distribution)
add_library(lib_crypto STATIC IMPORTED)
set_target_properties(lib_crypto PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/openssl/lib/${ANDROID_ABI}/libcrypto.a)
add_library(lib_ssl STATIC IMPORTED)
set_target_properties(lib_ssl PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/openssl/lib/${ANDROID_ABI}/libssl.a)
add_library(lib_re STATIC IMPORTED)
set_target_properties(lib_re PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/re/lib/${ANDROID_ABI}/libre.a)
add_library(lib_rem STATIC IMPORTED)
set_target_properties(lib_rem PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/rem/lib/${ANDROID_ABI}/librem.a)
add_library(lib_opus STATIC IMPORTED)
set_target_properties(lib_opus PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/opus/lib/${ANDROID_ABI}/libopus.a)
add_library(lib_g722_1 STATIC IMPORTED)
set_target_properties(lib_g722_1 PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/g7221/lib/${ANDROID_ABI}/libg722_1.a)
add_library(lib_ilbc STATIC IMPORTED)
set_target_properties(lib_ilbc PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/ilbc/lib/${ANDROID_ABI}/libilbc.a)
add_library(lib_webrtc STATIC IMPORTED)
set_target_properties(lib_webrtc PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/webrtc/lib/${ANDROID_ABI}/libwebrtc.a)
add_library(lib_bn STATIC IMPORTED)
set_target_properties(lib_bn PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/bn/lib/${ANDROID_ABI}/libbn.a)
add_library(lib_zrtp STATIC IMPORTED)
set_target_properties(lib_zrtp PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/zrtp/lib/${ANDROID_ABI}/libzrtp.a)
add_library(lib_baresip STATIC IMPORTED)
set_target_properties(lib_baresip PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/baresip/lib/${ANDROID_ABI}/libbaresip.a)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
include_directories(native-lib
${distribution_DIR}/baresip/include
${distribution_DIR}/re/include
${distribution_DIR}/rem/include
)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
android
OpenSLES
lib_baresip
lib_rem
lib_re
lib_ssl
lib_crypto
lib_opus
lib_g722_1
lib_ilbc
lib_webrtc
lib_zrtp
lib_bn
z
# Links the target library to the log library
# included in the NDK.
${log-lib})
参考https://github.com/juha-h/baresip-studio 就行了
4.接着在native-app里面写个start和接听的方法
#include <jni.h>
#include <string>
#include <pthread.h>
#include "AndroidLog.h"
#include "re.h"
#include "baresip.h"
typedef struct baresip_context {
struct ua *ua;
struct call *call;
} BaresipContext;
BaresipContext g_ctx;
static void signal_handler(int sig)
{
static bool term = false;
if (term) {
mod_close();
exit(0);
}
term = true;
LOGD("terminated by signal (%d)\n", sig);
ua_stop_all(false);
}
static void ua_exit_handler(void *arg)
{
(void)arg;
LOGD("ua exited -- stopping main runloop\n");
re_cancel();
}
static const char *ua_event_reg_str(enum ua_event ev)
{
switch (ev) {
case UA_EVENT_REGISTERING: return "registering";
case UA_EVENT_REGISTER_OK: return "registered";
case UA_EVENT_REGISTER_FAIL: return "registering failed";
case UA_EVENT_UNREGISTERING: return "unregistering";
default: return "?";
}
}
static void ua_event_handler(struct ua *ua, enum ua_event ev,
struct call *call, const char *prm, void *arg)
{
char event_buf[256];
char ua_buf[32];
char call_buf[32];
int len;
struct player *player = baresip_player();
LOGD("ua event (%s) %s\n", uag_event_str(ev), prm);
switch (ev) {
case UA_EVENT_REGISTERING:
case UA_EVENT_UNREGISTERING:
case UA_EVENT_REGISTER_OK:
len = re_snprintf(event_buf, sizeof event_buf, "%s", ua_event_reg_str(ev));
break;
case UA_EVENT_REGISTER_FAIL:
len = re_snprintf(event_buf, sizeof event_buf, "registering failed,%s", prm);
break;
case UA_EVENT_CALL_INCOMING:
// if (list_count(ua_calls(ua)) > 1) {
// play = mem_deref(play);
// (void)play_file(&play, player, "callwaiting.wav", 3);
// }
len = re_snprintf(event_buf, sizeof event_buf, "%s", "call incoming");
break;
case UA_EVENT_CALL_RINGING:
// play = mem_deref(play);
// (void)play_file(&play, player, "ringback.wav", -1);
len = re_snprintf(event_buf, sizeof event_buf, "%s", "call ringing");
break;
case UA_EVENT_CALL_PROGRESS:
len = re_snprintf(event_buf, sizeof event_buf, "%s", "call progress");
break;
case UA_EVENT_CALL_ESTABLISHED:
// play = mem_deref(play);
len = re_snprintf(event_buf, sizeof event_buf, "%s", "call established");
break;
case UA_EVENT_CALL_MENC:
if (prm[0] == '0')
len = re_snprintf(event_buf, sizeof event_buf, "call secure");
else if (prm[0] == '1')
len = re_snprintf(event_buf, sizeof event_buf, "call verify,%s", prm+2);
else if (prm[0] == '2')
len = re_snprintf(event_buf, sizeof event_buf, "call verified,%s", prm+2);
else
len = re_snprintf(event_buf, sizeof event_buf, "%s", "unknown menc event");
break;
case UA_EVENT_CALL_TRANSFER:
len = re_snprintf(event_buf, sizeof event_buf, "call transfer,%s", prm);
break;
case UA_EVENT_CALL_TRANSFER_FAILED:
len = re_snprintf(event_buf, sizeof event_buf, "transfer failed,%s", prm);
break;
case UA_EVENT_CALL_CLOSED:
// play = mem_deref(play);
// if (call_scode(call)) {
// const char *tone;
// tone = translate_errorcode(call_scode(call));
// if (tone) {
// (void)play_file(&play, player, tone, 1);
// }
// }
len = re_snprintf(event_buf, sizeof event_buf, "call closed,%s", prm);
break;
case UA_EVENT_MWI_NOTIFY:
len = re_snprintf(event_buf, sizeof event_buf, "mwi notify,%s", prm);
break;
case UA_EVENT_AUDIO_ERROR:
mem_deref(call);
goto out;
default:
goto out;
}
if( ev== UA_EVENT_CALL_INCOMING){
BaresipContext *x_ctx = (BaresipContext *)(arg);
x_ctx->ua=ua;
x_ctx->call=call;
}
out:
return;
}
#include <unistd.h>
static int pfd[2];
static pthread_t loggingThread;
static void *loggingFunction(void *arg) {
ssize_t readSize;
char buf[128];
while((readSize = read(pfd[0], buf, sizeof buf - 1)) > 0) {
if(buf[readSize - 1] == '\n') {
--readSize;
}
buf[readSize] = 0;
LOGE("22>%s", buf);
}
return 0;
}
static int runLoggingThread() {
setvbuf(stdout, 0, _IOLBF, 0);
setvbuf(stderr, 0, _IONBF, 0);
pipe(pfd);
dup2(pfd[1], 1);
dup2(pfd[1], 2);
if (pthread_create(&loggingThread, 0, loggingFunction, 0) == -1) {
return -1;
}
pthread_detach(loggingThread);
return 0;
}
extern "C" JNIEXPORT jstring JNICALL
Java_lilin_com_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++1";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT void JNICALL
Java_lilin_com_MainActivity_bareStart(JNIEnv *env, jobject instance) {
int err;
const char *path = "/data/data/lilin.com/files";
runLoggingThread();
memset(&g_ctx, 0, sizeof(g_ctx));
err = libre_init();
if (err)
goto out;
conf_path_set(path);
log_enable_debug(true);
err = conf_configure();
if (err) {
LOGD("conf_configure() failed: (%d)\n", err);
goto out;
}
err = baresip_init(conf_config());
if (err) {
LOGD("baresip_init() failed (%d)\n", err);
goto out;
}
play_set_path(baresip_player(), path);
err = ua_init("baresip v", true, false, false);
if (err) {
LOGD("ua_init() failed (%d)\n", err);
goto out;
}
uag_set_exit_handler(ua_exit_handler, NULL);
uag_event_register(ua_event_handler, &g_ctx);
err = conf_modules();
if (err) {
LOGE("conf_modules() failed (%d)\n", err);
goto out;
}
LOGD("Running main loop\n");
err = re_main(signal_handler);
LOGD("Running main loo1p\n");
out:
if (err) {
LOGE("stopping UAs due to error: (%d)\n", err);
ua_stop_all(true);
} else {
LOGE("main loop exit\n");
}
LOGD("closing");
ua_close();
module_app_unload();
conf_close();
baresip_close();
uag_event_unregister(ua_event_handler);
LOGD("unloading modules ...");
mod_close();
libre_close();
}extern "C"
JNIEXPORT void JNICALL
Java_lilin_com_MainActivity_bareStop(JNIEnv *env, jobject instance) {
// TODO
}
extern "C"
JNIEXPORT void JNICALL
Java_lilin_com_MainActivity_barejie(JNIEnv *env, jobject instance) {
LOGE("jieting");
re_thread_enter();
ua_answer( g_ctx.ua,g_ctx.call );
re_thread_leave();
}
5.把https://github.com/alfredh/baresip/tree/master/docs/examples 配置文件拷过来 res/raw下面 并参考他项目改下config 主要是加载模块或者用他的也行
最后改下运行的build.gradle 只用了64的
externalNativeBuild {
cmake {
abiFilters 'arm64-v8a'
}
}
6.开始写方法
创建个copy资源的
public class LinphoneMiniUtils {
public static void copyIfNotExist(Context context, int ressourceId, String target) throws IOException {
File lFileToCopy = new File(target);
if (!lFileToCopy.exists()) {
copyFromPackage(context, ressourceId, lFileToCopy.getName());
}
}
public static void copyFromPackage(Context context, int ressourceId, String target) throws IOException {
FileOutputStream lOutputStream = context.openFileOutput (target, 0);
InputStream lInputStream = context.getResources().openRawResource(ressourceId);
int readByte;
byte[] buff = new byte[8048];
while (( readByte = lInputStream.read(buff)) != -1) {
lOutputStream.write(buff,0, readByte);
}
lOutputStream.flush();
lOutputStream.close();
lInputStream.close();
}
}
7.把配置文件拷过去并启动baresip
8.将account配置文件添加一个sip账号格式参考原文件
9在添加一个按钮 为点击接听调下
barejie();
10.好了 如果没问题就可以跑了 选择一个桌面的sip软件 比如win10商店下载的linphone或者x-lite等等
启动后会先看到注册 200ok
桌面sip开始呼叫1003 点击接听就行了 说话双方都有声音了
视频通话请参考第二篇
更多参考https://github.com/juha-h/baresip-studio 和官方doc 写就ok了
更多交流群:261074724