JAVA和Android的JNI的使用

 JNI是Java 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
  /* 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
  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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值