基于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、界面设计如下:

转:基于 Android NDK 的学习之旅----- C调用Java(附源码)


老样子,很搓,不过实用,嘿嘿

代码不在这贴出了,有需要的兄弟直接到文章结束部分下载。

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. 基于RTP和Android的视频传输的研究实现方法
  2. Android 中.aar文件生成方法与用法
  3. Android Studio中获取sha1证书的方法
  4. android 退出程序三种方法及两种形式
  5. 【android】五种控制Android应用的权限的方法
  6. 2011.06.07(2)——— android 调试android源码包下的package应用的
  7. Android中Intent传递对象的两种方法(Serializable,Parcelable)
  8. 转:[Android]实现静默安装APK的两种方法

随机推荐

  1. 【30篇突击 android】源码统计九
  2. Android(安卓)控件的显示隐藏上下左右移
  3. How to decompile Google Android(安卓).
  4. OpenGL ES Tutorial for Android(安卓)–
  5. Android第三十八期 - 评价标签FlowLayout
  6. android中用HTTP请求将经纬度解析为具体
  7. 优秀项目
  8. android监听短信并判断是否未读
  9. 拥抱Android(安卓)studio
  10. [置顶] android仿网易导航栏HorizontalSc