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. 谈一谈CloudBlog的系统架构

    ---------------------------------------------------------------------------------------------[版权申明:本 ...

  2. Bootstrap3 排版-改变大小写

    通过这几个类可以改变文本的大小写. <p class="text-lowercase">Lowercased text.</p> <p class=& ...

  3. JS——2048(支持触屏及键盘操作)

    <html> <head> <title>2048</title> <style type="text/css"> ta ...

  4. [系统运维]Supervisord安装和启动程序

    supervisord 是client/server 系统 把不是守护进程的进程变成守护进程 监控它自己启动的进程,类似于看门狗 可以作为开机启动的一种封装 可以精确控制进程的状态,而不是pidfil ...

  5. android Handler机制之ThreadLocal详解

    概述 我们在谈Handler机制的时候,其实也就是谈Handler.Message.Looper.MessageQueue之间的关系,对于其工作原理我们不做详解(Handler机制详解). Messa ...

  6. ROS机器人程序设计(原书第2版)补充资料 (玖) 第九章 导航功能包集进阶 navigation

    ROS机器人程序设计(原书第2版)补充资料 (玖) 第九章 导航功能包集进阶 navigation 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中 ...

  7. ROS(indigo) 语音工具 科大讯飞 百度 pocketsphinx julius rospeex 16.11.22更新 ROS中文语音

    ROS语音工具汇总,目前先给出链接,只用过一些简单的命令. 中文语音: 参考链接:使用科大讯飞库 1 http://www.ncnynl.com/archives/201611/1069.html 2 ...

  8. 关于[[NSNotificationCenter defaultCenter] addObserver不remove后续又收到通知crash问题

    今天试了一个小demo,测出一个现象,同步出来:object 作为 observer 监听了通知 A,然后 object 中途被释放执行了dealloc,随后app发出这个通知 A:iOS 6.iOS ...

  9. C/C++与Matlab混合编程初探

    ================================================================== % 欢迎转载,尊重原创,所以转载请注明出处. % http://b ...

  10. Android设置item的行间距,以及去掉分割线方法

    1.设置item的行间距: 可以在xml布局文件中的listView下设置xml属性: android:divider="#00000000" android:dividerHei ...