[ C++/Java 实战 001] Android C++调用Notify()传递消息给 JAVA 分析

Android C++调用 Notify 传递消息给 JAVA 分析

    • 一、 C++ 与 Java 实现信号同步功能
      • 1. C++代码:Notify() 功能实现
      • 2. C++代码:CallStaticVoidMethod() 分析
      • 3. JNI 代码:android_hardware_Camera_native_setup() 分析
      • 4. JNI代码:post_event() 分析
      • 5. JAVA代码:postEventFromNative() 分析
      • 6. 总结整个调用过程
        • C ++ 中调用 Java 静态方法过程
        • Java 通过 JNI 调用 C++ 函数的过程


之前主要是做 驱动C 的,虽然也学过 C++/Java ,但毕竟不是天天做着的,会相对没那么熟悉,
现在应公司需求,要实现 C++ & Java 的某功能。
只能边学边实现,本文仅做笔记使用。


一、 C++ 与 Java 实现信号同步功能


1. C++代码:Notify() 功能实现

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中。

2. C++代码:CallStaticVoidMethod() 分析

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() 时当参数传入的。

3. JNI 代码:android_hardware_Camera_native_setup() 分析

我们知道: 如果要调用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);
}

4. JNI代码:post_event() 分析

通过前面的 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() 函数的。

5. JAVA代码: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;
            }
        }
    }

6. 总结整个调用过程

C ++ 中调用 Java 静态方法过程

// 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);  //开始发送事件
	}
}

Java 通过 JNI 调用 C++ 函数的过程

// 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);
	}
}

你可能感兴趣的:(06--Android,Java)