之前主要是做 驱动C 的,虽然也学过 C++/Java ,但毕竟不是天天做着的,会相对没那么熟悉,
现在应公司需求,要实现 C++ & Java 的某功能。
只能边学边实现,本文仅做笔记使用。
Notify() 主要的作用在于同步C++与Java 之间的状态,起一个同步信号的作用。
具体实现我们可能参考原生代码:
@ /frameworks/base/core/jni/android_hardware_Camera.cpp
----->
void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
{
ALOGV("notify");
JNIEnv *env = AndroidRuntime::getJNIEnv();
/*
* If the notification or msgType is CAMERA_MSG_RAW_IMAGE_NOTIFY, change it
* to CAMERA_MSG_RAW_IMAGE since CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed
* to the Java app.
*/
if (msgType == CAMERA_MSG_RAW_IMAGE_NOTIFY) {
msgType = CAMERA_MSG_RAW_IMAGE;
}
env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
mCameraJObjectWeak, msgType, ext1, ext2, NULL);
}
从上述代码中,可以看出,notify 是 C++ 的一个本地方法。
其主要作用就是:
通过 CallStaticVoidMethod 方法,调用上层Java 中的方法,并将 msgType 信号 传递进去给到 JAVA中。
CallStaticVoidMethod的函数原型如下:
static function CallStaticVoidMethod (clazz : IntPtr, methodID : IntPtr, args : jvalue[]) : void
主要作用是:
在C++中调用 Java对象中的一个静态方法,根据指定的methodID,可选传递参数(args)的数组到该方法。
在 上述Notify() 函数的代码中:
@ /frameworks/base/core/jni/android_hardware_Camera.cpp
env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
mCameraJObjectWeak, msgType, ext1, ext2, NULL);
==================>
mCameraJClass 是指向 java class 的指针。
原型如下:
class JNICameraContext: public CameraListener
{
private:
jobject mCameraJObjectWeak; // weak reference to java object
jclass mCameraJClass; // strong reference to java class
sp<Camera> mCamera; // strong reference to native object
}
==================>
其初始化的地方为 JNICameraContext 的构造函数中:
JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera)
{
mCameraJObjectWeak = env->NewGlobalRef(weak_this);
mCameraJClass = (jclass)env->NewGlobalRef(clazz);
mCamera = camera;
jclass faceClazz = env->FindClass("android/hardware/Camera$Face");
mFaceClass = (jclass) env->NewGlobalRef(faceClazz);
jclass rectClazz = env->FindClass("android/graphics/Rect");
mRectClass = (jclass) env->NewGlobalRef(rectClazz);
jclass pointClazz = env->FindClass("android/graphics/Point");
mPointClass = (jclass) env->NewGlobalRef(pointClazz);
mManualBufferMode = false;
mManualCameraCallbackSet = false;
}
可以看出该 clazz 是在构造 new JNICameraContext() 时当参数传入的。
我们知道: 如果要调用java 的静态方法,必须有如下几个过程:
// 1. 得到字节码
jclass jclass1 = (*env)->FindClass(env, "com/jaimex/ccalljava/JNI_C_Call_Java");
// 2. 得到方法,最后一个参数是方法签名
jmethodID jmethodIds = (*env)->GetStaticMethodID(env,jclass1,"sayHello", "(Ljava/lang/String;)V");
// 3. 得到方法
(*env)->CallStaticVoidMethod(env,jclass1, jmethodIds, jst);
因此,在android_hardware_Camera.cpp 中,
前面的 new JNICameraContext() 是在 android_hardware_Camera_native_setup() 函数中调用的。
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
sp<Camera> camera;
jclass clazz = env->GetObjectClass(thiz);
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
}
代码中,
android_hardware_Camera_native_setup 可以看出是一个JNI 方法,对应的是java中的native_setup方法,定义如下:
static const JNINativeMethod camMethods[] = {
{ "native_setup",
"(Ljava/lang/Object;IILjava/lang/String;)I",
(void*)android_hardware_Camera_native_setup },
}
注册地方为:
// Register native functions
return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods));
Java 中调用 native_setup 的地方为:
/frameworks/base/core/java/android/hardware/Camera.java
@ /frameworks/base/core/java/android/hardware/Camera.java
@Deprecated
public class Camera {
private native final int native_setup(Object camera_this, int cameraId, int halVersion,
String packageName);
private int cameraInitVersion(int cameraId, int halVersion) {
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
ActivityThread.currentOpPackageName());
}
}
从代码中可以看出,调用native_setup 是在camera 这个class中调用的。
因此前面的代码中就是说 jclass clazz 其实就是对就 public class Camera。
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
sp<Camera> camera;
jclass clazz = env->GetObjectClass(thiz);
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
}
通过前面的 3 中,我们知道了,mCameraJClass 其实就是 public class Camera的实例。
env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
mCameraJObjectWeak, msgType, ext1, ext2, NULL);
在如上代码中,其实就是要调用 fields.post_event 这个方法,传递的参数为 msgType。
fields.post_event 初始化的地方为:
// Get all the required offsets in java class and register native functions
int register_android_hardware_Camera(JNIEnv *env)
{
field fields_to_find[] = {
{ "android/hardware/Camera", "mNativeContext", "J", &fields.context },
};
find_fields(env, fields_to_find, NELEM(fields_to_find));
jclass clazz = FindClassOrDie(env, "android/hardware/Camera");
fields.post_event = GetStaticMethodIDOrDie(env, clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
// Register native functions
return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods));
}
从上面的代码,可以看出,fields.post_event 其实就是指向 postEventFromNative() 函数的。
@ /frameworks/base/core/java/android/hardware/Camera.java
@Deprecated
public class Camera {
private static final String TAG = "Camera";
private static void postEventFromNative(Object camera_ref,
int what, int arg1, int arg2, Object obj)
{
Camera c = (Camera)((WeakReference)camera_ref).get();
if (c.mEventHandler != null) {
// waht :对就的就是前面 msgType, 代表事件类型
Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);
c.mEventHandler.sendMessage(m); //开始发送事件
}
}
}
通过 sendMessage 发送消息后,最终消息就被上层接收到了,
其处理的代码,在 handleMessage() 中会对消息进行判断:
@ /frameworks/base/core/java/android/hardware/Camera.java
private class EventHandler extends Handler
{
private final Camera mCamera;
public EventHandler(Camera c, Looper looper) {
super(looper);
mCamera = c;
}
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case CAMERA_MSG_SHUTTER:
mShutterCallback.onShutter();
return;
case CAMERA_MSG_RAW_IMAGE:
mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera);
return;
case CAMERA_MSG_COMPRESSED_IMAGE:
mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
return;
case CAMERA_MSG_POSTVIEW_FRAME:
mPostviewCallback.onPictureTaken((byte[])msg.obj, mCamera);
return;
case CAMERA_MSG_FOCUS:
AutoFocusCallback cb = null;
cb = mAutoFocusCallback;
boolean success = msg.arg1 == 0 ? false : true;
cb.onAutoFocus(success, mCamera);
return;
case CAMERA_MSG_ZOOM:
mZoomListener.onZoomChange(msg.arg1, msg.arg2 != 0, mCamera);
return;
case CAMERA_MSG_PREVIEW_METADATA:
mFaceListener.onFaceDetection((Face[])msg.obj, mCamera);
return;
case CAMERA_MSG_ERROR :
mErrorCallback.onError(msg.arg1, mCamera);
return;
case CAMERA_MSG_FOCUS_MOVE:
mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera);
return;
default:
Log.e(TAG, "Unknown message type " + msg.what);
return;
}
}
}
// step 1: 获得java 的class
jclass clazz = FindClassOrDie(env, "android/hardware/Camera");
// step 2: 获得java class 中的postEventFromNative方法
fields.post_event = GetStaticMethodIDOrDie(env, clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
// step 3: 调用 postEventFromNative 方法
env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
mCameraJObjectWeak, msgType, ext1, ext2, NULL);
// step 4: postEventFromNative 的实现代码
public class Camera {
private static void postEventFromNative(Object camera_ref,
int what, int arg1, int arg2, Object obj)
{
Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);
c.mEventHandler.sendMessage(m); //开始发送事件
}
}
// 1. java 中的 方法声明, native 类型
private native final int native_setup(Object camera_this, int cameraId, int halVersion,
String packageName);
// 2. 在Java 中直接调用 native_setup
private int cameraInitVersion(int cameraId, int halVersion) {
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
ActivityThread.currentOpPackageName());
}
// 3. jni 代码中,对 JAVA 中的 native_setup 方法绑定
// 为 C++ 中的android_hardware_Camera_native_setup 函数
static const JNINativeMethod camMethods[] = {
{ "native_setup",
"(Ljava/lang/Object;IILjava/lang/String;)I",
(void*)android_hardware_Camera_native_setup },
}
// 4. 在C++ 函数中,通过CallStaticVoidMethod 调用Java 方法。
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
jclass clazz = env->GetObjectClass(thiz);
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
====>{
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, msgType, ext1, ext2, NULL);
}
}