1 什么是JNI

JNI Java本地开发接口

JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(C/C++)

通过这个协议,java代码就可以调用外部的C/C++代码,外部的C/C++代码也可以调用Java代码。

2 为什么用JNI

1  JNI扩展了java虚拟机的能力,驱动开发(wifi-hotspot)2.3无线热点共享

2  Native code效率高,数学运算,实时渲染的游戏上,音视频处理(极品飞车),opengl,ffmpeg

3  复用代码(文件压缩,人脸识别)

4  特殊的业务场景

3 怎么用JNI

1 C/C++语言

2 掌握java ini流程

3 NDK(native develop kits)

5 配置cygwin64的环境变量的方式是编写\Cygwin\etc\profile,将ndk的路径配置到path里面,截图如下:

打开Cygwin输入:Make –v,结果如下:

显示出来GNI Make的版本,说明我们的cygwin模拟的Linux编辑环境模拟成功。

输入ndk-build,出现以下结果:

显示出上面的效果,说明环境变量已经配置好了。

6 同样可以将这个变量配置到windows下的环境变量中:配置如下:

进入CMD命令行窗口中,如果出现以下结果,说明配置成功:

当配置了第6步之后,若cygwin没有配置成功时,也可以在window中的cmd命令行中使用ndk-build.

7 jni中的数据类型(后面是Java中的类型,左边是C语言中的类型):

#ifdef HAVE_INTTYPES_H

# include <inttypes.h>      /* C99 */

typedef uint8_t         jboolean;       /* unsigned 8 bits */

typedef int8_t          jbyte;          /* signed 8 bits */

typedef uint16_t        jchar;          /* unsigned 16 bits */

typedef int16_t         jshort;         /* signed 16 bits */

typedef int32_t         jint;           /* signed 32 bits */

typedef int64_t         jlong;          /* signed 64 bits */

typedef float           jfloat;         /* 32-bit IEEE 754 */

typedef double         jdouble;        /* 64-bit IEEE 754 */

#else

typedef unsigned char   jboolean;       /* unsigned 8 bits */

typedef signed char     jbyte;          /* signed 8 bits */

typedef unsigned short  jchar;          /* unsigned 16 bits */

typedef short          jshort;         /* signed 16 bits */

typedef int            jint;           /* signed 32 bits */

typedef long long      jlong;          /* signed 64 bits */

typedef float          jfloat;         /* 32-bit IEEE 754 */

typedef double        jdouble;        /* 64-bit IEEE 754 */

#endif

/* "cardinal indices and sizes" */

typedef jint            jsize;

8 案例效果(下面的土司是调用C语言代码显示的):

接下来编写案例,使用java代码调用C代码,创建项目helloworldformc,代码结构如下:

其中libs下的内容如下:

9 编写MainActivity,代码如下:

package com.example.helloworldformc;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.widget.Toast;

public class MainActivity extends Activity {

// 1 定义一个c方法的接口   相当于在java代码中定义了一个接口

//接口的实现方法是C语言实现的

public native String helloWorldFromC();

// 变态命名
         public native String hello_world_from_c();

// 5 步在java代码中 引入库函数

static{

System.loadLibrary("hello");// 注意事项 去掉前面的lib 后面的.so

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

public void click(View view){

// 弹出一个土司 土司的内容 是c代码写出来

// 第6步

Toast.makeText(getApplicationContext(), helloWorldFromC(), 0).show();

}

}

10 在项目下创建一个jni目录(这个是必须的),开始编写Hello.c,代码如下:

#include <stdio.h>

#include <jni.h>

/*

* 对应的是:public native String helloWorldFromC(){}

* jstring:表示的是返回的是String类型的

* 函数名称规则是:Java_包名_类名_方法名。

*

* 注意:包名之间的"."在下面要变成下划线

*/

jstring Java_com_example_helloworldformc_MainActivity_helloWorldFromC(JNIEnv* env,jobject obj) {

//2步  实现C代码

//返回一个java String类型的字符串,使用一下函数

//jstring     (*NewStringUTF)(JNIEnv*, const char*);

//(*env) 相当于 JNINativeInterface* JNIEnv

//*(*env)  相当于 JNINativeInterface

//可以通过下面两种方式返回参数

//return (**env).NewStringUTF(env,"helloworldfromc");

return  (*env)->NewStringUTF(env,"helloworldfromc");

//android.mk 告诉编译器  如何把C代码打包成函数库

//3 生成.mk文件

//4 步  把C代码  打包成函数库

}

/*这里JNIEXPORT表示的是通过工具生成的,这时候也可以将JNIEXPORT去掉*/

JNIEXPORT jstring JNICALL Java_com_example_helloworldformc_MainActivity_hello_1world_1from_1c

(JNIEnv * env, jobject obj){

}

注意:上面的这个源文件的类名也可以通过javah命令生成,生成过程如下:

(1)       如果JDK使用的是1.6,使用javah命令前要到达:项目目录\bin\classes目录下

(2)       如果JDK使用的是1.7,使用javah命令前要达到:项目目录\bin\src目录下:

例如(我使用的是JDK1.7):

在项目中生成.h:

11 Android.mk文件的内容如下:

#一个Android.mk文件必须下面这个变量开头,它用于定位

#它用于定位你的源文件,my-dir这个宏是构件系统提供的,

#它用于返回当前目录的路径(这个目录包含Android.mk它自己)

LOCAL_PATH := $(call my-dir)

#CLEAR_VARS也是build system构件系统提供的,指定到一个指定的GNU Makefile文件

#这个Makefile文件帮你去清除一些LOCAL_XXX变量(比如:LOCAL_MODULE,LOCAL_SRC_FILES

#,LOCAL_STATIC_LIBRARIES.等等...),除了LOCAL_PATH.

include $(CLEAR_VARS)

#LOCAL_MODULE变量必须在你的Android.mk文件中定义。名称必须唯一

#并且不能包含一些空格,要注意的是构件系统会自动的添加适当的前缀和前缀

#换一句话说,一个命名为"foo"的共享库模块,会被生成"libfoo.so"文件。

#重要提示:如果你定义的模块名称是"libfoo",构建系统将不会添加"lib"前缀,

#并且也会生成"libfoo.so"文件。

LOCAL_MODULE    := hello

#LOCAL_SRC_FILES变量必须包含一个C或者C++的源文件集合,这些文件最终会被用于

#生成一个module,注意的是,这里不应该有头文件和包含文件,因为构件系统自动为您

#添加这些文件,只需要列出源文件就行了。

#注意:默认的C++源文件的后缀名是.cpp,同样你也可以通过LOCAL_CPP_EXTENSION来自定义

#CPP的后缀名(例如:".cxx"可以,"cxx"不可以)

LOCAL_SRC_FILES := Hello.c

include $(BUILD_SHARED_LIBRARY)

12 接下来使用cygwin,使用ndk-build来编译程序

(1)、如想将c变成.so的库,需要使用ndk-build命令

(2)、将路径路径切换到工程目录下。

(3)、然后执行ndk-build这个操作(这个操作直接指定到项目路径下就可以了)

注意:在使用这个ndk-build功能之前,需要有Android.mk文件(告诉编译器,如何将C代码打包成函数库。具体的Android.mk怎么使用可以看ndk中的Android.html文档)



01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用的更多相关文章

  1. windows和linux环境下java调用C++代码-JNI技术

    最近部门做安卓移动开发的需要调C++的代码,困难重重,最后任务交给了我,查找相关资料,没有一个教程能把不同环境(windows,linux)下怎么调用说明白的,自己在实现的过程中踩了几个坑,在这里总结 ...

  2. 通过JNI实现java调用C代码和C代码调用java的代码

    一.java调用C代码 1)java中需要声明调用的函数,也就是native方法,并通过System.LoadLibrary来调用dll或者so(C代码).实例代码如下: public class H ...

  3. JNI Java调用C代码 示例

    Activity public class MainActivity extends ListActivity {     static {         System.loadLibrary(&q ...

  4. 1.JAVA中使用JNI调用C++代码学习笔记

    Java 之JNI编程1.什么是JNI? JNI:(Java Natibe Inetrface)缩写. 2.为什么要学习JNI?  Java 是跨平台的语言,但是在有些时候仍然是有需要调用本地代码 ( ...

  5. Java调用C++类库--JNI

    JNI是Java平台中的一个重要的功能,这里我把我做的Demo总结一下,分享一下,我会把每个步骤尽量的详细的展现出来. 这里我就不讲解JNI的原理了,google,百度一下,到处都是 好了,直接来讲步 ...

  6. AndroidStudio如何配置NDK/JNI开发环境

    参考文章: http://www.th7.cn/Program/Android/201509/550864.shtml http://www.open-open.com/lib/view/open14 ...

  7. JNI环境变量——JNIEnv*的使用 &&配置jd环境变量

      如果没有配置环境变量,先配置环境变量,如下: 1.右键我的电脑——高级——环境变量——下面的系统变量 2.选择[新建系统变量]--弹出“新建系统变量”对话框,在“变量名”文本框输入“JAVA_HO ...

  8. Android使用JNI(从java调用本地函数)

    当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...

  9. Android JNI之JAVA调用C/C++层

    转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5929996.html 一.java调用本地函数的开发步骤: 1.编写本地方法的类(可以说是用来叙述本地方法的类 ...

随机推荐

  1. ubuntu初始化python3+postgresql+uwsgi+nginx+django

    一. postgresql 数据库 安装 apt-get update apt-get install postgresql 进入psql客户端 sudo -u postgres psql 创建数据库 ...

  2. Rxjava +Retrofit 你需要掌握的几个技巧,Retrofit缓存,RxJava封装,统一对有无网络处理,异常处理, 返回结果问题

    本文出处 :Tamic 文/ http://blog.csdn.net/sk719887916/article/details/52132106 Rxjava +Rterofit 需要掌握的几个技巧 ...

  3. Python rich comparisons 自定义对象比较过程和返回值

    Classes wishing to support the rich comparison mechanisms must add one or more of the following new ...

  4. Java 资源本地化与国际化

    资源包 在编写应用程序的时候,需要面对的一个问题是如何来处理与locale相关的一些信息.比如,页面上的一些静态文本就希望能够以用户习惯的语言显示.最原始的做法是将这些信息硬编码到程序中(可能是一大串 ...

  5. 阻塞IO服务器模型之多线程服务器模型

    针对单线程服务器模型的特点,我们可以对其进行改进,使之能对多个客户端同时进行响应.最简单的改进即是使用多线程(或多进程)服务器模型,在应用层级别,我们一般采用多线程模式.多线程能让多个客户端同时请求, ...

  6. TortoiseSVN使用

    TortoiseSVN是Subversion版本控制系统的一个免费开源客户端,不需要为使用它而付费. TortoiseSVN是 Subversion 的 Windows 扩展.它使你避免接触 Subv ...

  7. ROS_Kinetic_x 目前已更新的常用機器人資料 rosbridge agvs pioneer_teleop nao TurtleBot

    Running Rosbridge Description: This tutorial shows you how to launch a rosbridge server and talk to ...

  8. JDBC数据库连接简介(一)

    jdbc的由来 odbc(open database connection) 最初各个数据库比如mysql和oracle等,虽然都支持sql,但是他们的连接方式是不一样的,需要按照相应的api来编写不 ...

  9. TCP连接建立系列 — 客户端接收SYNACK和发送ACK

    主要内容:客户端接收SYNACK.发送ACK,完成连接的建立. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 接收入口 tcp_v4_rcv |--&g ...

  10. [ExtJS5学习笔记]第二十节 Extjs5配合数组的push方法,动态创建并加载组件

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39226773 官方例子:http://docs.sencha.com/extjs/5. ...