关于JAVA和Android的JNI的使用

来源:互联网 发布:android关于网络面试题 编辑:程序博客网 时间:2024/06/05 18:20

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别的相关安装文章.

原创粉丝点击