This is a cpp file which I used to jni call and callback in one of my project. I post it here so that i do not have to re r&d. It uses android 4.0.3 source to compile.
#include "JNIMain.h" #include "GlobalResource.h" #include "Recorder.h" JavaVM *javaVM; jobject recorderJava; Recorder recorder; jmethodID audioCallBackID; jmethodID videoCallBackID; extern sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, struct JNICameraContext** context); extern "C" { Recorder* recorder; jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { GlobalResource* gr = GlobalResource::getInstance(); javaVM = jvm; return JNI_VERSION_1_6; } jint Java_stopNativeRecording(JNIEnv *env, jobject obj) { if(recorder!=0) { LOGD("stopping native recorder"); recorder->stop(); if(recorderJava!=0) env->DeleteGlobalRef(recorderJava); } else { LOGD("recording was not started"); } return 0; } jint Java_startNativeRecording(JNIEnv *env, jobject obj, jobject jCamera, jobject jSurface) { LOGD("starting native recorder"); GlobalResource* gr = GlobalResource::getInstance(); recorderJava = env->NewGlobalRef(obj); jclass cls = env->GetObjectClass(obj); audioCallBackID = env->GetMethodID(cls,"onAudioData", "([B)V"); videoCallBackID = env->GetMethodID(cls,"onVideoData", "([B)V"); sp<Camera> cmr=get_native_camera(env,jCamera, NULL); jclass surfaceClass = env->FindClass("android/view/Surface"); jfieldID surfaceField = env->GetFieldID(surfaceClass, "mNativeSurface", "I"); Surface* const p = (Surface*)(env->GetIntField(jSurface, surfaceField)); sp<Surface> surface=sp<Surface>(p); recorder = new Recorder(); recorder->start(cmr,surface); return 0; } jobject Java_getCodecInfo(JNIEnv *env, jobject obj, jobject jCamera, jobject jSurface) { LOGD("starting native recorder"); GlobalResource* gr = GlobalResource::getInstance(); recorderJava = env->NewGlobalRef(obj); jclass cls = env->GetObjectClass(obj); audioCallBackID = env->GetMethodID(cls,"onAudioData", "([B)V"); videoCallBackID = env->GetMethodID(cls,"onVideoData", "([B)V"); sp<Camera> cmr=get_native_camera(env,jCamera, NULL); jclass surfaceClass = env->FindClass("android/view/Surface"); jfieldID surfaceField = env->GetFieldID(surfaceClass, "mNativeSurface", "I"); Surface* const p = (Surface*)(env->GetIntField(jSurface, surfaceField)); sp<Surface> surface=sp<Surface>(p); recorder = new Recorder(); recorder->storeCodecInfo(cmr,surface); /*******************************************returning**************************************/ jclass CodecInfoClass = env->FindClass("CodecInfo"); jmethodID constructor = env->GetMethodID(CodecInfoClass, "<init>", "()V"); // no parameters jobject codecInfo = env->NewObject(CodecInfoClass, constructor); //get field ids LOGD("here"); jfieldID spsFieldID = env->GetFieldID(CodecInfoClass, "VIDEO_SPS", "[B"); jfieldID ppsFieldID = env->GetFieldID(CodecInfoClass, "VIDEO_PPS", "[B"); jfieldID audioProfileFieldID = env->GetFieldID(CodecInfoClass, "AUDIO_PROFILE", "I"); jfieldID audioSamplingRateFieldID = env->GetFieldID(CodecInfoClass, "AUDIO_ACTUAL_SAMPLING_RATE", "I"); jfieldID audioChannelID = env->GetFieldID(CodecInfoClass, "AUDIO_CHANNEL", "I"); LOGD("here"); //sps android::List<AVCParamSet>::iterator itS = gr->mSeqParamSets.begin(); if(itS != gr->mSeqParamSets.end()) { int seqParamSetLength = itS->mLength; jbyteArray vsps = env->NewByteArray(seqParamSetLength);; env->SetByteArrayRegion(vsps, 0, seqParamSetLength, (jbyte*)itS->mData); env->SetObjectField (codecInfo, spsFieldID, vsps); } LOGD("sps done"); //pps android::List<AVCParamSet>::iterator itP = gr->mPicParamSets.begin(); if(itP != gr->mPicParamSets.end()) { int picParamSetLength = itP->mLength; jbyteArray vpps = env->NewByteArray(picParamSetLength); env->SetByteArrayRegion(vpps, 0, picParamSetLength, (jbyte*)itP->mData); env->SetObjectField (codecInfo, ppsFieldID, vpps); } LOGD("pps done"); //audioProfile env->SetIntField(codecInfo, audioProfileFieldID, gr->mProfile); //audioSamplingRate env->SetIntField(codecInfo, audioSamplingRateFieldID, gr->mActualSampleingRate); //audioChannel env->SetIntField(codecInfo, audioChannelID, gr->mChannel); return codecInfo; } jint Java_cameraPreviewTest(JNIEnv *env, jobject obj, jobject jSurface) { return 0; } } //extern c // these functions are called from c++ JNIEnv* attachCurrentThreadtoJVM() { JavaVM *jvm = javaVM; JNIEnv *env=NULL; jvm->GetEnv((void **)&env, JNI_VERSION_1_6); jvm->AttachCurrentThread(&env, NULL); return env; } void detachCurrentThreadtoJVM() { JavaVM *jvm = javaVM; jvm->DetachCurrentThread(); } void sendDataToJava(JNIEnv* env,Packet* pk, MEDIATYPE dataType) { jbyteArray jbArray = env->NewByteArray(pk->length); env->SetByteArrayRegion(jbArray, 0, pk->length, (jbyte*)pk->data); if(dataType == AUDIO) env->CallVoidMethod(recorderJava, audioCallBackID, jbArray); else env->CallVoidMethod(recorderJava, videoCallBackID, jbArray); delete pk->data; delete pk; env->DeleteLocalRef(jbArray); }