Android应用中CycloneDDS创建Domain Participant失败排查
我能在ADB shell中编译运行可执行文件,正常创建CycloneDDS的Domain Participant;但将逻辑集成到Android GUI应用,通过JNI调用native函数创建时返回-1(创建失败)。相关代码如下:
ADB可执行文件代码
main.cpp
#include <iostream> #include <dds/dds.h> int main(int argc, char *argv[]) { dds_entity_t dp = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); std::cout << "Domain participant: " << dp << std::endl; return 0; }
CMakeLists.txt
cmake_minimum_required(VERSION 3.21) project(android-subscriber) find_package(CycloneDDS REQUIRED) add_executable(android-subscriber main.cpp) target_link_libraries(android-subscriber PRIVATE CycloneDDS::ddsc)
构建参数
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "CMAKE_TOOLCHAIN_FILE": "<NDK_PATH>/build/cmake/android.toolchain.cmake", "ANDROID_ABI": "x86_64", "ANDROID_NATIVE_API_LEVEL": "28" }
运行结果
Domain participant: 863414216
GUI应用相关代码
native-dds-lib.cpp片段
static dds_entity_t dp; extern "C" JNIEXPORT jstring JNICALL Java_mainactivity_MainActivity_nativeDdsInit(JNIEnv *env, jobject thiz) { std::stringstream ss; dp = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); ss << "Domain participant: " << dp; return env->NewStringUTF(ss.str().c_str()); }
MainActivity.java片段
public class MainActivity extends Activity implements SurfaceHolder.Callback { private native String nativeDdsInit(); private ActivityMainBinding binding; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding.textviewMessage.setText(nativeDdsInit()); } static { System.loadLibrary("android_publisher"); } ... }
GUI应用运行显示 Domain participant: -1,即创建失败。
排查步骤
检查权限配置:Android GUI应用需要网络权限才能进行DDS通信,在
AndroidManifest.xml中添加:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />若targetSdkVersion>=23,需在代码中动态申请权限。
获取具体错误信息:调用
dds_create_participant失败后,通过CycloneDDS的错误API获取详情,修改native代码:extern "C" JNIEXPORT jstring JNICALL Java_mainactivity_MainActivity_nativeDdsInit(JNIEnv *env, jobject thiz) { std::stringstream ss; dp = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); ss << "Domain participant: " << dp; if (dp < 0) { int err = dds_get_last_error(); ss << ", Error: " << dds_strerror(err); } return env->NewStringUTF(ss.str().c_str()); }验证库链接情况:确认GUI应用的CMakeLists.txt和ADB版本配置一致,正确链接CycloneDDS库。用
readelf -d libandroid_publisher.so查看动态依赖,确保libddsc.so等依赖存在。对比运行环境差异:在GUI应用中打印进程环境变量(如
getenv("CYCLONEDDS_URI")),和ADB shell中的环境对比,排查是否缺少CycloneDDS所需配置。尝试显式Domain配置:不要使用
DDS_DOMAIN_DEFAULT,而是通过dds_qos_t设置参数,或指定CYCLONEDDS_URI配置文件,验证是否因默认配置不兼容导致失败。切换线程上下文:将
dds_create_participant调用放到后台线程执行,避免主线程的上下文限制或阻塞问题。
内容的提问来源于stack exchange,提问作者Robert Kalinke

