標籤:des android style color io 使用 java ar for
很多場合都有這樣的需求,由於以前都是java調用c的介面,沒有做過回調,今天花了大半天時間把這個流程跑通了,記錄一下,以備後用。這裡發句牢騷,那些網上分享出來的代碼,請問你們確實是能正常工作嗎?還有查來查去都是那幾份,大家轉載精神可嘉啊
jni相關標頭檔代碼
/* DO NOT EDIT THIS FILE - it is machine generated */#include/* Header for class com_example_ndktest_CallbackTest */#ifndef _Included_com_example_ndktest_CallbackTest#define _Included_com_example_ndktest_CallbackTest#ifdef __cplusplusextern "C" {#endif/** Class: com_example_ndktest_CallbackTest* Method: start* Signature: ()V*/JNIEXPORT void JNICALL Java_com_example_ndktest_CallbackTest_start(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
具體實現代碼
#include<stdlib.h>#include<pthread.h>#include<jni.h>#include<android/log.h>#include "com_example_ndktest_CallbackTest.h"#define LOG_TAG "jni"#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)jmethodID mid;jclass objclass;jobject mobj;pthread_t thread;JavaVM *m_vm;//初始化的時候會調進來一次,在這個方法裡持有jvm的引用JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){ m_vm=vm; JNIEnv* env = NULL; jint result = -1; if(m_vm){ LOGD("m_vm init success"); }else{ LOGD("m_vm init failed"); } if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK){ return result; } return JNI_VERSION_1_4;}JNIEnv* getJNIEnv(int* needsDetach){ JNIEnv* env = NULL; jint result = -1; if ((*m_vm)->GetEnv(m_vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK){ int status = (*m_vm)->AttachCurrentThread(m_vm, &env, 0); if (status < 0){ LOGD("failed to attach current thread"); return NULL; } *needsDetach = 1; } LOGD("GetEnv Success"); return env;}void *thread_run(){ LOGD("thread start"); int needsDetach; JNIEnv *evn=getJNIEnv(&needsDetach); LOGD("start noop callback"); int i; for(i = 0; i < 100; i++){ jstring jstr = (*evn) -> NewStringUTF(evn, "I am Fengfei"); LOGD("invoke callback"); (*evn)->CallVoidMethod(evn, mobj, mid, jstr); jthrowable exception = (*evn)->ExceptionOccurred(evn); if (exception) { (*evn)->ExceptionDescribe(evn); } sleep(2); } if(needsDetach) (*m_vm)->DetachCurrentThread(m_vm);}JNIEXPORT void JNICALL Java_com_example_ndktest_CallbackTest_start(JNIEnv *evn, jobject object){LOGD("call start"); //在子線程中不能這樣用 //jclass tclass = (*evn)->FindClass(evn, "com/example/ndktest/CallbackTest"); //這種寫法可以用在子線程中 objclass=(*evn)->GetObjectClass(evn, object); mid = (*evn)->GetMethodID(evn, objclass, "callback", "(Ljava/lang/String;)V"); //JNI 函數參數中 jobject 或者它的子類,其參數都是 local reference。Local reference 只在這個 JNI函數中有效,JNI函數返回後,引用的對象就被釋放,它的生命週期就結束了。若要留著日後使用,則需根據這個 local reference 建立 global reference。Global reference 不會被系統自動釋放,它僅當被程式明確調用 DeleteGlobalReference 時才被回收。(JNI多線程機制) mobj=(*evn)->NewGlobalRef(evn, object); pthread_create(&thread, NULL, thread_run, NULL);}
java代碼(具體怎麼產生.so,參看android ndk使用)
package com.example.ndktest;public class CallbackTest {static { System.loadLibrary("callback");}public native void start();public void callback(String str){ System.out.println(str);}}
android使用c通過jni回調java