Android中OboeSinePlayer示例代码崩溃问题求助
解决Oboe正弦播放器崩溃问题
我帮你梳理下导致崩溃的几个核心原因,以及对应的解决办法:
1. 最关键的问题:OboeSinePlayer对象生命周期过短
你在JNI方法oboeSinePlayer()里创建了一个局部的OboeSinePlayer实例,方法执行完后这个对象就会被销毁,但音频流还在运行,回调onAudioReady时会引用已经被释放的对象,这必然导致崩溃。
修复方案:
把OboeSinePlayer改成全局静态实例,保证它的生命周期和App一致:
// 在OboeSinePlayer.cpp顶部声明全局实例 static OboeSinePlayer sOboePlayer; // 修正JNI方法的返回类型(Java层是void,之前写了jstring会导致不匹配) extern "C" JNIEXPORT void JNICALL Java_com_example_gettingstartedoboe_MainActivity_oboeSinePlayer(JNIEnv *env, jobject /* this */) { sOboePlayer.start(); }
2. 解决liboboe.so找不到的问题(UnsatisfiedLinkError)
- 先确认CMakeLists.txt里的
OBOE_DIR路径完全正确,指向你本地Oboe仓库的根目录 - 添加Oboe动态库编译选项,确保
liboboe.so会被打包到APK:
在CMakeLists.txt里add_subdirectory之前添加:set(OBOE_BUILD_SHARED_LIBS ON) - 检查App的build.gradle,确保指定了正确的ABI架构,和Oboe编译的架构匹配:
android { defaultConfig { ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } }
3. 处理SIGILL致命信号错误
这个错误通常是指令集不兼容,或者代码存在未定义行为:
- 检查OboeSinePlayer的成员变量初始化顺序:你的
mPhaseIncrement依赖kTwoPi、kFrequency、kSampleRate,虽然当前声明顺序没问题,但把初始化移到构造函数里更稳妥,避免潜在的初始化顺序问题:// 在OboeSinePlayer类里添加构造函数 OboeSinePlayer() { mPhaseIncrement = kTwoPi * kFrequency / static_cast<double>(kSampleRate); } - 确保Oboe编译时使用的NDK版本和你的App一致,避免指令集不兼容。
4. 必须添加错误处理,排查潜在问题
你的start()方法里没有检查Oboe的操作结果,很多错误会被掩盖。添加日志和错误检查:
// 先引入日志头文件 #include <android/log.h> #define LOG_TAG "OboePlayer" #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) bool OboeSinePlayer::start() { oboe::AudioStreamBuilder builder; // 检查openManagedStream的结果 oboe::Result result = builder.setSharingMode(oboe::SharingMode::Shared) ->setPerformanceMode(oboe::PerformanceMode::LowLatency) ->setChannelCount(kChannelCount) ->setSampleRate(kSampleRate) ->setFormat(oboe::AudioFormat::Float) ->setCallback(this) ->openManagedStream(managedStream); if (result != oboe::Result::OK) { LOGE("Failed to open audio stream: %s", oboe::convertToText(result)); return false; } // 检查start的结果 result = managedStream->requestStart(); if (result != oboe::Result::OK) { LOGE("Failed to start audio stream: %s", oboe::convertToText(result)); return false; } return true; }
5. 调整MainActivity的调用顺序
虽然不是崩溃直接原因,但把音频启动放在UI初始化之后更合理:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = findViewById(R.id.sample_text); tv.setText(stringFromJNI()); oboeSinePlayer(); // 移到这里,避免在UI未初始化时启动音频 }
按照这些步骤修改后,应该能解决崩溃问题,实现持续的正弦音播放。
内容的提问来源于stack exchange,提问作者Al G Johnston
相关产品推荐
相关产品推荐

