eclipse下Jni开发步骤详细总结

前提:已经搭好ndk环境。

步骤:

1.在java中定义本地(native)方法

2.在工程目录下新建一个jni文件夹(用来存放c/c++,android.mk,Application.mk等文件)

3.在jni文件夹中新建一个c文件,并在c中实现步骤1中定义的方法

4.在jni文件夹中新建一个Android.mk和Application.mk文件,并配置该文件的内容

5.把C文件编译成库文件

6.在java中加载库文件,调用步骤1中定义的本地(native)方法

具体实现过程:

1.在java中定义本地(native)方法

public class MainActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	//定义本地方法,在c/c++下实现
	public native String stringFromC();
}

2.在工程目录下新建一个jni文件夹(用来存放c/c++,android.mk,Application.mk等文件)

右击项目-->New-->Folder,输入要新建的文件夹名称(Folder name):jni  --->. Finish 后的目录结构如下:

3.在jni文件夹中新建一个c文件,并在c中实现步骤1中定义的方法

击上一步中新建的文件夹:jni -->New-->File,输入要新建的文件名(File name)hello.c --->.Finish ,如图(Android.mk和Application.mk文件在步骤4中建立):

(1)在hello.c文件中编写方法:

#include <jni.h>
#include <string.h>

jstring Java_com_example_testjni2_MainActivity_stringFromC(JNIEnv* env,
		jobject thiz) {
	char* cstr = "Hello From CCCC!";
	//把字符数组转为java的字符串,该方法在jni.h中定义


	//jstring     (*NewStringUTF)(JNIEnv*, const char*);
	return (*env)->NewStringUTF(env, cstr);
}
该方法主要做了一件事:定义一个字符数组指针,把字符数组转化为java的字符串返回。其中,jstring Java_com_example_testjni2_MainActivity_stringFromC(JNIEnv* env, jobject thiz) ,jstring是返回类型,表示java的string类型,Java_com_example_testjni2_MainActivity_stringFromC是实现步骤1中定义的stringFromC()方法,在这里的命名规则是:Java_包名_类名_方法名(JNIEnv* env,jobject thiz),JNIEnv是一个以线程相关的代表JNI环境的结构体,通过JNIEnv提供的JNI系统函数可以完成对java调用和操作object对象。JNIEnv在jni.h中是这样定义的

从中可以看出jni.h头文件中对于***.c  &  ***.cpp采用不同的定义

Java调用C和C++函数时的JNI使用区别:
在C的定义中,env是一个两级指针,而在C++的定义中,env是个一级指针,而且须将env作为第一个参数传给jni函数
对于***.c:
1.jclass test_class = (*env)->GetObjectClass(env, obj);
2.jfieldID id_num = (*env)->GetFieldID(env, test_class, "num", "I");

对于 ***.cpp:
1.jclass test_class = env->GetObjectClass(obj); 
2.jfieldID id_num = env->GetFieldID(test_class, "num", "I");


4.在jni文件夹中新建一个Android.mk和Application.mk文件,并配置该文件的内容

(1)重复步骤3中的新建文件方法,分别新建文件Android.mk、Application.mk(这两个Makefile文件是编译的时候使用)

(2)在Android.mk文件中编写内容:

## 指定本路径
LOCAL_PATH := $(call my-dir)
## 清除之前定义的变量
include $(CLEAR_VARS)
## 指定编译的模块和源文件
## 要生成的动态库名
LOCAL_MODULE    := hello
##  
LOCAL_SRC_FILES := hello.c

## 打印logcat要指定的参数
LOCAL_LDLIBS :=-llog
## 生成链接库
include $(BUILD_SHARED_LIBRARY)

(3)在Application.mk中编写如下内容:

##根据需要生成的目标设备来定

APP_ABI :=all

For example, to support hardware FPU instructions on ARMv7 based devices, use:

          APP_ABI := armeabi-v7a
Or to support ARMv8 AArch64 instruction set, use:

          APP_ABI := arm64-v8a
Or to support the IA-32 instruction set, use:

          APP_ABI := x86
Or to support the Intel64 instruction set (r1), use:

          APP_ABI := x86_64
Or to support the MIPS32 instruction set, use:

          APP_ABI := mips
Or to support the MIPS64 instruction set (r6), use:

          APP_ABI := mips64
Or to support all at the same time, use:

          APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a x86_64 mips64
Or even better, since NDK r7, you can also use the special value 'all' which means "all ABIs supported by this NDK release":

          APP_ABI := all

关于更多的Android.mk和Application.mk如何编写可参考NDK帮助文档,在android-ndk-r10e\docs目录下。


5.把c/c++编译成库文件

这里介绍两个方法:

方法(1):

右击项目--> Properties-->Builders-->New... -->Program

Finish确定。这样就配置好了编译动态库的环境,当jni目录的内容有变并保存时系统就会自动编译生成相应的库文件:

这里生成的动态库文件和Android.mk指定生成的库文件名不同,Android.mk指定生成的库文件名要“去头插尾”,即前面去掉lib,后面去掉.so


方法(2):

在项目路径下,按住Shift+在空白处右击-->在此处打开命令窗口

输入:ndk-build(前提是配置了NDK的环境变量,把ndk-build.cmd的路径加入到了系统变量path中)

eclipse中刷新就可以看到生成在lib下的库文件:


6.在java中加载库文件,调用步骤1中定义的本地(native)方法

最后一步是调用库文件:

public class MainActivity extends Activity {
	//加载动态库
	static{
		System.loadLibrary("hello");
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void onClickBtn(View view) {
<span style="white-space:pre">		</span>//弹出吐司,弹出<span style="font-family: Arial, Helvetica, sans-serif;">stringFromC()方法返回的字符串</span>
		Toast.makeText(this, stringFromC(), Toast.LENGTH_LONG).show();
	}
	//定义本地方法,在c/c++下实现
	public native String stringFromC();
}

效果图:



如果要在C中打印日志则以上的基础上:

1.在Android.mk文件中加:LOCAL_LDLIBS :=-llog

2.在C文件中引入头文件android/log.h,再调用打印日志的方法(在android/log.h头文件中定义有)

#include <android/log.h>

#define TAG "hello"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)

jstring Java_com_example_testjni2_MainActivity_stringFromC(JNIEnv* env,
		jobject thiz) {
	LOGD("heloooooooooooooo!");
	
	char* cstr = "Hello From CCCC!!!";
	//把字符数组转为java的字符串,该方法在jni.h中定义
	//jstring     (*NewStringUTF)(JNIEnv*, const char*);
	return (*env)->NewStringUTF(env, cstr);
}

log.h:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值