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 中)。
我是 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 中)。