一、环境的搭建:
1、需要的工具:
A、cygwin (在windows下使用LINUX系统) http://www.cygwin.com
B、android-ndk-1.6_r1-windows (主要是起到将C或C++编译成动态库的作用) http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip
C、eclipse(建立ANDROID工程的软件,使用ANDROID的童鞋应该早就安装了,在这不复述)。
2、安装cygwin
A、从上面指定的网址下载cygwin 软件,点击cygwin.exe进行安装。
B、安装软件运行起来后,通常采用默认情况,一直点击下一步就好。
上面这个图有三个选项,一般默认就好,第二个是说,只下载不安装,下载后需要手动安装;第三个是说,在下载到本地后再进行安装;
这个是指该软件的安装路径,一般不需要更换。
这个路径是指下载的内容保存在什么位置,这个自己可以指定。
让其自动下载,再点击“下一步”。
这个是需要选择下载内容的地址,之前在这选择N次,后面安装都失败了,如果想多选择几个下载地址,可以按住“ctrl”进行选择,建议不要多选,多选后会创建多个文件夹
如果失败就重头开始,选择新的地址,反复安装,才能成功。
让其自动下载,再点击“下一步”。
这一步是要选择需要安装的内容,一般像GNU gcc g++ 等常用工具需要安装,当然也可以全部安装,但全部安装的时间会很长。
最后下载完成后会自动安装,点击完成就好。
3、验证cygwin安装成功。
运行安装好的cygwin软件,进去输入gcc -v make -v g++ -v 等命令,看是否能得到其版本信息,如不能得到,说明有些工具没有安装,需要重新安装
未安装的工具(其方法跟前面一样,只是选择你未安装的工具即可)。
至此cygwin软件算是安装完成,如果后期使用到新的命令,如果无法使用,则需要重新安装未安装的工具。
4、安装NDK
a、按照前面给的地址,下载NDK工具软件。
b、将该工具软件解压到某路径下(尽量不要是中文路径,因为在cygwin环境下使用中文不方便)E:\androidNDK\android-ndk-1.6_r1-windows\android-ndk-1.6_r1
c 、打开cygwin软件,首先进入根目录下,在使用cd cygdrive/e/androidNDK/android-ndk-1.6_r1-windows/android-ndk-1.6_r1/ 进入该目录下
d、输入build/host-setup.sh 如果出现下面信息说明就安装成功。
5、环境搭建好后,当然就是去编写一个JNI接口如何调用.SO文件了。步骤如下
A、e/androidNDK/android-ndk-1.6_r1-windows/android-ndk-1.6_r1/ 目录下有一个APP目录,专门是放NDK工程的,所以我们
在创建ANDROID工程时指定location位置为e/androidNDK/android-ndk-1.6_r1-windows/android-ndk-1.6_r1/APP/first_jni
创建一个JNI接口类Jin.java,内容如下:
package example.dialog.test;
public class Jin {
public native int add();
public native String getString();
}
B、运行DOS命令窗口,进入上述文件的目录下,使用 javac Jin.java 生成Jin.class类
C、运行javah -jni 包名+Jin.class 命令,最后生成 包名+Jin.h
D、在ANDROID工程目录下创建Jni目录,并将前面生成的 包名+Jin.h文件复制到该目录下,再在此目录下新建.c文件,用来实现 包名+Jin.h中的函数。
实现如下:
#include<stdio.h>
#include<stdlib.h>
#include"example_dialog_test_Jin.h"
int add()
{
int x,y;
x=100;
y=100;
return x*y;
}
JNIEXPORT jint JNICALL Java_example_dialog_test_Jin_add(JNIEnv *env,jobject thiz){
return add();
}
JNIEXPORT jstring JNICALL Java_example_dialog_test_Jin_getString(JNIEnv *env,jobject thiz){
(*env)->NewStringUTF(env,"hello world in c!!!");
}
E、JNI通过调用动态链接库(WINDOWS下是DLL,LINUX下是SO)来实现对C\C++方法的调用,因此现在我们就需要将上面写的
C代码编译成SO文件。
编译时需要再从个文件: Android.mk和Application.mk.这两个文件的存放目录是有讲究的,前者存在与C文件一个目录下,后者
存在ANDROID工程根目录下。
Android.mk 文件的内容一般可以去其它工程中去复制过来,内容如下:
LOCAL_PATH := $(call my-dir) //LOCAL_PATH表示此时位于工程目录的根目录,(call my-dir)返回当前目录位置。
include $(CLEAR_VARS)
LOCAL_MODULE := NewJNI //用来区分 Android.mk中的每一个模块,文件名必须唯一,不能有空格,这个是你以后库文件生成的文件名,编译器会自动 给你加上前缀lib和后缀.so.
LOCAL_SRC_FILES := example_dialog_test_Jin.c //编译时的C文件
include $(BUILD_SHARED_LIBRARY) //表明生成动态库
Application.mk中的内容:
APP_PROJECT_PATH := $(call my-dir)/firstjni-test
APP_MODULES := NewJNI //些处的值要与Android.mk中的LOCAL_MODULE中的值一样。
最后启动cygwin进入NDK目录,输入make APP=frist_jin,出现下面的界面表示编译成功。即在E:\androidNDK\android-ndk-1.6_r1-windows\android-ndk-1.6_r1\apps\first-jni\firstjni-test\libs\armeabi 该目录下生成了libNewJNI.so动态库。
F、接着我们将在安卓应用程序中使用该库,在上述工程下新建一个MyJni.java类,其内容如下:
package example.dialog.test;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import example.dialog.test.Jin;
public class MyJni extends Activity{
private TextView textview;
static{
System.loadLibrary("NewJNI");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Jin jni = new Jin();
int result = jni.add();
textview =(TextView)findViewById(R.id.tv);
textview.setText("add()="+result+"\ngetString()="+jni.getString());
}
}
最后运行应用程序,结果如下 图所示:
整个工程的目录如下 :
到此,整个过程都已经结束了,能够做到这样,也说明你对JNI接口以及NDK工具的使用算是入门了。
当然在整个过程中会有一些问题,我主要遇到过以下问题:
1、安装好cygwin软件后,用build/host-setup.h时出现GNU无法使用,后来查明了原因是在装cygwin时没有下载GNU以及后面使用的make,重新下载就好。
2、在使用javah -jni 包名+类名时(且不需要加.class后缀),出现无法找到包名+类名 ,原因是目录的层次不对,应该在包名的上级目录使用该命令。
3、在使用make APP=项目文件夹(而不是生成so文件名)。
4、在运行模似器时,一直报错,说引用的so文件内容为空,后来查询到原因是因为模拟器先用的是 inter atom(x86)的,而.so文件属于ARM系列的,更换后成功。
android如何使用自定义JNI接口,以及NDK工具的环境搭建与使用。