在ndk开发中,在c中调用java代码其实是通过反射技术来实现的。
代码的下载链接为:http://download.csdn.net/detail/caihongshijie6/6649995
1、main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="c代码呼叫java的空方法" android:onClick="click1" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="c代码呼叫java的两个int参数的方法" android:onClick="click2" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="c代码呼叫java的string参数方法" android:onClick="click3" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="c代码呼叫java的静态string参数方法" android:onClick="click4" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="在mainactivity里面调用空方法" android:onClick="click5" /> </LinearLayout>
2、DataProvider
package com.njupt.ndk_callback; public class DataProvider { //C调用java空方法 public void helloFromJava(){ System.out.println("hello from java"); } //C调用java中的带两个int参数的方法 public int Add(int x,int y){ int result = x+y; System.out.println("java result: " + result); return result; } //C调用java中参数为string的方法 public void printString(String s){ System.out.println("java " + s); } public static void printStaticStr(String s){ System.out.println("java static " + s); } //让c代码调用对应的java代码 public native void callmethod1(); public native void callmethod2(); public native void callmethod3(); //调用一个静态的c代码 public native void callmethod4(); }
3、MainActivity
package com.njupt.ndk_callback; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { static{ System.loadLibrary("Hello"); } private DataProvider dp; //用语言是native方法和所调用的java代码不在同一个类中...它所调用的是DataProvider中的一个printString()方法.. public native void call_dp_method1(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); dp = new DataProvider(); } public void click1(View v){ dp.callmethod1(); } public void click2(View v){ dp.callmethod2(); } public void click3(View v){ dp.callmethod3(); } public void click4(View v){ dp.callmethod4(); } public void click5(View v){ call_dp_method1(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
4、Hello.c
#include <stdio.h> #include <jni.h> #include "com_njupt_ndk_callback_DataProvider.h" #include "com_njupt_ndk_callback_MainActivity.h" #include <android/log.h>//include D:\android-ndk-r7b\platforms\android-8\arch-arm\usr\include\android下的log.h这个目录 #define LOG_TAG "System.out" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod1 (JNIEnv * env, jobject obj){ //在c代码里面调用java代码里面的方法 // java 反射 //1 . 找到java代码的 class文件 // jclass (*FindClass)(JNIEnv*, const char*); jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider"); if(dpclazz == 0){ LOGI("find class error");return ; } LOGI("find class ..."); //2 寻找class里面的方法 // jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*) jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V"); if(method1 == 0){ LOGI("find method1 error..");return ; } LOGI("find method1 ..."); //3 .调用这个方法 // void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); (*env)->CallVoidMethod(env,obj,method1); } JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod2 (JNIEnv * env , jobject obj){ jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider"); if(dpclazz == 0){ LOGI("find class error");return ; } LOGI("find class ..."); jmethodID method2 = (*env)->GetMethodID(env,dpclazz,"Add","(II)I"); if(method2 == 0){ LOGI("find method2 error..");return ; } LOGI("find method2 ..."); // 3 调用这个方法 // jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); int result = (*env)->CallIntMethod(env,obj,method2,3,5); LOGI("c code Result = %d", result); } JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod3 (JNIEnv * env, jobject obj){ jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider"); if(dpclazz == 0){ LOGI("find class error");return ; } LOGI("find class ..."); jmethodID method3 = (*env)->GetMethodID(env,dpclazz,"printString","(Ljava/lang/String;)V"); if(method3 == 0){ LOGI("find method3 error..");return ; } LOGI("find method3 ..."); (*env)->CallVoidMethod(env,obj,method3,(*env)->NewStringUTF(env,"hello in c")); } JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod4 (JNIEnv * env, jobject obj){ jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider"); if(dpclazz == 0){ LOGI("find class error");return ; } LOGI("find class ..."); //2 寻找class里面的方法 // jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); // 注意 :如果要寻找的方法是静态的方法 那就不能直接去获取methodid //jmethodID method4 = (*env)->GetMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V"); // jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*); jmethodID method4 = (*env)->GetStaticMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V"); if(method4 == 0){ LOGI("find method4 error..");return ; } LOGI("find method4 ..."); //3.调用一个静态的java方法 // void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); (*env)->CallStaticVoidMethod(env,dpclazz,method4,(*env)->NewStringUTF(env,"static haha in c")); } JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_MainActivity_call_1dp_1method1 (JNIEnv * env, jobject obj) { jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider"); if(dpclazz == 0) { LOGI("find class error"); return; } LOGI("find class ..."); jmethodID method5 = (*env)->GetStaticMethodID(env,dpclazz,"printString","(Ljava/lang/String;)V"); if(method5 == 0) { LOGI("find method5 error.."); return; } LOGI("find method5 ..."); //3 .调用这个方法(用于解决native方法和所调用的java代码不在同一个类中的情况..) // void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); // jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...); // jobject (*AllocObject)(JNIEnv*, jclass); jobject dpobject = (*env)->AllocObject(env,dpclazz); (*env)->CallStaticVoidMethod(env,dpobject,method5,(*env)->NewStringUTF(env,"not int a class ,static hello jni")); }
5、Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := Hello LOCAL_SRC_FILES := Hello.c LOCAL_LDLIBS += -llog include $(BUILD_SHARED_LIBRARY)
1、javah命令
用于生成.h文件。
使用场景:cmd下进入到src目录后 javah 包名+类名
2、javap命令
用于生成某一个类中的所有方法的方法签名
使用场景:cmd下进入到bin/classes目录后javap 包名+类名
3、ndk-build命令
用于生成.so文件
使用场景:在cygwin下进入到工程目录后,直接输入ndk-build