jni回撥java方法

yingxian_Fei發表於2016-04-20

1、jni普通方法中回撥java方法

	static void android_server_LSPowerService_set_acc_callback(JNIEnv* env, jobject obj,jstring name)  {
		Mutex::Autolock l(sLock); 
		const String8 nameString = Utility::getStringValue(env, name);
		jclass localRef = env->GetObjectClass(obj);
		jmethodID methodId = env->GetMethodID(localRef, nameString.string(), "(I)V");	
		env->CallVoidMethod(obj, methodId, cAccStatus);
	}

2、jni執行緒中回撥java方法

由於java呼叫jni時傳遞的JNIEnv和jobject會在jni返回時被釋放,因此需要使用的引數申請全域性的變數使用。可以參考如下例子:

#define LOG_TAG "LSPowerServicejni"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
 
#include <utils/Log.h> 
#include <ls/app_comm.h>  
#include <stdio.h>
#include <pthread.h>
#include <sys/select.h>

namespace android
{    class Utility {
    public:
        static String8 getStringValue(JNIEnv* env, jobject object, const char* fieldName);

        static char* getByteArrayValue(
                JNIEnv* env, jobject object, const char* fieldName, int* dataLength);

        static char* getByteArrayValue(
                JNIEnv* env, jbyteArray byteArray, int* dataLength);

        static String8 getStringValue(JNIEnv* env, jstring string);

        static int getIntValue(JNIEnv* env, jobject object, const char* fieldName);
    };

    String8 Utility::getStringValue(JNIEnv* env, jobject object, const char* fieldName) {
        /* Look for the instance field with the name fieldName */
        jfieldID fieldID
            = env->GetFieldID(env->GetObjectClass(object), fieldName , "Ljava/lang/String;");
    
        if (NULL != fieldID) {
            jstring valueString = (jstring) env->GetObjectField(object, fieldID);
            return Utility::getStringValue(env, valueString);
        }
    
        String8 dataString("");
        return dataString;
    }
    
    String8 Utility::getStringValue(JNIEnv* env, jstring string) {
        String8 dataString("");
    
        if (NULL != string && string != env->NewStringUTF("")) {
            char* bytes = const_cast< char* > (env->GetStringUTFChars(string, NULL));
    
            const int length = strlen(bytes) + 1;
            char *data = new char[length];
            strncpy(data, bytes, length);
            dataString = String8(data);
    
            env->ReleaseStringUTFChars(string, bytes);
            delete [] data; data = NULL;
        }
        return dataString;
    }
    
    char* Utility::getByteArrayValue(
                JNIEnv* env, jobject object, const char* fieldName, int* dataLength) {
    
        *dataLength = 0;
    
        jfieldID fieldID = env->GetFieldID(env->GetObjectClass(object), fieldName , "[B");
    
        if (NULL != fieldID) {
            jbyteArray byteArray = (jbyteArray) env->GetObjectField(object, fieldID);
            return Utility::getByteArrayValue(env, byteArray, dataLength);
        }
        return NULL;
    }
    
    char* Utility::getByteArrayValue(JNIEnv* env, jbyteArray byteArray, int* dataLength) {
        char* data = NULL;
        if (NULL != byteArray) {
            jint length = env->GetArrayLength(byteArray);
    
            *dataLength = length;
            if (0 < *dataLength) {
                data = new char[length];
                env->GetByteArrayRegion(byteArray, (jint)0, length, (jbyte *) data);
            }
        }
        return data;
    }
    
    int Utility::getIntValue(JNIEnv* env, jobject object, const char* fieldName) {
        jfieldID fieldID;
        int intValue = -1;
            
        jclass clazz = env->GetObjectClass(object);
        /* Look for the instance field with the name fieldName */
        fieldID = env->GetFieldID(clazz, fieldName , "I");
    
        if (NULL != fieldID) {
            intValue = (int) env->GetIntField(object, fieldID);
        }
    
        return intValue;
    }

    class LsNativeMiscDevice{
        protected:
            class DoReadThread : public Thread {
                private :
                    bool                 mRequestExit;
                    LsNativeMiscDevice*  mMiscDevice;

                public:
                    DoReadThread(LsNativeMiscDevice *dev) 
                        : Thread(false),mRequestExit(false),mMiscDevice(dev)  {

                    }
                    
                    ~DoReadThread()  {
                        mRequestExit = false;
                        mMiscDevice = NULL;
                    }
                    
                    void startThread() {
                        run("LsPowerLoopThread", PRIORITY_URGENT_DISPLAY);
                    }
                    
                    void stopThread() {
                        mRequestExit = true;
                    }
                    
                    virtual bool threadLoop() {
                        if (mRequestExit) {
                            return false;
                        }
                        return mMiscDevice ? mMiscDevice->readData() : false;
                    }            
            };

            class DataCallBackDef : public RefBase{
                protected:                
                    JavaVM*     mJavaVM;
                    jobject     mJavaObject;
                    jmethodID   mMethodId;                                
                    
                public:
                    DataCallBackDef(JNIEnv* env,jobject& obj,jmethodID methodId)  {
                        if (env->GetJavaVM(&mJavaVM) < JNI_OK) {
                            ALOGW("NativeActivity GetJavaVM failed");
                            return;
                        }
                        mJavaObject = env->NewGlobalRef(obj);    
                        mMethodId = methodId;
                    }
                    
                    ~DataCallBackDef()  {
                        mMethodId = NULL;
                        mJavaVM = NULL;
                        if(mJavaObject != NULL)  {
                            JNIEnv *env = AndroidRuntime::getJNIEnv();
                            env->DeleteGlobalRef(mJavaObject);
                            mJavaObject = NULL;    
                        }
                    }

                    void callBack(const int value)  {                        
                        if(mJavaVM != NULL && mJavaObject != NULL)  {
                            JNIEnv*     env;
                            mJavaVM->AttachCurrentThread(&env, NULL);
                            env->CallVoidMethod(mJavaObject, mMethodId, value);
                            mJavaVM->DetachCurrentThread();
                        }                    
                    }
            };
            
        private:

            pthread_rwlock_t            mRwLock;
            sp<DoReadThread>            mReadThread;    
            sp<DataCallBackDef>         mShakeupCallBack;
            JNIEnv*                     mEnv;

        public:
            LsNativeMiscDevice(JNIEnv *env) : mEnv(env)
            {
                mReadThread = new DoReadThread(this);
                mShakeupCallBack = NULL;
                pthread_rwlock_init(&mRwLock, NULL);
            }

            ~LsNativeMiscDevice()  {
                if(mReadThread != NULL)  {
                    mReadThread->stopThread();
                    mReadThread.clear();
                    mReadThread = 0;
                }
                if(mShakeupCallBack != NULL)  {
                    mShakeupCallBack.clear();
                    mShakeupCallBack = 0;
                }
                pthread_rwlock_destroy(&mRwLock);
            }    

            void setShakeupCallBack(JNIEnv *env,jobject& obj,jmethodID id)  {
                Mutex::Autolock locker(&mCallbackLock);
                //create new
                if(mShakeupCallBack != NULL)  {
                    mShakeupCallBack.clear();
                    mShakeupCallBack = 0;                        
                }
                mShakeupCallBack = new DataCallBackDef(env,obj,id);
                ALOGD("end setShakeupCallBack\n");
            }            

            int startLoopData()  {        
                Mutex::Autolock locker(&mObjectLock);                                
                if(mReadThread != NULL)  {
                     mReadThread->startThread();
                }
                return 0;
            }

            int stopLoopData()  {
                Mutex::Autolock locker(&mObjectLock);
                //stop thread.
                if(mReadThread != NULL)  {
                     mReadThread->stopThread();
                }
                return 0;
            }

            bool readData()  {
                if(mShakeupCallBack != NULL)  {
                   mShakeupCallBack->callBack(mShakeupStatus);
                }    
                return true;
            }                
    };

    static LsNativeMiscDevice* mLsPowerDevice;
    static Mutex sLock;

    static void android_server_LSPowerService_set_shakeup_callback(JNIEnv* env, jobject obj,jstring name)  {
        Mutex::Autolock l(sLock); 
        ALOGD("android_server_LSPowerService_set_shakeup_callback.");
        if(mLsPowerDevice != NULL)  {
            const String8 nameString = Utility::getStringValue(env, name);
            jclass localRef = env->GetObjectClass(obj);
            jmethodID methodId = env->GetMethodID(localRef, nameString.string(), "(I)V");    
            mLsPowerDevice->setShakeupCallBack(env,obj,methodId);               
        }
    }        
};

相關推薦閱讀資料:

http://m.android100.org/?host=www.android100.org&src=http%3A%2F%2Fwww.android100.org%2Fhtml%2F201308%2F19%2F3994.html

http://m.2cto.com/kf/201202/119764.html

相關文章