Jni(Java Native Interface)是sun提供的java与系统中的原生方法交互的技术(在windows\linux系统中,实现java与native method互调)。目前只能由c/c++实现。
Android 底层是LInux,C,C++。有时候我们APK应用里也会调用C,C++的方法,虽然这种方式用的不多,我们还是要看下如何实现的。估计大公司JNI 会用的比较多,C,C++实现的东西容易跨平台,效率有时候会比JAVA高点。
1.Win7 + Java SDK 7.0 + Eclipse (这个比较简单,个人喜欢在WIndows下开发Android软件)
2.VMware 7 + Ubuntu 11 + Java SDK 6.0 + Android源码 + android-ndk-r7c + make-3.81
1.只有一台机子,就用虚拟机了,安装Ubuntu是容易的(需要准备至少35G空间),最后执行下StartX,和给Root 用户设置密码
2.安装Java SDK ,我是到官方网站下载个.jar文件,chomd+x后,执行下,再设置环境变量即可
3.下载Android源码,最好参考官方网站的指导,虽然是英文版的,但是是最新的,书上或网络上的大部分都过时了
4.编译Android源码,切换到放置Android源码的目录,make 执行下。
5.android-ndk-r7c也是到官方网站下的,不需要安装,解压到硬盘的特定位置即可(看了readme后再看install,才发现需要make-3.81+)
6.make-3.81 google 搜过来下,执行make -configure,make -check,make -install 即可。
7.切换到放置Android源码的目录, 执行 source ./build/envsetup.sh
注意一下,我们这个项目中有一个特殊的文件夹jni 里面有 Android.mk,hello-jni.c两个文件
这两个文件的作用就是为了编译生成libs/armeabi/libhello-jni.so文件的。而java就是调用libhello-jni.so里的function的
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY)有时候想给这几行加下注释,还是算了,hello-jni.c是要编译的目标文件,hello-jni是要生成.so文件的名称,会自动加上lib,其他的就照抄吧。如果还需要打印log什么的,就需要加上LOCAL_LDLIBS += -llog等。
#include <string.h> #include <jni.h> /* This is a trivial JNI example where we use a native method * to return a new VM String. See the corresponding Java source * file located at: * * /src/com/example/HelloJni/HelloJni.java */ jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) { return (*env)->NewStringUTF(env, "Hello from JNI !"); }
先解释下jstring, 我们需要在c,c++和java之间传递值,中间桥梁就是这些以j开头的类型,string对于jstring
Java类型 | 本地类型 | 描述 |
boolean | jboolean | C/C++8位整型 |
byte | jbyte | C/C++带符号的8位整型 |
char | jchar | C/C++无符号的16位整型 |
short | jshort | C/C++带符号的16位整型 |
int | jint | C/C++带符号的32位整型 |
long | jlong | C/C++带符号的64位整型e |
float | jfloat | C/C++32位浮点型 |
double | jdouble | C/C++64位浮点型 |
Object | jobject | 任何Java对象,或者没有对应java类型的对象 |
Class | jclass | Class对象 |
String | jstring | 字符串对象 |
Object[] | jobjectArray | 任何对象的数组 |
boolean[] | jbooleanArray | 布尔型数组 |
byte[] | jbyteArray | 比特型数组 |
char[] | jcharArray | 字符型数组 |
short[] | jshortArray | 短整型数组 |
int[] | jintArray | 整型数组 |
long[] | jlongArray | 长整型数组 |
float[] | jfloatArray | 浮点型数组 |
double[] | jdoubleArray | 双浮点型数组 |
解释下那个长长的函数名称Java_com_example_hellojni_HelloJni_stringFromJNI,这个函数名称可以自己打,但是要遵循它的规律,前面是java包的名称,最后面才是我们定义的方法名称。
这个函数名称也可以用这样的方法生成(假设我们的java文件叫TestJni.java,项目名称hello-jni,包名称com.example.hellojni):
1.先运行Android项目,这样会生成 “hello-jni\bin\classes\com\example\hellojni\TestJni.class” 类文件
2.打开cmd,cd 到 “hello-jni\bin\classes“ 执行javah com.example.hellojni.TestJni,会在hello-jni\bin\classes\目录下生成 com_example_hellojni_TestJni.h文件。这里头就有函数名称和返回值,参数。只是没有具体实现的。
jni文件下有了Android.mk 和hello-jni.c就可以编译libhello-jni.so文件了。
这里我也卡了很久,我知道有两种方法可以生成:
1.linux cd到jni文件夹下面,执行mm命令,如果编译没错的话,会在类似:out\target\product\kpt75_ics\system\lib下生成so文件,这种方法调试比较麻烦,每次都要到这里复制so文件到项目中。
2.安装好make-3.81后,cd到项目根目录,执行~/myandroid/android-nkd-r7c/ndk-build,红色字前面的路径取决与你的nkd解压放的路径,也可以把前面长长的路径添加到环境变量中,假设环境变量的名称角$NDK 那么就执行$NDK/ndk-build即可。用这种方法编译生成so文件,会自动在项目下建立lib/armeabi/lib-hellojni.so文件,这样方便调试。
其实比较有参考价值是官方google提供的jni例子:有关于Opengl,播放音乐等程序。可以在下载的ndk里面找到。
最后是project 下载hello-jni
文章源地址:http://www.waitingfy.com/?p=146