基于 Android NDK 的学习之旅----- C调用Java
2011-08-31 16:22
435 查看
许多成熟的C引擎要移植到Android平台上使用,一般都会提供一些接口,让Androidsdk和jdk实现。
下文将会介绍C如何通过JNI层调用Java的静态和非静态方法。
a)该类提供了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、关键代码说明
C中定义映射的类、方法、对象
jclassTestProvider;
jobjectmTestProvider;
jmethodIDgetTime;
jmethodIDsayHello;
C中映射类
TestProvider=(*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");
C中新建对象
jmethodIDconstruction_id=(*jniEnv)->GetMethodID(jniEnv,TestProvider,"<init>","()V");
TestProvidermTestProvider=(*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的两个方法
4、Android.mk文件关键代码
老样子,不说了,你懂的。如果不懂,嘎嘎,那就请点击Android.mk文件简介
5、JNI文件夹下文件
Provider.h
Provider.c
CToJava.c
C成功调用了Java中的getTime方法,通过C方法打印出上层调用得到的时间,并且上层成功吐司出调用信息出来。
2、点击“C调用java非静态方法”按钮
C成功调用了sayHello方法,并成功接收到C传递的参数,和吐司出相对应的信息
getTime=(*jniEnv)->GetStaticMethodID(jniEnv,TestProvider,"getTime","()Ljava/lang/String;");
故事情节还没发展这么快,下一章才会专门介绍下这个签名的使用
b)映射方法的时候需要区别静态和非静态GetStaticMethodID,GetMethodID
c)调用的时候也需要区分CallStaticObjectMethod,CallVoidMethod而且还需要区分返回值类型
有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,点击下载源码C调用Java例子
本文出自duicky博客,转载请注明出处/article/5095940.html
下文将会介绍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中映射类
TestProvider=(*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");
C中新建对象
jmethodIDconstruction_id=(*jniEnv)->GetMethodID(jniEnv,TestProvider,"<init>","()V");
TestProvidermTestProvider=(*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); |
} |
} |
4、Android.mk文件关键代码
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(); |
Provider.c
#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); |
} |
CToJava.c
#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而且还需要区分返回值类型
有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,点击下载源码
本文出自
相关文章推荐
- 基于 Android NDK 的学习之旅----- C调用Java(附源码)
- 基于 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 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用 C(附源码)
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 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