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

许多成熟的C引擎要移植到Android平台上使用,一般都会提供一些接口,Android sdkjdk实现。

下文将会介绍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中定义映射的类、方法、对象

jclass TestProvider;

jobject mTestProvider;

jmethodID getTime;

jmethodID sayHello;

C中映射

TestProvider = (*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");

C中新建对象

jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, TestProvider,"<init>", "()V");

TestProvider 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);

注意GetXXXMethodIDCallXXXMethod

第一个XXX表示的是映射方法的类型,如:静态跟非静态

第二个XXX表示调用方法的返回值,如:Void,Object,等等。(调用静态方法的时候Call后面要加Static

详细映射方法调用方法请参考JNI文档,这个很重要

3、Java上层关键代码

TestProvider.Java的两个方法

packagecom.duicky;
/**
*
*
* @author luxiaofeng <454162034@qq.com>
*
*/
publicclassTestProvider {
publicstaticString getTime() {
LogUtils.printWithSystemOut("Call From C Java Static Method");
LogUtils.toastMessage(MainActivity.mContext,"Call From C Java Static Method");
returnString.valueOf(System.currentTimeMillis());
}
publicvoidsayHello(String msg) {
LogUtils.printWithSystemOut("Call From C Java Not Static Method :"+ msg);
LogUtils.toastMessage(MainActivity.mContext,"Call From C Java Not Static Method :"+ msg);
}
}

  

4、Android.mk文件关键代码

LOCAL_PATH := $(call my-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>
voidGetTime() ;
voidSayHello();

  

Provider.c

#include "Provider.h"
#include <android/log.h>
externJNIEnv* jniEnv;
jclass TestProvider;
jobject mTestProvider;
jmethodID getTime;
jmethodID sayHello;
intGetProviderInstance(jclass obj_class);
/**
* 初始化 类、对象、方法
*/
intInitProvider() {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","InitProvider Begin 1");
if(jniEnv == NULL) {
return0;
}
if(TestProvider == NULL) {
TestProvider = (*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");
if(TestProvider == NULL){
return-1;
}
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","InitProvider Begin 2 ok");
}
if(mTestProvider == NULL) {
if(GetProviderInstance(TestProvider) != 1) {
(*jniEnv)->DeleteLocalRef(jniEnv, TestProvider);
return-1;
}
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","InitProvider Begin 3 ok");
}
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","InitProvider Begin 4 ok");
}
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","InitProvider Begin 5 ok");
}
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","InitProvider Begin 6");
return1;
}
intGetProviderInstance(jclass obj_class) {
if(obj_class == NULL) {
return0;
}
jmethodID construction_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;
}
return1;
}
/**
* 获取时间 ---- 调用 Java 方法
*/
voidGetTime() {
if(TestProvider == NULL || getTime == NULL) {
intresult = InitProvider();
if(result != 1) {
return;
}
}
jstring jstr = NULL;

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. Android单元测试
  5. Android(安卓)Uevent 分析,从kernel到framework
  6. Android架构组件(三)——ViewModel
  7. 探究Android异步消息的处理之Handler详解
  8. Android入门进阶教程(12)-SystemService详解
  9. android Content Provider详解

随机推荐

  1. Android--Socket通信
  2. Android(安卓)GPS学习笔记—GpsLP初始化
  3. Android--取得控件在手机屏幕上的位置
  4. android push
  5. android音频处理
  6. Android中AutoCompleteTextView的特殊使
  7. Android(安卓)修改U盘名称
  8. Android与蓝牙耳机建立连接的分析
  9. Android(安卓)点击back键两次退出程序
  10. 一、 Android完全退出应用程序