最近打算重构项目中的部分代码,将部分耗时或者敏感的代码放到native中实现。说来惭愧,本人今年3月份才开始接触android开发,虽然一早就知道android中可使用c/c++代码,但一直没有尝试。因而趁着此次机会研究一下android中的ndk开发,花了一个下午加一个上午,经历了种种悲剧后终于跑通了第一个demo。在整个过程当中参考了无数文章,也走了不少弯路,特此写下本文章,但愿帮助刚刚接触JNI的童鞋们更快的上手。 html
上面说的貌似是废话,如今开始进入正题。个人开发环境是windows+eclipse,所以在开始真正写代码前,还须要在windows上搭建相关环境才能编译.so文件。这里我推荐看下 http://www.cnblogs.com/jdksummer/articles/2166057.html 这篇配置文章写的很详细。 java
假设你如今已经搭建好了开发环境,那么开始吧!(听着音乐,开始咱们的学习吧!!)
android
1.打开eclipse新建一个android的工程,就叫"MyFirstJNI"吧。创建后添加一个class文件做为jni的接口,我是这样添加的
c++
在该类中添加以下代码:都是一些很简单的函数^^ windows
package com.example.myjni; public class JNI { public native void write(); public native String sayHello(); public native int plus(int a, int b); }
这个就是native code在java中的接口了。添加完成后,build project。第一步的准备工做就此完成,很容易吧。 app
2.打开cmd并定位到刚刚新建的"MyFirstJNI"工程目录下的bin/classes目录,执行”javah -classpath . -jni com.example.myjni.JNI“,没有意外的话,bin/classes目录下应该会产生一个com_example_myjni_JNI.h文件。这个就是native code须要实现的函数了。 eclipse
3.如今咱们把刚刚获得的.h文件拷贝出,为它新建一个工程,我是手工创建的。创建D:\MyfirstJNISO目录,并创建子目录jni(必须叫这个,不然后面会不能编译哦),并将.h文件拷贝到该目录下,并新建一个com_example_myjni_JNI.c文件实现相关函数,代码以下: 函数
#include <string.h> #include "com_example_myjni_JNI.h" JNIEXPORT void JNICALL Java_com_example_myjni_JNI_write (JNIEnv *env, jobject thiz) { } /* * Class: com_example_myjni_JNI * Method: sayHello * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_myjni_JNI_sayHello (JNIEnv *env, jobject thiz) { return (*env)->NewStringUTF(env, "Hello from JNI !"); } /* * Class: com_example_myjni_JNI * Method: plus * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_example_myjni_JNI_plus (JNIEnv *env, jobject thiz, jint a, jint b) { return a+b; }
接着还须要同一个目录下添加一个Android.mk文件,编译时候使用,具体内容以下: 学习
LOCAL_PATH := $(call my-dir) 测试
include $(CLEAR_VARS)
LOCAL_MODULE := first_jni (最终so文件名是libfirst_jni.so)
LOCAL_SRC_FILES := com_example_myjni_JNI.c (代码)
include $(BUILD_SHARED_LIBRARY)
是否是很麻烦,不过咱们已经离成功愈来愈近了。
3.如今整理一下,咱们到目前为止的工做,新建了一个android工程以及一个C的工程(暂且叫工程吧),如今开始最重要的一步,编译c代码生成.so文件让android工程中的调用。你如今应该已经配置好了cygwin了吧,打开吧,定位到C工程目录,好比D:\myfirstJNISO的话就执行”cd /cygdrive/D/myfirstJNISO“,而后执行”$NDK/ndk-build
“(其中$NDK和你配置的cygwin有关)。
这样编译的工做就完成了,若是你前面没有犯任何错的话。赶忙打开C工程目录吧应该是这样的吧
黄色标记的目录就是咱们须要的东西哦,里面是一个”armeabi“文件夹,里面是编译获得的.so文件。
final.将上面的armeabi文件夹整个拷贝到咱们一开始创建的MyfirstJNI工程的libs目录下,全部工做都已就绪,你的工程应该是这样的:
(ps:请忽略android-support-v4.jar这个和本次的内容不要紧)
如今就来编写java代码调用吧,在MainActivity中添加必须的代码:
static { System.loadLibrary("first_jni"); }
这个是让系统加载so库,注意编译生成的库的名字是带前缀lib的,代码中请忽略不然会找不到相应的so文件。
调用就很简单了:
jni = new JNI(); jni.sayHello(); jni.plus(1,2);
最后添加一些简单的button测试一下吧,我作的比较简陋了:
至此,咱们的第一个ndk的demo就跑起来了。