Android JNI - hqzhang/cloudtestbed GitHub Wiki

  1. declare native function that defined in CPP layer
public class Hellojnicpp extends Activity {
	
	private native void native_wiper_init();

      private static native void native_wiper_class_init();

      @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           
            setContentView(R.layout.main);
            Log.d(tag, "onCreate()*****1");
           
            Toast.makeText(getApplicationContext(),"&&&&&&&&&"+ 
            MainHelloService.string,
      			  Toast.LENGTH_LONG).show();
            //Intent myint= new Intent(this, );
      }
      /** A native method that is implemented by the
      * ‘hello-jni’ native library, which is packaged
      * with this application.
      */
      public native String stringFromJNI();
      /** Load the native library where the native method
      * is stored.
      */
      static {
            System.loadLibrary("hello-jni");
            native_wiper_class_init();
      }
      
      /*callback function*/
      public void callback(String msg)
      {  
    	  Toast.makeText(getApplicationContext(),"HQ Java callback:"+msg, 
    			  Toast.LENGTH_LONG).show(); 
      }
      /*callforward function*/

      public void CallJNI(View view)
      {   
    	  String hello = stringFromJNI();
    	  Toast.makeText(getApplicationContext(),"get from C:"+ hello, 
    			  Toast.LENGTH_LONG).show();
    	  //Intent intent = new Intent(this,android.basic.lesson14.MusicService.class);
    	  //bindService(intent,conn,Context.BIND_AUTO_CREATE);
      }
      
}
  1. register native table and call next layer interface
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <android/log.h>
#include "ulp.h"
#include <dlfcn.h>
#include <stdlib.h>

static jobject jWiper = NULL;
static jmethodID midCallBackStr;

int main_init(void);
int call_function();
//create object wiper
 static void instanceInit(JNIEnv *env, jobject obj) {
     if (NULL == jWiper) {
         jWiper = env->NewGlobalRef(obj);
     }
 }
 static void classInit(JNIEnv* env, jclass clazz) {
	 midCallBackStr = (env)->GetMethodID( clazz,
	 										"callback", "(Ljava/lang/String;)V");
	 main_init();
 }
 static jstring stringFromJNI (JNIEnv *env, jobject Obj) //called by jv
 {
	//jclass thisClass = (env)->GetObjectClass( Obj);
	//jmethodID midCallBackStr = (env)->GetMethodID( thisClass,
	//								"callback", "(Ljava/lang/String;)V");
	//if (NULL == midCallBackStr) return;
	__android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s","c++ callback**");
	printf("In C++, call back Java's called(String)\n");
	fflush(stdout);
	call_function();  //call second layer cpp

 }
 static jstring callback(JNIEnv *env, jobject Obj){       //callback
	 jstring message = (env)->NewStringUTF( "Hello from C++");
	 	(env)->CallVoidMethod( Obj, midCallBackStr, message);
	 	return env->NewStringUTF("Hello from C++ over JNI!******");
 }

//name mapping table
static JNINativeMethod method_table[] = {//6
		{"native_wiper_class_init", "()V", (void *)classInit},
		{"native_wiper_init", "()V", (void *)instanceInit},
   		{"stringFromJNI", "()Ljava/lang/String;", (void*)stringFromJNI}
};

//using name mapping table
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {
	JNIEnv* env;
	if ( vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6 )!= JNI_OK   ){//8
		return -1;
	}
	else {
		jclass clazz = env->FindClass("com/example/Hellojnicpp");
	    if(clazz){
	    	env->RegisterNatives(clazz, method_table, sizeof(method_table)/sizeof(method_table[0]));
	        env->DeleteLocalRef(clazz);
	        return JNI_VERSION_1_6;
	    }else return -1;
	}
   return JNI_VERSION_1_6;
 }

/** Another method using interface  */
static void location_callback();

UlpCallbacks sUlpCallbacks = {
    sizeof(UlpCallbacks),
    location_callback
};

typedef void  (*simple_forward)(void);
//typedef const ulpInterface* (get_ulp_interface) (void);

static void location_callback(){
	__android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s","enter  locationcallback in main###############\n");

}
const ulpInterface* loc_eng_ulpInf = NULL;
//init function for loading next module.
int main_init(void) {
    const char *error;
    void *module;
    __android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s", "enter main_lib\n");
    /* Load dynamically loaded library */
    module = dlopen("libhello.so", RTLD_LAZY);
    if (!module) {
    	__android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s",
    			"Couldn't open libhello.so:\n");
        exit(1);
    }
    /* call init interface *///
    __android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s", "enter main_lib:dslsym\n");
    get_ulp_interface* get_ulp_inf;
    const ulpInterface* loc_eng_ulpInf = NULL;

    dlerror();    /* Clear any existing error */
    __android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s", "enter main_lib:dslsym1\n");
    get_ulp_inf = (get_ulp_interface*) dlsym(module , "ulp_get_interface");
    if ((error = dlerror()) != NULL)  {
    	__android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cppfir","%s", error);
    	__android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cppsec","%s", dlerror());
        return 0;
     }
    __android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s", "enter main_lib:dslsym3\n");
    __android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s", "enter main_lib:->init\n");
    // Initialize the ULP interface
    loc_eng_ulpInf = get_ulp_inf(); //for interface design
    loc_eng_ulpInf->init(&sUlpCallbacks);
}
// forward function
int call_function(){

    if(!loc_eng_ulpInf)__android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s", "ERROR main_lib:forward\n");
    /* use pointer to call*/
    else loc_eng_ulpInf->forw();
   __android_log_print(ANDROID_LOG_DEBUG,"hello-jni.cpp","%s", "enter main_lib:finish\n");
   /* All done, close things cleanly */
    //dlclose(module);
    return 0;
}

3 define interface struct and getInterface function in first layer

#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include "ulp.h"

extern "C" {
int ulp_init(UlpCallbacks *cb);

void forward ();
static ulpInterface ulpInf =
{
   sizeof(ulpInterface),
   ulp_init,
   forward
};

UlpCallbacks *globalcb;

ulpInterface* ulp_get_interface () //call this by upper cpp
{
	__android_log_print(ANDROID_LOG_DEBUG,"hello-  jni1.cpp","%s","enter ulp_get_interface ().\n");
   return &ulpInf;
}

int ulp_init(UlpCallbacks *cb){   //init by upper cpp

	__android_log_print(ANDROID_LOG_DEBUG,"hello-jni1.cpp","%s","enter ulp_init function to set callback\n");
    globalcb = cb;
    return 0;
}
void forward () {                //forward to callback to upper cpp
	__android_log_print(ANDROID_LOG_DEBUG,"hello-jni1.cpp","%s","enter  forward () and call callback from main **************\n");
    globalcb->location_cb();
}
}

4 just header file

#include <stdio.h>
//#ifdef __cplusplus
//extern "C" {
//#endif
typedef void (* ulp_callback)(void);

/** ULP callback structure. */
typedef struct {
    size_t      size;
    ulp_callback location_cb;
} UlpCallbacks;

typedef struct {
    unsigned int   size;
    int   (*init)(UlpCallbacks *cb);
    void  (*forw)(void);
}ulpInterface;

typedef const ulpInterface* (get_ulp_interface) (void);
#ifdef __cplusplus
//}
#endif}
⚠️ **GitHub.com Fallback** ⚠️