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
进入到项目目录下,执行ndk-build
android工程目录结构如下
6.运行JNIDemoTwo程序
至此,一个最简单的jni使用过程已经完成。