基于 Android NDK 的学习之旅-----Java 调用C
2013-07-15 12:22
417 查看
基于AndroidNDK的学习之旅-----C调用Java
许多成熟的C引擎要移植到Android平台上使用,一般都会提供一些接口,让Androidsdk和jdk实现。下文将会介绍C如何通过JNI层调用Java的静态和非静态方法。
1、主要流程
1、新建一个测试类TestProvider.javaa)该类提供了2个方法
b)一个静态的方法,一个非静态的方法
2、JNI中新建Provider.c
a)该文件中需要把Java中的类TestProvider映射到C中
b)把TestProvider的两个方法映射到C中
c)新建TestProvider对象
d)调用两个方法
3、Android上层调用JNI层
4、JNI层调用C层
5、C层调用Java方法
2、设计实现
1、界面设计如下:老样子,很搓,不过实用,嘿嘿
代码不在这贴出了,有需要的兄弟直接到文章结束部分下载。
2、关键代码说明
C中定义映射的类、方法、对象
jclassTestProvider;
jobjectmTestProvider;
jmethodIDgetTime;
jmethodIDsayHello;
C中映射类(通过java的路径得到JAVA的类)
TestProvider=(*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");
C中新建对象(调用init的实例化类对象)
jmethodIDconstruction_id=(*jniEnv)->GetMethodID(jniEnv,TestProvider,"<init>","()V");
mTestProvider=(*jniEnv)->NewObject(jniEnv,TestProvider,construction_id);
C中映射方法(通过类名得到对应的函数映射)
静态:
getTime=(*jniEnv)->GetStaticMethodID(jniEnv,TestProvider,"getTime","()Ljava/lang/String;");
非静态:
sayHello=(*jniEnv)->GetMethodID(jniEnv,TestProvider,"sayHello","(Ljava/lang/String;)V");
C中调用Java的方法
静态:
(*jniEnv)->CallStaticObjectMethod(jniEnv,TestProvider,getTime);
非静态:
(*jniEnv)->CallVoidMethod(jniEnv,mTestProvider,sayHello,jstrMSG);
注意GetXXXMethodID和CallXXXMethod。
第一个XXX表示的是映射方法的类型,如:静态跟非静态
第二个XXX表示调用方法的返回值,如:Void,Object,等等。(调用静态方法的时候Call后面要加Static)
详细映射方法和调用方法请参考
JNI文档,这个很重要!
3、Java上层关键代码
TestProvider.Java的两个方法
package com.duicky; /** * * *@authorluxiaofeng<454162034@qq.com> * */ public class TestProvider{ public static StringgetTime(){ LogUtils.printWithSystemOut( "CallFromCJavaStaticMethod" ); LogUtils.toastMessage(MainActivity.mContext, "CallFromCJavaStaticMethod" ); return String.valueOf(System.currentTimeMillis()); } public void sayHello(Stringmsg){ LogUtils.printWithSystemOut( "CallFromCJavaNotStaticMethod:" +msg); LogUtils.toastMessage(MainActivity.mContext, "CallFromCJavaNotStaticMethod:" +msg); } } |
LOCAL_PATH:=$(callmy-dir) include$(CLEAR_VARS) LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include LOCAL_LDLIBS+=-L$(SYSROOT)/usr/lib-llog LOCAL_MODULE:=NDK_04 LOCAL_SRC_FILES:=\ CToJava.c\ Provider.c include$(BUILD_SHARED_LIBRARY) |
5、JNI文件夹下文件
Provider.h
#include<string.h> #include<jni.h> void GetTime(); void SayHello(); |
#include"Provider.h" #include<android/log.h> extern JNIEnv*jniEnv; jclassTestProvider; jobjectmTestProvider; jmethodIDgetTime; jmethodIDsayHello; int GetProviderInstance(jclassobj_class); /** *初始化类、对象、方法 */ int InitProvider(){ __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProviderBegin1" ); if (jniEnv==NULL){ return 0; } if (TestProvider==NULL){ TestProvider=(*jniEnv)->FindClass(jniEnv, "com/duicky/TestProvider" ); if (TestProvider==NULL){ return -1; } __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProviderBegin2ok" ); } if (mTestProvider==NULL){ if (GetProviderInstance(TestProvider)!=1){ (*jniEnv)->DeleteLocalRef(jniEnv,TestProvider); return -1; } __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProviderBegin3ok" ); } if (getTime==NULL){ getTime=(*jniEnv)->GetStaticMethodID(jniEnv,TestProvider, "getTime" , "()Ljava/lang/String;" ); if (getTime==NULL){ (*jniEnv)->DeleteLocalRef(jniEnv,TestProvider); (*jniEnv)->DeleteLocalRef(jniEnv,mTestProvider); return -2; } __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProviderBegin4ok" ); } if (sayHello==NULL){ sayHello=(*jniEnv)->GetMethodID(jniEnv,TestProvider, "sayHello" , "(Ljava/lang/String;)V" ); if (sayHello==NULL){ (*jniEnv)->DeleteLocalRef(jniEnv,TestProvider); (*jniEnv)->DeleteLocalRef(jniEnv,mTestProvider); (*jniEnv)->DeleteLocalRef(jniEnv,getTime); return -3; } __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProviderBegin5ok" ); } __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProviderBegin6" ); return 1; } int GetProviderInstance(jclassobj_class){ if (obj_class==NULL){ return 0; } jmethodIDconstruction_id=(*jniEnv)->GetMethodID(jniEnv,obj_class, "<init>" , "()V" ); if (construction_id==0){ return -1; } mTestProvider=(*jniEnv)->NewObject(jniEnv,obj_class, construction_id); if (mTestProvider==NULL){ return -2; } return 1; } /** *获取时间----调用Java方法 */ void GetTime(){ if (TestProvider==NULL||getTime==NULL){ int result=InitProvider(); if (result!=1){ return ; } } jstringjstr=NULL; char *cstr=NULL; __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "GetTimeBegin" ); jstr=(*jniEnv)->CallStaticObjectMethod(jniEnv,TestProvider,getTime); cstr=( char *)(*jniEnv)->GetStringUTFChars(jniEnv,jstr,0); __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "SuccessGetTimefromJava,Value=%s" ,cstr); __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "GetTimeEnd" ); (*jniEnv)->ReleaseStringUTFChars(jniEnv,jstr,cstr); (*jniEnv)->DeleteLocalRef(jniEnv,jstr); } /** *SayHello----调用Java方法 */ void SayHello(){ if (TestProvider==NULL||mTestProvider==NULL||sayHello==NULL){ int result=InitProvider(); if (result!=1){ return ; } } jstringjstrMSG=NULL; jstrMSG=(*jniEnv)->NewStringUTF(jniEnv, "Hi,I'mFromC" ); __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "SayHelloBegin" ); (*jniEnv)->CallVoidMethod(jniEnv,mTestProvider,sayHello,jstrMSG); __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "SayHelloEnd" ); (*jniEnv)->DeleteLocalRef(jniEnv,jstrMSG); } |
#include<string.h> #include<android/log.h> #include<jni.h> #include"Provider.h" JNIEnv*jniEnv; /** *Java中声明的nativegetTime方法的实现 */ void Java_com_duicky_MainActivity_getTime(JNIEnv*env,jobjectthiz) { if (jniEnv==NULL){ jniEnv=env; } GetTime(); } /** *Java中声明的nativesayHello方法的实现 */ void Java_com_duicky_MainActivity_sayHello(JNIEnv*env,jobjectthiz) { if (jniEnv==NULL){ jniEnv=env; } SayHello(); } |
3、运行效果
1、点击“C调用java静态方法”按钮C成功调用了Java中的getTime方法,通过C方法打印出上层调用得到的时间,并且上层成功吐司出调用信息出来。
2、点击“C调用java非静态方法”按钮
C成功调用了sayHello方法,并成功接收到C传递的参数,和吐司出相对应的信息
4、C调用Java注意点
a)C映射java方法时对应的签名getTime=(*jniEnv)->GetStaticMethodID(jniEnv,TestProvider,"getTime","()Ljava/lang/String;");
故事情节还没发展这么快,下一章才会专门介绍下这个签名的使用
b)映射方法的时候需要区别静态和非静态GetStaticMethodID,GetMethodID
c)调用的时候也需要区分CallStaticObjectMethod,CallVoidMethod而且还需要区分返回值类型
有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,
转载:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/15/2139934.html
点击下载源码
相关文章推荐
- 基于 Android NDK 的学习之旅-----Java 调用C(附源码)
- 基于 Android NDK 的学习之旅-----Java 调用 C(附源码)
- 基于 Android NDK 的学习之旅----- C调用Java(附源码)
- 基于 Android NDK 的学习之旅-----Java 调用C(附源码)
- 基于 Android NDK 的学习之旅----- C调用Java(附源码)
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java(附源码)
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅-----Java 调用 C(附源码)
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C