关于JAVA和Android的JNI的使用

    技术2025-02-13  14

    JNIJava Native Interface的缩写.

        设计目的是:标准JAVA库不支持一些平台特性,你可以用别的语言,编写代码使得你的软件支持这些平台特性,也可能你的程序需要用低级语言编写一些算法以提高程序的效率.这些情况都可能是你使用JNI的原因.

     

     

    JNI的编写步骤:

    1.编写带有native 声明的java类.

    2.编译java文件成class类

    3.使用javah -jni com.ikags.project.XXXX 编译成.h文件

    4.使用C/C++编写代码

    5.将.h和.c(.cpp)文件编译成.dll(.so)文件(根据平台不同,用不同的工具,PC平台VS2005就可以,android平台的话,用cygwin+android NDK(android  Native Development Kit)进行开发.

    6.将.dll(.so)文件提供给你的项目,用system.loadLibrary方法调用.

     

     

    下面2个平台一起讲解.不同的部分用蓝色加以区分. 1.编写一个带有native声明的java类.其中native方法就是需要生成的可调用的方法.这一步很简单 package com.ikags; public class AJni {   public native void display();   public native int plus(int x,int y);   public native int reduce(int x,int y); }   2.编译成class文件   可以通过命令行中的 javac AJni.java进行编译.最简单的方法,用J2SE项目直接右键run。然后,可以在项目下的bin目录中找到AJni.class文件.目的达成.如果通过命令行编译会出现问题,请找到JAVA 文件夹下面对应JDK的bin目录,把文件copy到里面执行(或者在环境变量中配置bin目录的位置)    3.使用javah -jni com.ikags.project.XXXX 编译成.h文件   通过命令行中的javah -jni com.ikags.project.XXXX 编译成.h文件,其中在编译.h文件的时候切记加入路径,这个有时候会引起一些奇怪的问题,比如说调用失败,调用不到啥的,原因未知.如果编译失败的话,处理方法同编译成class文件,请找到JAVA 文件夹下面对应JDK的bin目录,把文件copy到里面执行(或者在环境变量中配置bin目录的位置),此时生成文件com_ikags_AJni.h     4.使用C/C++编写代码   其中前一阶段生成的.h头文件如下: /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_ikags_AJni */ #ifndef _Included_com_ikags_AJni #define _Included_com_ikags_AJni #ifdef __cplusplus extern "C" { #endif /*  * Class:     com_ikags_AJni  * Method:    display  * Signature: ()V  */ JNIEXPORT void JNICALL Java_com_ikags_AJni_display   (JNIEnv *, jobject); /*  * Class:     com_ikags_AJni  * Method:    plus  * Signature: (II)I  */ JNIEXPORT jint JNICALL Java_com_ikags_AJni_plus   (JNIEnv *, jobject, jint, jint); /*  * Class:     com_ikags_AJni  * Method:    reduce  * Signature: (II)I  */ JNIEXPORT jint JNICALL Java_com_ikags_AJni_reduce   (JNIEnv *, jobject, jint, jint);

    #ifdef __cplusplus } #endif #endif

        这里是不需要进行任何更改的.这里只要自己再写一个.c(.cpp)文件,其中包含有这三个方法即可,这里特别注意,PC和android平台支持的库不一样,如果调用了不支持的库的话,后面的编译会出错,这个需要特别注意一下.  PC端的话还好说,而android平台方面,目前1.6的NDK只支持Math库,C标准库,ZLib库,Log库和OpenGL ES库.(这里举例来说PC端的JNI支持printf,但是如果android上不支持,这时候针对android平台开发的话,编译时候就会出错)     我编写的com_ikags_AJni.c如下: #include <com_ikags_AJni.h> JNIEXPORT void JNICALL Java_com_ikags_AJni_display   (JNIEnv *, jobject){   return;   }; JNIEXPORT jint JNICALL Java_com_ikags_AJni_plus   (JNIEnv *, jobject, jint x, jint y){     return x+y;     }; JNIEXPORT jint JNICALL Java_com_ikags_AJni_reduce   (JNIEnv *, jobject, jint x, jint y){     return x-y; };

    5.将.h和.c(.cpp)文件编译成.dll(.so)文件(根据平台不同,用不同的工具,PC平台VS2005就可以,android平台的话,用cygwin+android NDK(android  Native Development Kit)进行开发.这里的编译就体现了不同平台的区别.

    PC端:     直接通过VS2005就可以编译.编译时候如果出现找不到某些.h文件的错误的话(fatal error C1083: 无法打开包括文件L ..........  No such file or directory),参考下面更改: 项目--->属性---->配置属性---->C/C++---->常规---->附加包含目录”选项中有很多include下的库 ,将JAVA JDK里面incude的和里面的win32这两个路径添加入目录中,再尝试编译.一般来说代码正确的话,可以编译通过.这里生成myjni.dll.

    Android端:     这里要通过cygwin 和android NDK进行编译,cygwin安装步骤这里不再多说,android NDK下载后直接解压就OK.cygwin记得安装几个C的编译器. 打开cygwin,看到命令行模式, 通过 cd 命令进入NDK的目录,然后运行build/host-setup.sh .可以看到一些信息,如果没有报错的话,就正常安装完毕 编译本身命令很简单, make APP=hello-jni -B 就可以尝试编译 自带实例.编译成功的话,说明配置成功,然后我们开始编译我们自己的程序.

    在NDK目录的apps文件夹下,建立一个myjni文件夹,从hello项目里面复制Application.mk到myjni文件夹里面,用文本编辑器编辑文本为 APP_PROJECT_PATH := $(call my-dir) APP_MODULES      := myjni    然后建立一个jni文件夹,从hello项目里面复制一个Android.mk到jni文件夹目录,然后用文本编辑器更改里面的相关参数. LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE    := myjni LOCAL_SRC_FILES := com_ikags_AJni.cpp include $(BUILD_SHARED_LIBRARY)

    这时候把你的.h和.c(.cpp)等文件复制到这个目录下.然后用cygwin 运行make APP=myjni -B.如果编码没有错误的话,会自动生成/libs/armeabi/libmyjni.so文件,至此android的JNI文件生成完成.

    6.将.dll(.so)文件提供给你的项目,用system.loadLibrary方法调用. PC端: 将dll文件复制入程序跟目录,保留第一步写的native Java代码.在需要用的代码里面加入:  static   {     System.loadLibrary("myjni");   } 在运行方法里面加入:     AJni newlib = new AJni(); int i = newlib.plus(330, 1003);

    输出i即可测试是否有效.

    Android端: 将libs整个目录复制到android项目下.这里要注意的是loadLibrary读取的名字和lib的名字不同.这里我们的so文件为libmyjni.so,但是我们下面写的loadLibrary为myjni,这点是要注意下的 在自己的Activity里面添加代码:  static   {     System.loadLibrary("myjni");   }

    在运行方法里面加入:     AJni newlib = new AJni(); int i = newlib.plus(330, 1003);

    这是可以用Log.v方法来查看i的数值.

    针对android真机测试,需要将.so文件push入手机,system中的lib目录.需要可以自行google别的相关安装文章.

    最新回复(0)