前言

  • Android开发中,使用 NDK开发的需求正逐渐增大
  • 但很多人却搞不懂 JNI 与 NDK 到底是怎么回事
  • 今天,我将先介绍JNI 与 NDK & 之间的区别,手把手进行 NDK的使用教学,希望你们会喜欢 

目录


1. JNI介绍

1.1 简介

  • 定义:Java Native Interface,即 Java本地接口
  • 作用: 使得Java 与 本地其他类型语言(如C、C++)交互

    即在 Java代码 里调用 C、C++等语言的代码 或 C、C++代码调用 Java 代码

  • 特别注意:

    1. JNI是 Java 调用 Native 语言的一种特性
    2. JNI 是属于 Java 的,与 Android 无直接关系

1.2 为什么要有 JNI

  • 背景:实际使用中,Java 需要与 本地代码 进行交互
  • 问题:因为 Java 具备跨平台的特点,所以Java 与 本地代码交互的能力非常弱
  • 解决方案: 采用 JNI特性 增强 Java 与 本地代码交互的能力

1.3 实现步骤

  1. Java中声明Native方法(即需要调用的本地方法)
  2. 编译上述 Java源文件javac(得到 .class文件)
  3. 通过 javah 命令导出JNI的头文件(.h文件)
  4. 使用 Java需要交互的本地代码 实现在 Java中声明的Native方法 

    如 Java 需要与 C++ 交互,那么就用C++实现 JavaNative方法

  5. 编译.so库文件
  6. 通过Java命令执行 Java程序,最终实现Java调用本地代码

更加详细过程请参考本文第4节:具体使用


2. NDK介绍

2.1 简介

  • 定义:Native Development Kit,是 Android的一个工具开发包

    NDK是属于 Android 的,与Java并无直接关系

  • 作用:快速开发C、 C++的动态库,并自动将so和应用一起打包成 APK 
    即可通过 NDK在 Android中 使用 JNI与本地代码(如C、C++)交互
  • 应用场景:在Android的场景下 使用JNI

    即 Android开发的功能需要本地代码(C/C++)实现

  • 特点

  • 额外注意

2.2 使用步骤

  1. 配置 Android NDK环境
  2. 创建 Android 项目,并与 NDK进行关联
  3. 在 Android 项目中声明所需要调用的 Native方法
  4. 使用 Android需要交互的本地代码 实现在Android中声明的Native方法 

    比如 Android 需要与 C++ 交互,那么就用C++ 实现 JavaNative方法

  5. 通过 ndk - bulid 命令编译产生.so库文件
  6. 编译 Android Studio 工程,从而实现 Android 调用本地代码

更加详细过程请参考本文第4节:具体使用


3. NDK与JNI关系


4. 具体使用

本文根据版本的不同介绍了两种在Android Studio中实现 NDK的方法:Android Studio2.2 以下 & 2.2以上

4.1 Android Studio2.2 以下实现NDK

  • 步骤如下

    1. 配置 Android NDK环境
    2. 关联 Andorid Studio项目 与 NDK
    3. 创建本地代码文件(即需要在 Android项目中调用的本地代码文件)
    4. 创建 Android.mk文件 & Application.mk文件
    5. 编译上述文件,生成.so库文件,并放入到工程文件中
    6. 在 Andoird Studio项目中使用 NDK实现 JNI 功能
  • 步骤详解

步骤1:配置 Android NDK环境

具体请看文章手把手教你配置Android NDK环境

步骤2: 关联Andorid Studio项目 与 NDK

  • 当你的项目每次需要使用 NDK 时,都需要将该项目关联到 NDK

    1. 此处使用的是Andorid Studio,与Eclipse不同
    2. 还在使用Eclipse的同学请自行查找资料配置
  • 具体配置如下

a. 在Gradle的 local.properties中添加配置

ndk.dir=/Users/Carson_Ho/Library/Android/sdk/ndk-bundle
  • 1

ndk目录存放在SDK的目录中,并命名为ndk-bundle,则该配置自动添加

b. 在Gradle的 gradle.properties中添加配置

android.useDeprecatedNdk=true
// 对旧版本的NDK支持

c. 在Gradle的build.gradle添加ndk节点

  • 至此,将Andorid Studio的项目 与 NDK 关联完毕
  • 下面,将真正开始讲解如何在项目中使用NDK 

步骤3:创建本地代码文件

  • 即需要在Android项目中调用的本地代码文件

    此处采用 C++作为展示

test.cpp

# include <jni.h>
# include <stdio.h>extern "C"
{JNIEXPORT jstring JNICALL Java_scut_carson_1ho_ndk_1demo_MainActivity_getFromJNI(JNIEnv *env, jobject obj ){// 参数说明// 1. JNIEnv:代表了VM里面的环境,本地的代码可以通过该参数与Java代码进行操作// 2. obj:定义JNI方法的类的一个本地引用(this)return env -> NewStringUTF("Hello i am from JNI!");// 上述代码是返回一个String类型的"Hello i am from JNI!"字符串}
}

此处需要注意:

  • 如果本地代码是C++.cpp或者.cc),要使用extern "C" { }把本地方法括进去
  • JNIEXPORT jstring JNICALL中的JNIEXPORT 和 JNICALL不能省
  • 关于方法名Java_scut_carson_1ho_ndk_1demo_MainActivity_getFromJNI 
    1. 格式 = Java _包名 _ 类名_Java需要调用的方法名
    2. Java必须大写
    3. 对于包名,包名里的.要改成__要改成_1

如我的包名是:scut.carson_ho.ndk_demo,则需要改成scut_carson_1ho_ndk_1demo 
最后,将创建好的test.cpp文件放入到工程文件目录中的src/main/jni文件夹 
若无jni文件夹,则手动创建。

下面我讲解一下JNI类型与Java类型对应的关系介绍 

步骤4:创建Android.mk文件

  • 作用:指定源码编译的配置信息

    如工作目录,编译模块的名称,参与编译的文件等

  • 具体使用

Android.mk

LOCAL_PATH       :=  $(call my-dir)
// 设置工作目录,而my-dir则会返回Android.mk文件所在的目录include              $(CLEAR_VARS)
// 清除几乎所有以LOCAL——PATH开头的变量(不包括LOCAL_PATH)LOCAL_MODULE     :=  hello_jni
// 设置模块的名称,即编译出来.so文件名
// 注,要和上述步骤中build.gradle中NDK节点设置的名字相同LOCAL_SRC_FILES  :=  test.cpp
// 指定参与模块编译的C/C++源文件名include              $(BUILD_SHARED_LIBRARY)
// 指定生成的静态库或者共享库在运行时依赖的共享库模块列表。

最后,将上述文件同样放在`src/main/jni`文件夹中。

步骤5:创建Application.mk文件

  • 作用:配置编译平台相关内容
  • 具体使用

*Application.mk*

APP_ABI := armeabi
// 最常用的APP_ABI字段:指定需要基于哪些CPU平台的.so文件
// 常见的平台有armeabi x86 mips,其中移动设备主要是armeabi平台
// 默认情况下,Android平台会生成所有平台的.so文件,即同APP_ABI := armeabi x86 mips
// 指定CPU平台类型后,就只会生成该平台的.so文件,即上述语句只会生成armeabi平台的.so文件

最后,将上述文件同样放在`src/main/jni`文件夹中

步骤6:编译上述文件,生成.so库文件

  • 经过上述步骤,在src/main/jni文件夹中已经有3个文件

  • 打开终端,输入以下命令
// 步骤1:进入该文件夹
cd /Users/Carson_Ho/AndroidStudioProjects/NDK_Demo/app/src/main/jni
// 步骤2:运行NDK编译命令
ndk-build

  • 编译成功后,在src/main/会多了两个文件夹libs & obj,其中libs下存放的是.so库文件

步骤7:在src/main/中创建一个名为jniLibs的文件夹,并将上述生成的so文件夹放到该目录下

  1. 要把名为 CPU平台的文件夹放进去,而不是把.so文件放进去
  2. 如果本来就有.so文件,那么就直接创建名为jniLibs的文件夹并放进去就可以

步骤8:在Andoird Studio项目中使用NDK实现JNI功能

  • 此时,我们已经将本地代码文件编译成.so库文件并放入到工程文件中
  • Java代码中调用本地代码中的方法,具体代码如下:

MainActivity.java

public class MainActivity extends AppCompatActivity  {// 步骤1:加载生成的so库文件// 注意要跟.so库文件名相同static {System.loadLibrary("hello_jni");}// 步骤2:定义在JNI中实现的方法public native String getFromJNI();// 此处设置了一个按钮用于触发JNI方法private Button Button;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 通过Button调用JNI中的方法Button = (Button) findViewById(R.id.button);Button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Button.setText(getFromJNI());}});}

主布局文件:activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="scut.carson_ho.ndk_demo.MainActivity">// 此处设置了一个按钮用于触发JNI方法<Buttonandroid:id="@+id/button"android:layout_centerInParent="true"android:layout_width="300dp"android:layout_height="50dp"android:text="调用JNI代码" /></RelativeLayout>

结果展示


源码地址

Carson-Ho的Github地址:NDK_Demo


4.2 Android Studio2.2 以上实现NDK

  • 如果你的Android Studio是2.2以上的,那么请采用下述方法

    因为Android Studio2.2以上已经内部集成 NDK,所以只需要在Android Studio内部进行配置就可以

  • 步骤讲解

步骤1:按提示创建工程

在创建工程时,需要配置 NDK,根据提示一步步安装即可。

步骤2:根据需求使用NDK

  • 配置好NDK后,Android Studio会自动生成C++文件并设置好调用的代码
  • 你只需要根据需求修改C++文件 & Android就可以使用了。


5. 总结

  • 本文主要讲解 Java的 JNI与 AndroidNDK相关知识
  • 下面我将继续对 Android中的NDK进行深入讲解 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记
  • 转载自:https://blog.csdn.net/carson_ho/article/details/73250163

Android:JNI 与 NDK到底是什么相关推荐

  1. Android JNI 和 NDK

    1.Android NDK 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第 ...

  2. Connor学Android - JNI和NDK编程

    Learn && Live 虚度年华浮萍于世,勤学善思至死不渝 前言 Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习.复盘过程,欢迎各位 ...

  3. Android jni开发--NDK环境搭建

    谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwin才能使用NDK.而在NDKr7开始,Google的Windows版的NDK提供 ...

  4. Android JNI(一)——NDK与JNI基础

    前言 ndk开发是高级Android 开发必备的技能,也是很多Android开发工程师难以逾越的门槛,因此,学习ndk开发已经是高级Android必备技能,所以我尝试把自己ndk开发经验记录下来,不知 ...

  5. android jni 机器码,NDK构建

    Android.mk Android.mk把你的源码组织成"模块"(静态库/动态库).默认情况会读取project/jni/Android.mk,并会读取project/jni/A ...

  6. Android 中的 NDK 到底是什么?(详细解析+案例实战)

    NDK 提供了一系列的工具,帮助开发者快速开发 C (或 C++ )的动态库,并能自动将 so 和 java 应用一起打包成 apk:这些工具对开发者的帮助是巨大的 什么是 NDK ? Android ...

  7. Android JNI和NDK学习(5)--JNI分析API

    Java类型和本地类型对应 在如下情况下,需要在本地方法中应用java对象的引用,就会用到类型之间的转换: java方法里面将参数传入本地方法: 在本地方法里面创建java对象: 在本地方法里面ret ...

  8. Android:JNI 与 NDK的区别(含实例教学)

    前言 在Android开发中,使用 NDK开发的需求正逐渐增大 但很多人却搞不懂 JNI 与 NDK 到底是怎么回事 今天,我将先介绍JNI 与 NDK & 之间的区别,手把手进行 NDK的使 ...

  9. Android JNI学习(六)——Java与Native实战演习

    前言: 前几篇我主要介绍了jni先关的基础知识和常用API,相信看过的童靴对JNI已经有了一定的了解,如果不了解也没关系,下面我给出了链接,可以点进去学习.接下来我将实战一个完整案例,案例很简单,就是 ...

最新文章

  1. awk 添加自定义变量
  2. 【Android RTMP】Android Camera 视频数据采集预览 ( 图像传感器方向设置 | Camera 使用流程 | 动态权限申请 )
  3. debian安装python3_debian上安装python3.6
  4. boost::describe模块实现overloaded的测试程序
  5. CF938G Shortest Path Queries(线性基/线段树分治/异或)
  6. skywalking(1) 基于opentracing规范的APM系统
  7. linux设备驱动中的并发控制
  8. 土豆服务器延期修复,DNF更新推迟, 土豆服务器发霉了?
  9. linux安装neo4j
  10. 脉冲控制仪C语言程序,可编程脉冲控制仪
  11. 身份证OCR识别SDK
  12. Web CAD SDK 14.1.0 New Crack
  13. WPS 连接 H2 Database
  14. SVN忽略文件和文件夹
  15. ios下input框 数字键盘问题
  16. archlinux音量管理
  17. 测角误差估计算法matlab,Harris角点检测 及 Matlab实验
  18. AD根据Primitives进行敷铜
  19. 底量超顶量超级大黑马指标源码_求通达信顶底趋势指标源码
  20. 计算机网络课程设计:电子政务

热门文章

  1. php jwt token过期时间,php – 动态设置laravel jwt的到期时间
  2. xp系统安装oracle乱码,linux中安装Oracle汉字乱码完整解决方案
  3. “;“分号空语句的使用
  4. win7怎么关闭虚拟机服务器,大师教您Win7系统怎么彻底关闭退出vmware虚拟机的处理要领...
  5. C 语言编程利器 之CLion
  6. GitHub开源比Hadoop快至少10倍的物联网大数据平台
  7. 0.基于C++的图像处理算法实现、INTEL CPU上SSE加速、ARM CPU上NEON加速
  8. Linux那些事儿 之 戏说USB(27)设备的生命线(十)
  9. linux下free源码,linux命令free源码解读:Procps free.c
  10. 用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值