Webrtc 中,Java API是C++层的一层接口包装,但是没有像Android中那样,可以直接对应的找到Java层类
对应的C++层的JNI接口文件。
在Webrtc中,Java层使用注解的方式来标记需要进行JNI接口生成的头文件和函数选项:
用到的注解:
namespace webrtc {
namespace jni {
///函数...
}
}
没有指定NativeClassQualifiedName的时候,调用的就是include 了生成的头文件的源文件的同名方法实现;
@NativeClassQualifiedName("CPPClass::InnerClass")
private native double nativeMethodOtherP0(long nativePtr);
对应调用c++层的
JNI_GENERATOR_EXPORT jdouble
Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethodOtherP0(JNIEnv*
env, jobject jcaller,
jlong nativePtr) {
//指定调用用CPPClass::InnerClass中的方法
CPPClass::InnerClass* native =
reinterpret_cast<CPPClass::InnerClass*>(nativePtr);
CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0);
//调用方法
return native->MethodOtherP0(env, base::android::JavaParamRef<jobject>(env,
jcaller));
}
上面讲的Java层的注解只是一个标记,并不是用
Java的注解处理器
来进行处理的,而是使用Python脚本来解析和生成文件,类,函数声明和函数实现的。
JNI接口的头文件生成是使用文件:
src\base\android\jni_generator\jni_generator.py
来进行解析和生成的。
生成的文件为 “java_name” + _jni.h
比如Java文件为AudioTest
, 那么如果有JNINamespace注解,那就会生成一个AudioTest_jni.h
文件
调用跟踪方法:
比如:
@org.webrtc.JNINamespace("webrtc::jni") //首先有这个注解,命名空间为webrtc::jni
public class AudioTrack extends org.webrtc.MediaStreamTrack {
public AudioTrack(long nativeTrack) {
super(nativeTrack);
}
...
public void setVolume(double volume) {
nativeSetVolume(super.nativeTrack, volume);
}
private static native void nativeSetVolume(long track, double volume); //找这个native方法
}
这个只生成头文件,源文件需要自己实现,我们只需要找到对应的源文件就可以知道调用的对象是那个函数;
//src\sdk\android\src\jni\pc\audiotrack.cc
#include "api/mediastreaminterface.h"
#include "sdk/android/generated_peerconnection_jni/jni/AudioTrack_jni.h"
namespace webrtc {
namespace jni {
//调用的native方法就是这个
static void JNI_AudioTrack_SetVolume(JNIEnv*,
const JavaParamRef<jclass>&,
jlong j_p,
jdouble volume) {
rtc::scoped_refptr<AudioSourceInterface> source(
reinterpret_cast<AudioTrackInterface*>(j_p)->GetSource());
source->SetVolume(volume);
}
} // namespace jni
} // namespace webrtc
JNI_ + "class_name" + "Method_name()" //注意,method匹配的方法去掉了native前缀的大驼峰形式;
比如:
package org.chromium.example.jni_generator;
@JNINamespace("base::android")
class SampleForTests {
private native void nativeSetNonPODDatatype(Rect rect);
}
会生成为
namespace base {
namespace android {
//转换的简单匹配接口,我们在生成之前看到的接口就是这个,原文件中会对这个接口进行实现;
static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv* env, const
base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jobject>& rect);
//这个是生成的JNI规则匹配接口
JNI_GENERATOR_EXPORT void
Java_org_chromium_example_jni_1generator_SampleForTests_nativeSetNonPODDatatype(JNIEnv*
env, jobject jcaller,
jobject rect) {
//接口中默认调用了生成的转换的简单匹配接口
return JNI_SampleForTests_SetNonPODDatatype(env,
base::android::JavaParamRef<jobject>(env, jcaller),
base::android::JavaParamRef<jobject>(env, rect));
}
}
}
代码跟踪流程可以总结如下:
@JNINamespace("base::android")
public class AudioTest {
public void nativeTest();
}