Intereting Posts
Создание ZeroMQ для Android-эмулятора x86 Глобальная смерть AudioTrack Альтернатива наблюдаемому шаблону? Android Espresso: Подождите, пока активность закончится / запустится Android: состояние приложения, когда приложение выходит из стека из-за ограничения памяти Как получить последнюю дату изменения для списка контактов (Добавить / Удалить / Изменить) В чем причина «FimgApiStretch: стрейч не удался» в Android Android: цифры Проблема Ошибка при создании подпроекта android при использовании команды android для работы с телефоном. Получил эту ошибку с помощью retrofit2 & OkHttp3. Не удалось разрешить хост «<имя-хоста>»: нет адреса, связанного с именем хоста GLES20.glUniform4fv дает GL_INVALID_OPERATION (1282) Как я могу выделить текстовое содержимое в уведомлении? Установите альфа-прозрачность только для макета, а не для своих детей Что такое разумная политика лицензирования с использованием лицензирования на Android Market Установить вход / выход текста для кнопки в Android Android SDK 4.0?

Как обрабатывать вызовы в AudioTrack из jni без сбоев?

Я пытался записать AudioTrack из jni-обратного вызова, и я получаю сигнал 7 (SIGBUS), fault addr 00000000.

Я рассмотрел пример Wolf3D для odroid, и они, похоже, используют android.os.Handler для публикации Runnable, который будет делать обновление в правильном контексте потока. Я также попробовал AttachCurrentThread, но в этом случае я тоже не могу.

Он работает, чтобы воспроизводить звук при запуске из конструктора, даже если я обертываю его в поток, а затем отправляю его обработчику. Когда я делаю «тот же» через обратный вызов из jni, он терпит неудачу. Я предполагаю, что я придерживаюсь некоторых правил, но я не мог понять, кто они. До сих пор я не нашел ответа здесь на SO.

Поэтому я задаюсь вопросом, знает ли кто, как это должно быть сделано.

EDIT: ответили ниже.

Следующий код служит для иллюстрации проблемы.

Ява:

package com.example.jniaudiotrack; import android.app.Activity; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; import android.os.Handler; import android.util.Log; public class JniAudioTrackActivity extends Activity { AudioTrack mAudioTrack; byte[] mArr; public static final Handler mHandler = new Handler(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mArr = new byte[2048]; for (int i = 0; i < 2048; i++) { mArr[i] = (byte) (Math.sin(i) * 128); } mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT, 2048, AudioTrack.MODE_STREAM); mAudioTrack.play(); new Thread(new Runnable() { public void run() { mHandler.post(new Runnable() { public void run() { mAudioTrack.write(mArr, 0, 2048); Log.i(TAG, "*** Handler from constructor ***"); } }); } }).start(); new Thread(new Runnable() { public void run() { audioFunc(); } }).start(); } public native void audioFunc(); @SuppressWarnings("unused") private void audioCB() { mHandler.post(new Runnable() { public void run() { mAudioTrack.write(mArr, 0, 2048); Log.i(TAG, "*** audioCB called ***"); } }); } private static final String TAG = "JniAudioTrackActivity"; static { System.loadLibrary("jni_audiotrack"); } } 

каст:

 #include <jni.h> extern "C" { JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj); } JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj) { JNIEnv* jniEnv; JavaVM* vm; env->GetJavaVM(&vm); vm->AttachCurrentThread(&jniEnv, 0); jclass cls = env->GetObjectClass(obj); jmethodID audioCBID = env->GetMethodID(cls, "audioCB", "()V"); if (!audioCBID) { return; } env->CallVoidMethod(cls, audioCBID); } 

Фрагмент трассировки:

 I/DEBUG ( 1653): pid: 9811, tid: 9811 >>> com.example.jniaudiotrack <<< I/DEBUG ( 1653): signal 7 (SIGBUS), fault addr 00000000 I/DEBUG ( 1653): r0 00000800 r1 00000026 r2 00000001 r3 00000000 I/DEBUG ( 1653): r4 42385726 r5 41049e54 r6 bee25570 r7 ad00e540 I/DEBUG ( 1653): r8 000040f8 r9 41048200 10 41049e44 fp 00000000 I/DEBUG ( 1653): ip 000000f8 sp bee25530 lr ad02dbb5 pc ad012358 cpsr 20000010 I/DEBUG ( 1653): #00 pc 00012358 /system/lib/libdvm.so 

Кажется, проблема памяти. Создание mAudioTrack и mArr static позволило решить проблему. Я посылал неправильный объект для обратного вызова. См. Комментарий от fadden. Я удалил вызов AttachCurrentThread, так как это не имело никакого значения в этом случае.

Ява:

 package com.example.jniaudiotrack; import android.app.Activity; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; import android.os.Handler; import android.util.Log; public class JniAudioTrackActivity extends Activity { public AudioTrack mAudioTrack; public byte[] mArr; public static Handler mHandler = new Handler(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mArr = new byte[2048]; for (int i = 0; i < 2048; i++) { mArr[i] = (byte) (Math.sin(i) * 128); } mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT, 2048, AudioTrack.MODE_STREAM); mAudioTrack.play(); new Thread(new Runnable() { public void run() { audioFunc(); } }).start(); } public native void audioFunc(); @SuppressWarnings("unused") private void audioCB() { mHandler.post(new Runnable() { public void run() { mAudioTrack.write(mArr, 0, 2048); Log.i(TAG, "*** audioCB called ***"); } }); } private static final String TAG = "JniAudioTrackActivity"; static { System.loadLibrary("jni_audiotrack"); } } 

Cpp:

 #include <jni.h> extern "C" { JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj); } JNIEXPORT void Java_com_example_jniaudiotrack_JniAudioTrackActivity_audioFunc(JNIEnv* env, jobject obj) { jclass cls = env->GetObjectClass(obj); jmethodID audioCBID = env->GetMethodID(cls, "audioCB", "()V"); if (!audioCBID) { return; } env->CallVoidMethod(obj, audioCBID); }