我最近也在忙于安卓ndk的项目,安卓系统通过C调用一些设备的驱动,要在windows平台开发环境搭建起来,所以要通过java的JNI技术来实现,我把我自己摸索的步骤分享给大家!如果有不准确之处还请大家指正!
1.第一步,先把安卓平台搭建好,然后下载ndk包,我下载的是android-ndk-r9d,然后解压,其中,在./android-ndk-r9d/samples文件夹下有个hello-jni,这就是官方提供的一个项目样例。
2.第二步,创建Android项目,先创建一个java文件,在java文件中写库加载块和native方法声明(不要写在activity里,单独写在一个java文件里),这个具体可以在样例中可以看到(我在java文件里就写这两个,然后用单态模式返回一个对象用来调用c方法)。
3.第三步,生成该java文件的class文件,最简单的方法就是把项目先运行一遍,这样在bin/classes里就会有该java文件的class了,接着,将cmd里切换到该项目的根目录,执行javah -classpath bin/classes -d jni com.ndk.HelloJni,下面是一些解释
-classpath bin/classes:表示类class文件的路径,上面运行一遍项目就是生成它
-d jni: 表示生成的.h头文件存放的目录
com.ndk.HelloJni则是完整类名 ,即 我的包名是 com.ndk, 而HelloJni 为刚才编写的java文件名。
这一步成功需要在之前编译工程文件时候有在 bin/classes/com/ndk/hellojni/ 目录下生成了 HelloJni.class的基础之上。
4.之后会在jni下生成文件 com_ndk_HelloJni.h,生成的这个文件就是你编写C文件的参照,
比如,如果HelloJni.h文件生成如下:
#include <jni.h>
/* Header for class com_ndk_HelloJni */
#ifndef _Included_com_ndk_HelloJni
#define _Included_com_ndk_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_ndk_HelloJni
* Method: StringFromJni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ndk_HelloJni_StringFromJni
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
那么,你的HelloJni.c文件应该这么写
<span style="font-size:18px;">#include <string.h>
#include <jni.h>
JNIEXPORT jstring JNICALL Java_com_ndk_HelloJni_StringFromJni
(JNIEnv * env, jobject this)
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}</span>
5.在Jni目录下创建一个Android.mk的文件,实际上这就是创建了编译.C文件的规则,
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
接下来是对文件中内容的解释:编译的目标对象,LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。
注意:编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'hello-jni'的共享库模块,将会生成'libhello-jni.so'文件。
LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。
注意,默认的C++源码文件的扩展名是’.cpp’. 指定一个不同的扩展名也是可能的,只要定义LOCAL_DEFAULT_CPP_EXTENSION变量,不要忘记开始的小圆点(也就是’.cxx’,而不是’cxx’)
(2)打开Eclipse,新建一个Android工程,在工程根目录下新建jni文件夹,该文件夹就用来保存NDK需要编译的文件代码等。
(3)新建并配置一个Builder:
(a)Project->Properties->Builders->New,新建一个Builder。
(b)在弹出的【Choose configuration type】对话框,选择【Program】,点击【OK】:
(c)在弹出的【Edit Configuration】对话框中,配置选项卡【Main】。
在“Name“中输入新builders的名称(我取名为Ndk_Builder)。
在“Location”中输入nkd-build.cmd的路径。
(我的是D:\AndroidDev\android-ndk-r9d\ndk-build.cmd,根据各自的ndk路径设置,也可以点击“Browser File System…”来选取这个路径)。
在“Working Diretcoty”中输入${workspace_loc:/TestNdk}(也可以点击“Browse Workspace”来选取TestNdk目录)。
(d)【Edit Configuration】对话框中,配置选项卡【Refresh】。
勾选“Refresh resources upon completion”,
勾选“The entire workspace”,
勾选“Recuresively include sub-folders”。
(e)【Edit Configuration】对话框中,配置选项卡【Build options】。
勾选“After a “Clean””,
勾选“During manual builds”,
勾选“During auto builds”,
勾选“Specify working set of relevant resources”。
点击“Specify Resources…”
勾选TestNdk工程的“jni“目录,点击”finish“。
点击“OK“,完成配置。
OK,到这里Eclipse就能够自动调用NDK编译jin目录下的C/C++代码了。