本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件。

在Eclipse中添加配置NDK,路径如下Eclipse->Window->Preferences->Android->NDK ,选择NDK的路径,然后Apply即可。

新建一个名为AndroidJNI_AccessField的Android工程,新建一个jni的文件夹,其目录下文件树列表如下:

├── jni
│   ├── accessfield
│   │   ├── accessfield_jni.c
│   │   ├── Android.mk
│   │   └── logger.h
│   ├── Android.mk
│   └── Application.mk

jni/Application.mk文件内容如下:

APP_ABI := all

jni/Android.mk,主要用来指定顺序执行所有子文件夹下面的makefile文件,内容如下:

include $(call all-subdir-makefiles)

jni/accessfield/Android.mk,主要用来指定需要编译出的动态库的名称,以及需要编译的源文件,内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE     := accessfield_jni
LOCAL_SRC_FILES := accessfield_jni.c LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)

jni/accessfield/logger.h 主要用来在JNI层打印日志,内容如下:

#include <jni.h>
#include <android/log.h> /**
* 定义log标签
*/
#define TAG "jni_logger" /**
* 定义info信息
*/
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) /**
* 定义debug信息
*/
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) /**
* 定义error信息
*/
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

jni/accessfield/objectarray_jni.c,主要用来注册绑定java函数和native函数,以及java函数在c中相应函数的具体实现, 内容如下:

#include "logger.h"

#ifndef NULL
#define NULL ((void *) 0)
#endif /**
* 获取数组的大小
*/
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) /**
* 指定要注册的类,对应的完整的java类名
*/
#define JNIREG_CLASS "com/clarck/jni/AccessField" /**
* 返回成员实例域
*/
JNIEXPORT void JNICALL native_accessField(JNIEnv *env, jobject obj) {
jfieldID fid;
jstring jstr;
const char *str; //在实力引用对象上得到类的引用
jclass cls = (*env)->GetObjectClass(env, obj);
//从类的引用,成员域的名称,和成员域描述符来得到成员域(field)ID
fid = (*env)->GetFieldID(env, cls, "mStr", "Ljava/lang/String;");
if (NULL == fid) {
return ;
} //获取传递对象引用和成员域ID获取实例域访问函数
jstr = (*env)->GetObjectField(env, obj, fid);
//获取传递对象引用的字符
str = (*env)->GetStringUTFChars(env, jstr, NULL);
if (NULL == str) {
return ;
}
LOGI("mStr = %s \n", str);
(*env)->ReleaseStringUTFChars(env, jstr, str); jstr = (*env)->NewStringUTF(env, "");
if (NULL == jstr) {
return ;
}
//替换掉获取到的实例对象的引用
(*env)->SetObjectField(env, obj, fid, jstr); //Caching at the Point of Use
/*static jfieldID fid_s = NULL;
jstring jstr;
const char *str; jclass cls = (*env)->GetObjectClass(env, obj);
if (NULL == fid_s) {
fid_s = (*env)->GetFieldID(env, cls, "mStr", "Ljava/lang/String;");
if (NULL == fid_s) {
return ;
}
}
LOGI("In C \n"); jstr = (*env)->GetObjectField(env, obj, fid_s);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
if (NULL == str) {
return ;
}
LOGI("mStr = %s \n", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
jstr = (*env)->NewStringUTF(env, "123");
if (NULL == jstr) {
return ;
}
(*env)->SetObjectField(env, obj, fid_s, jstr);*/
} /**
* 得到静态成员实例域
*/
JNIEXPORT void JNICALL native_staticAccessField(JNIEnv *env, jobject obj) {
jfieldID fid;
jint si; jclass cls = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetStaticFieldID(env, cls, "mSi", "I");
if (NULL == fid) {
return ;
} si = (*env)->GetStaticIntField(env, cls, fid);
LOGI("mSi = %d \n", si);
(*env)->SetStaticIntField(env, cls, fid, );
} /**
* Java和JNI函数绑定
*/
static JNINativeMethod method_table[] = {
{ "accessField", "()V", (void*) native_accessField },
{ "staticAccessField", "()V", (void*) native_staticAccessField },
}; /**
* 注册native方法到java中
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods) {
jclass clazz;
clazz = (*env)->FindClass(env, className);
if (clazz == NULL) {
return JNI_FALSE;
} if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < ) {
return JNI_FALSE;
} return JNI_TRUE;
} /**
* 调用注册方法
*/
int register_ndk_load(JNIEnv* env) {
return registerNativeMethods(env, JNIREG_CLASS, method_table,
NELEM(method_table));
} JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return result;
} register_ndk_load(env); //返回jni的版本
return JNI_VERSION_1_4;
}

接着在Project中右键Android Tools->Add Native Support,最后java层调用如下:

package com.clarck.jni;

public class AccessField {
public String mStr;
public static int mSi; public native void accessField();
public native void staticAccessField(); static {
System.loadLibrary("accessfield_jni");
}
}
package com.clarck.jni;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AccessField accessField = new AccessField();
accessField.mStr = "abc";
accessField.accessField();
Log.d("Test", "mStr = " + accessField.mStr); accessField.mSi = 100;
accessField.staticAccessField();
Log.d("Test", "mStr = " + accessField.mSi);
} }

执行Ctrl+B执行编译,运行工程即可。

Android NDK 学习之在C中调用Java的变量和静态变量的更多相关文章

  1. Android NDK 学习之在C中抛出异常

    本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...

  2. Android NDK学习总结

    一.android NDK编程步骤 java文件中声明native方法. android工程根目录新建jni文件夹. 调用javah命令为第一步声明的native方法生成相应的.h头文件. 通过win ...

  3. Android JNI入门第六篇——C调用Java

    本篇将介绍在JNI编程中C调用Java实现. 源码下载地址:http://download.csdn.net/detail/xyz_lmn/4868265 关键代码: java: public cla ...

  4. Oracle数据库中调用Java类开发存储过程、函数的方法

    Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日  浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...

  5. 在JS中调用JAVA变量

    在JS中调用JAVA变量可以,方法是:var JS变量名 = “<%=JAVA变量名 %>”<%中间写java代码,跟在JSP中一样%>在JAVA中 ,无法调用JS变量

  6. kettle中调用java类

    kettle中调用java类 有时须要在kettle调用java类,如:验证.查询或自己定义加密等.有时甚至连主要的数据訪问都不那么简单,如获取一个存储文件或使用一个数据库连接,某些数据源可能封装在应 ...

  7. 在scala中调用java代码

      详细代码请见https://github.com/lujinhong/scalademo 在scala中调用java代替非常非常简单,直接调用即可 (一)一个简单示例 1.创建一个java类 pa ...

  8. PySpark 的背后原理--在Driver端,通过Py4j实现在Python中调用Java的方法.pyspark.executor 端一个Executor上同时运行多少个Task,就会有多少个对应的pyspark.worker进程。

    PySpark 的背后原理 Spark主要是由Scala语言开发,为了方便和其他系统集成而不引入scala相关依赖,部分实现使用Java语言开发,例如External Shuffle Service等 ...

  9. [javase学习笔记]-8.2 成员变量与静态变量的差别

    这一节我们看一看成员变量与静态变量的差别所在. 什么是静态变量呢?我们上节用statickeyword时就提到了静态变量.也就是说用statickeyword修饰的变量就是静态变量. 我们在6.4节学 ...

随机推荐

  1. weui 导航悬浮固定

    <style> .none{display: none} #toolbar { display: flex; justify-content: center; align-items: c ...

  2. jsoup获取文章内容

    jsoup爬取文章内容 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Se ...

  3. libfacedetection环境配置

    E:\Opencv\libfacedetection_install1\include E:\Opencv\libfacedetection_install1\lib libfacedetect-x6 ...

  4. 【Mybatis】MyBatis之整合Spring(八)

    创建环境 系统:macOS Java:1.8 软件:eclipse,maven,mysql 创建步骤 本例:创建一个Maven项目(SpringMVC+Spring+Mybatis),页面上展示员工列 ...

  5. 【GStreamer开发】GStreamer播放教程05——色彩平衡

    目标 亮度,对比度,色度和饱和度都是常见的视频调节参数,也是GStreamer里面设置色彩平衡的参数.本教程将展示: 如何发现可用的色彩平衡通道 如何改变它们 介绍 <GStreamer基础教程 ...

  6. mousedown、mouseup、click事件之间的关系及执行顺序

      三个事件的触发时机 mousedown 当鼠标指针移动到元素上方,并按下鼠标按键(左.右键均可)时,会发生 mousedown 事件.与 click 事件不同,mousedown 事件仅需要按键被 ...

  7. {"aa":null} 如何能转化为 {"aa":{}}

    一个同事问的一个功能需求:{"aa":null} 如何能转化为 {"aa":{}}因为需求暂时不明确,暂时先完成这样的转换.使用的是FastJson1.2.7 ...

  8. javascript bom操作

    BOM BOM介绍 全称 Browser Object Mode 浏览器对象模式 操作浏览器的API接口.比如浏览器自动滚动 Windows对象的顶层部分是BOM的顶层(核心)对象,所有的对象都是通过 ...

  9. 解决Ubuntu14.04不能打正确拼音--无法选择第二个拼音

    这时候 我们回到桌面 按"ctrl"+"Alt"+"T",打开系统终端,在终端里面输入ibus-daemon -drx并回车 Ref: ht ...

  10. Amazon SQS 消息队列服务

    Amazon sqs是亚马逊提供的线上消息队列服务, 可以实现应用程序解耦,以及可靠性保证. sqs提供了两种消息队列, 一种是标准消息队列, 一种是先进先出队列(FIFO), 其区别是FIFO是严格 ...