Android NDK - 引用 JNIEnv 从 C++ 调用 Java

Android NDK - referencing JNIEnv to call Java from C++

我是 C++ 的新手,我在这里使用 Superpowered FrequencyDomain 示例: https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine/blob/master/Examples_Android/FrequencyDomain/app/src/main/jni/FrequencyDomain.cpp

我想用从这个 while 循环中接收到的最响亮的频率不断更新 TextView:

static bool audioProcessing(void * __unused clientdata, short int *audioInputOutput, int numberOfSamples, int __unused samplerate) {
SuperpoweredShortIntToFloat(audioInputOutput, inputBufferFloat, (unsigned int)numberOfSamples); // Converting the 16-bit integer samples to 32-bit floating point.
frequencyDomain->addInput(inputBufferFloat, numberOfSamples); // Input goes to the frequency domain.

// In the frequency domain we are working with 1024 magnitudes and phases for every channel (left, right), if the fft size is 2048.
while (frequencyDomain->timeDomainToFrequencyDomain(magnitudeLeft, magnitudeRight, phaseLeft, phaseRight)) {

我想我需要做这样的事情:

jclass classs = env->FindClass("com/superpowered/frequencydomain/MainActivity");
jmethodID method = env->GetMethodID(classs, "updateTextViewFromJNI","(I)V");
env->CallVoidMethod(thiz, method, myJavaInt);

但这些是示例 C++ 函数中唯一可以访问 env 和 thiz 的行:

void callJavaMethod(JNIEnv* env,jobject thiz) {...previous 3 lines...}

像这样调用 Java 函数:

public void updateTextViewFromJNI(int i) {
    txtLoudestFreq.setText(Integer.toString(i));
}

我一直在尝试不同的方法来获取 JNIEnv 和 jobject,但我还没有成功。我看到它们在这里未使用:

extern "C" JNIEXPORT void Java_com_superpowered_frequencydomain_MainActivity_FrequencyDomain(JNIEnv * __unused javaEnvironment, jobject __unused obj, jint samplerate, jint buffersize)

但我不确定如何访问它们:

audioProcessing

我试过让它们全球化。从我读过的内容来看,我试图获得对它们的参考,但不知道如何去做。我需要执行哪些步骤才能调用如下内容:

env->CallVoidMethod(thiz, method, myJavaInt);

来自 audioProcessing 内部?非常感谢!

不建议从音频处理线程调用 Java,因为它涉及多个阻塞调用。

Env 和 thiz 是特定于线程的,因线程而异。为音频处理线程获取它们是一个很大的禁忌。

反之则更好:

  • 用您想要的结果更新音频处理回调中的数组 显示。
  • 创建一个 JNI 函数到 return,数组的值到 Java。
  • 定期从 Runnable 调用该 JNI 函数(在 Java 中)。