У меня проблема с NDK.
В моем методе JNI_OnLoad я кэширую указатель JavaVm, класс, который вызвал метод, и идентификатор метода, который я использую позже:
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved){
JNIEnv *env;
cachedJVM = jvm;
if((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6)){
LOG_ERROR("Could not get JNIEnv*");
return JNI_ERR;
}
javaClass = (*env)->FindClass(env, "org/test/opensl/AudioProcessor");
if(javaClass == NULL){
LOG_ERROR("Could not get java class");
return JNI_ERR;
}
javaCallbackMID = (*env)->GetMethodID(env, javaClass, "enqueueAudio", "([B)V");
if(javaCallbackMID == NULL){
LOG_ERROR("Could not get method identifier");
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
У меня есть небольшой служебный метод, определенный следующим образом, который должен дать мне указатель на JNIEnv:
JNIEnv* JNU_GetEnv(){
JNIEnv* env;
(*cachedJVM)->GetEnv(cachedJVM, (void**)&env, JNI_VERSION_1_6);
return env;
}
И, наконец, У меня есть обратный вызов от OpenSL ES SLAndroidSimpleBufferQueueItf
, который я хочу обрабатывать записанный звук из SLRecordItf
:
void recorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context){
SLresult result;
JNIEnv* env;
recorderContext* thisContext = (recorderContext*)context;
env = JNU_GetEnv();
if(env == NULL){
LOG_ERROR("Could not get JNIEnv*");
return;
}
jbyteArray data = (*env)->NewByteArray(env, MAX_PACKET_SIZE);
if(data == NULL){
LOG_ERROR("No memory could be allocated for buffer");
return;
}
(*env)->SetByteArrayRegion(env, data, 0, MAX_PACKET_SIZE, recorderBuffer);
(*env)->CallByteMethodA(env, thisContext->caller, javaCallbackMID, data);
(*env)->DeleteLocalRef(env, data);
result = (*bq)->Enqueue(bq, recorderBuffer,
RECORDER_FRAMES * sizeof(jbyte));
checkError(result, "Unable to enqueue new buffer");
}
Где параметр контекста для метода обратного вызова содержит только ссылку на объект, который вызвал собственный метод. Это самоопределенная структура вроде этой:
typedef struct recorderContext{
jobject caller;
} recorderContext;
Однако каждый раз, когда я пытаюсь запустить ее, я получаю сообщение об ошибке «Не удалось получить JNIEnv *»
от метода обратного вызова.
Мой вопрос в основном сводится к следующему: почему я могу получить указатель на JNIEnv в методе JNI_OnLoad, но не в RecorderCallback, поскольку оба используют один и тот же указатель Java VM для получения JNIEnv?
Мне это нужно обратный вызов для передачи записанного аудио обратно на мой уровень Java для дальнейшей обработки ...