JNI乃Java Native Interface简称,为Java世界和Native世界之间的桥梁。自java 1.1开始JNI标准成为java平台的一部分。它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。
下面通过实现简单的加法函数,来手动实现如何使用JNI。
生成JNI头文件的方法:
E:\android_proj\JNITestOne\src>javah -d ..\jni 包名.类名
生成so,还得要有NDK
Eclipse集成NDK
先下载cygwin、NDK、及CDT插件


一、下载安装cygwin
NDK运行需要借助于该工具,模拟linux的环境。
1.下载地址: http://www.cygwin.com  下载setup.exe,然后点击运行
2.安装方式选择 Install from Internet->...->选择路径的时候目录不要带有空格的->..->连接方式选择Didrect Connection
-->cygwin包下载地址 http://mirrors.kernel.org/  ,搜索列表的时候只需过滤以下包即可
autoconf2.1、automake1.14、binutils、gcc-core、gcc-g++、gdb、pcre、pcre-devel、gawk、make
下载完后测试确认:
3.运行cygwin,命令行输入 cygcheck -c cygwin 会打印出版本和状态
4.依次运行gcc -version、g++ -version、make -version、gdb -version 测试


二、下载NDK
ndk用来编译本地文件生成库
下载路径:http://developer.android.com/tools/sdk/ndk/index.html
下载完后解压即可,但需注意不要解压在路径中带有空格的文件夹下。


完成一、二后,可打开cygwin,进入到ndk/samples/hello-jni下测试NDK是否OK
$$NDK/ndk-build
如果成功则会打印出so生成的路径。


三、下载CDT插件
主要是用来在eclipse上开发C/C++代码方便一点。
下载路径:http://www.eclipse.org/cdt/downloads.php
解压后,将解压目录里的features和plugins里面新增的文件更新到eclipse目录对应的文件夹里面
然后可以创建C/C++工程。但是可能是缺少配置,有些库链不上,无法编译(未搞通??????)




四、JNI的使用
下面演示一下 Eclipse+cygwin+NDK运行android项目,演示JNI的使用过程:
1.创建Android project
创建JniTwo 类调用native方法Display(),为保证能加载libjnitwo.so,在类中定义静态方法load调用库。

package com.aug.jnidemotwo; 



 import android.app.Activity; 

 import android.os.Bundle; 

 import android.util.Log; 

 import android.view.Menu; 



 public class JniTwo extends Activity { 



public native String Display();  //声明native方法 

 

static { 

System.loadLibrary("jnitwo");  //加载jni库 

} 

 

@Override 

protected void onCreate(Bundle savedInstanceState) { 

super.onCreate(savedInstanceState); 

setContentView(R.layout.activity_jni_two); 

Log.d("JniTwo", Display());//调用库方法 

} 



@Override 

public boolean onCreateOptionsMenu(Menu menu) { 

// Inflate the menu; this adds items to the action bar if it is present. 

getMenuInflater().inflate(R.menu.activity_jni_two, menu); 

return true; 

} 

 }




2.生成jni头文件

E:\android_proj\JNIDemoTwo>cd src 



 E:\android_proj\JNIDemoTwo\src>javah -d ../jni com.aug.jnidemotwo.JniTwo 

 注释:  -d 是将生成的.h放到指定的jni目录 



 E:\android_proj\JNIDemoTwo\src>ls ../jni 

 Android.mk  com_aug_jnidemotwo_JniTwo.cpp  com_aug_jnidemotwo_JniTwo.h 

 E:\android_proj\JNIDemoTwo\src> 

 com_aug_jnidemotwo_JniTwo.h 

 /* DO NOT EDIT THIS FILE - it is machine generated */ 

 #include <jni.h> 

 /* Header for class com_aug_jnidemotwo_JniTwo */ 



 #ifndef _Included_com_aug_jnidemotwo_JniTwo 

 #define _Included_com_aug_jnidemotwo_JniTwo 

 #ifdef __cplusplus 

 extern "C" { 

 #endif 

 /* 

  * Class:     com_aug_jnidemotwo_JniTwo 

  * Method:    Display 

  * Signature: ()Ljava/lang/String; 

  */ 

 JNIEXPORT jstring JNICALL Java_com_aug_jnidemotwo_JniTwo_Display 

   (JNIEnv *, jobject); 



 #ifdef __cplusplus 

 } 

 #endif 

 #endif





3.然后增加cpp文件实现native方法

com_aug_jnidemotwo_JniTwo.cpp 

 #include "com_aug_jnidemotwo_JniTwo.h" 

 #include <stdio.h>   

 #include <jni.h>  

 JNIEXPORT jstring JNICALL Java_com_aug_jnidemotwo_JniTwo_Display(JNIEnv * env, jobject jobj) 

 { 

//env->ReleaseStringUTFChars(sRet, "abcdefg"); 

char *retStr = "hello, this is test!"; 

jstring retJstr = env->NewStringUTF(retStr); 

//env->ReleaseStringUTFChars(s, str); 

//printf("1111111111111"); 

return retJstr; 

 }




4.创建Android.mk编译生成so库

Android.mk 



 LOCAL_PATH := $(call my-dir) 

 include $(CLEAR_VARS) 



 LOCAL_MODULE := jnitwo 

 LOCAL_SRC_FILES := com_aug_jnidemotwo_JniTwo.cpp 



 include $(BUILD_SHARED_LIBRARY)



5.NDK编译生成so库

运行cygwin

android jni如何指定头文件_android


进入到项目目录下,执行ndk-build


android jni如何指定头文件_java_02

android工程目录结构如下

android jni如何指定头文件_JNI使用_03


6.运行JNIDemoTwo程序


android jni如何指定头文件_android_04


至此,一个最简单的jni使用过程已经完成。