您的位置:首页 > 移动开发 > Android开发

基于 Android NDK 的学习之旅----- C调用Java

2011-08-31 16:22 435 查看
许多成熟的C引擎要移植到Android平台上使用,一般都会提供一些接口,让Androidsdk和jdk实现。

下文将会介绍C如何通过JNI层调用Java的静态和非静态方法。

1、主要流程

1、新建一个测试类TestProvider.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、设计实现

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)
  

老样子,不说了,你懂的。如果不懂,嘎嘎,那就请点击Android.mk文件简介

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而且还需要区分返回值类型

有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,点击下载源码C调用Java例子

本文出自duicky博客,转载请注明出处/article/5095940.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: