Android Jni 事例,ndk

Android Jni 例子,ndk

1.Android JNI介绍

Jni(Java Native Interface)是sun提供的java与系统中的原生方法交互的技术(在windows\linux系统中,实现java与native method互调)。目前只能由c/c++实现。

Android 底层是LInux,C,C++。有时候我们APK应用里也会调用C,C++的方法,虽然这种方式用的不多,我们还是要看下如何实现的。估计大公司JNI 会用的比较多,C,C++实现的东西容易跨平台,效率有时候会比JAVA高点。

2.拿官方的Hello-Jni做个说明吧

先说下JNI需要的平台和软件把(Linux 下)。虽然是简单的Hello-Jni,也让我弄了很久

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

3.先看下一个JNi 的源码目录结构吧

Android Jni 事例,ndk

注意一下,我们这个项目中有一个特殊的文件夹jni 里面有 Android.mk,hello-jni.c两个文件

这两个文件的作用就是为了编译生成libs/armeabi/libhello-jni.so文件的。而java就是调用libhello-jni.so里的function的

4.开始编码

4.1/jni/Android.mk

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等。

4.2/jni/hello-jni.c

#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文件。这里头就有函数名称和返回值,参数。只是没有具体实现的。

4.3 编译生成xx.so文件

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