JNI—Android Studio下的 NDK 环境配置

  • JNI与NDK的理解
    • JNI
      • 什么是JNI呢?
      • 为什么用JNI呢?
      • 怎么学JNI呢?
    • NDK
      • 什么是NDK呢?
      • 为什么用NDK呢?
      • 怎么学NDK呢?
  • JNI与NDK的开发准备
    • JNI原生开发流程(Eclipse)
      • 基本流程
      • 详细流程
      • 补充说明
    • NDK集成开发流程(Eclipse)
      • 基本流程
      • 详细流程
      • 补充说明
      • 重要配置
    • NDK集成开发流程(AS)
      • 详细流程

JNI与NDK的理解

JNI是一种协议

NDK是用来开发JNI的谷歌工具包

JNI

什么是JNI呢?

  1. Andriod系统架构(理解)
  2. 相当于桥梁的作用
    Java Native Interface: java本地开发接口
  3. 通过jni就可以让java与C/C++代码实现互调

为什么用JNI呢?

  1. native coder执行高效:大量的运算(极品飞车),万能解码(ffmpeg),Opengl(3D 渲染)
  2. 通过jni技术,可以扩展Android手机的功能-wifi热点等
  3. 代码的复用:ffmpeg,onencv(人脸识别库),7-zip
  4. 使用场景:考虑特殊情况(效率/操作硬件)

怎么学JNI呢?

  1. 学C语言-看懂代码
  2. 了解"JNI开发流程 "

NDK

编译C代码就需要用到NDK工具

什么是NDK呢?

  1. Native Develop Kits(本地开发工具包)
  2. Android提供的用来做JNI开发的工具包

为什么用NDK呢?

提高JNI开发的效率

  1. 生成代码
  2. 代码提示
  3. 多平台交叉编译

怎么学NDK呢?

 了解"NDK"开发流程

JNI与NDK的开发准备

 Android Studio下的 NDK 环境配置(两篇均可以)
 https://blog.csdn.net/weixin_42814000/article/details/105259159

 https://blog.csdn.net/weixin_42814000/article/details/105259289

 Eclipse下的 NDK 环境配置
 https://blog.csdn.net/weixin_42814000/article/details/105259122

JNI原生开发流程(Eclipse)

基本流程

  1. 在Java类中定义native方法
  2. 生成包含对应JNI函数声明的头文件
  3. 实现生成的JNI函数
  4. 借助NDK编译生成动态链接库文件(.so)
  5. 在Java类中加载动态连接库并调用native的方法
  6. 运行安装到ARM模拟器上

详细流程

  1. 在Java类中定义native方法

    在Activity类中声明: public native String helloJNI();

  2. 生成包含对应JNI函数声明的头文件

    1). 在命令行窗口中执行: javah Activity全类名(在src下执行)
    说明有的电脑可能会提示GBK的不可映射字符: 添加 -encoding utf-8

    2). 在src下会生成一个头文件: com_atguigu_hellojni_MainActivity.h

    3). 头文件中包含一个native方法对应的JNI函数声明(需要后面实现):
    JNIEXPORT jstring JNICALL Java_com_atguigu_hellojni_MainActivity_helloJNI(JNIEnv *, jobject)

  3. 实现生成的JNI函数

    1). 在应用下创建一个文件夹: jni

    2). 将刚才生成的头文件复制到此文件夹下

    3). 创建一个c文件来实现生成的JNI函数声明: test.c

 #include "com_atguigu_hellojni_MainActivity.h"JNIEXPORT jstring JNICALL Java_com_atguigu_hellojni_MainActivity_helloJNI(JNIEnv * env, jobject jobj) {return (*env)->NewStringUTF(env, "Hello from C");}
  1. 借助NDK编译生成动态链接库文件(.so)

    1). 解压NDK包, 配置NDK文件夹到path(不能包含空格)

    2). 借助NDK下的文档(ANDROID-MK.html)编写用于编译的文件(jni/Android.mk)

 LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := hello-jni #指定生成的so文件的唯一标识LOCAL_SRC_FILES := test.c  #指定包含JNI函数的c文件名include $(BUILD_SHARED_LIBRARY)

3). 在命令行窗口中进入应用根目录, 执行ndk-build命令, 生成so动态链接库文件

 so文件路径: /libs/armeabi/libhello-jni.so

  1. 在Java类中加载动态连接库并调用native的方法
    1). 在静态代码块中加载so文件:

     static {System.loadLibrary("hello-jni");}
    

2). 调用native方法:

String result = helloJNI();
  1. 运行安装到ARM模拟器上

补充说明

  1. JNIEXPORT :

    在Jni编程中所有本地语言实现Jni接口的方法前面都有一个"JNIEXPORT",这个可以看做是Jni的一个标志,至今为止没发现它有什么特殊的用处。

  2. JNICALL :

    这个可以理解为Jni 和Call两个部分,和起来的意思就是 Jni调用XXX(后面的XXX就是JAVA的方法名)。

NDK集成开发流程(Eclipse)

基本流程

  1. 安装配置NDK
  2. 将NDK关联到eclipse
  3. 为当前应用自动生成c文件和mk文件
  4. 定义naitve方法
  5. 实现native方法对应的JNI函数
  6. 一键编译生成so文件
  7. 加载动态库, 并调用native方法
  8. 运行应用安装到ARM模拟器上

详细流程

  1. 安装配置NDK

    1). 解压NDK的zip包到非中文目录

    2). 配置path : 解压后NDK的根目录----->ndk-build

  2. 将NDK关联到eclipse

    Window–>Preferences–>Android–>NDK–>配置NDK的根目录

  3. 为当前应用自动生成c文件和mk文件

    1). 选中当前应用右键–>Android Tools–>Add Native Support

    2). 将生成的.cpp文件改为.c文件

    3). 修改mk文件: 将.cpp改为.c

  4. 配置关联jni.h (见"配置关联jni.h文件"截图)

    1). 选中当前应用右键–>Properties–>C/C++ General–>Paths and Symbols

    2). 选择add–>选择File System–>选择文件夹android-ndk-r9\platforms\android-18\arch-arm\usr\include

    3). 点击ok–>点击apply

  5. 定义naitve方法

    public native String helloNDK();

  6. 实现native方法对应的JNI函数

    1). 使用javah命令, 生成JNI头文件, 将其复制到jni文件下

    2). 在c文件中实现h文件中的函数声明

    3). 利用* 的NewStringUTF()函数, 返回字符串

  7. 一锤编译生成so文件

    1). 使用工具栏中的"Build"工具点击锤子按钮生成

    2). 文件路径: /libs/armeabi/libNDKTest.so

  8. 加载动态库, 并调用native方法

static {System.loadLibrary("NDKTest");}String result = helloNDK();
  1. 运行应用安装到ARM模拟器上

补充说明

  1. 修改C函数, 不需要再单独编译生成so文件, 可直接运行安装

  2. APK只是将so打包了, 本质并不需要jni文件夹下的相关文件

  3. 多平台交叉编译
    1、 arm
    2、 intel
    3、 mips

  4. Android.mk详细介绍

      #必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件#宏函数’my-dir’,由编译系统提供,用于返回当前路径(包含c/c++文件)LOCAL_PATH := $(call my-dir)#清除除LOCAL_PATH之外的LOCAL_XXX变量#CLEAR_VARS由编译系统提供include $(CLEAR_VARS)#以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的#编译会产生的链接库文件(lib+名称+.so): libtest2-jni.soLOCAL_MODULE := test2-jni#指定将要编译打包进模块中的C或C++源代码文件#如果有多个, 以空格隔开LOCAL_SRC_FILES := test2.c#编译生成动态库(也就是.so文件)include $(BUILD_SHARED_LIBRARY)#编译生成静态库(也就是.a文件)#include $(BUILD_STATIC_LIBRARY)
    

重要配置

  1. 编写Android.mk

  2. 配置关联jni.h文件

  3. 编写Application.mk

NDK集成开发流程(AS)

详细流程

  1. 安装配置NDK
    1).
    https://github.com/inferjay/AndroidDevTools
    根据自己的系统选择

    2). 解压NDK的zip包到非中文目录

    注意文件夹名字不能有空格

    3). 配置Path环境变量 : 解压后NDK的根目录----->ndk-build


    然后点击环境变量(建议配置在上面 用户变量,因为如果配置在系统变量的话,如果有一天你删除了系统变量的,那么会导致系统用不了,如果配置在用户变量,要进行删除时,如果用不了,只用重新创建一个用户就可以了,电脑还是可以使用。)

    配置Path的原因就是可以通过cmd操作命令

    如果没有配置Path,不会弹出下面的信息,它会说命令没有被找到

  2. 给AS配置关联NDK

    1). local.properties中添加配置

     ndk.dir=G\:\\android-ndk-r10(=号后面为ndk的解压路径)
    


2). gradle.properties中添加配置

兼容老的ndk(老的版本):android.useDeprecatedNdk=true

 android.useDeprecatedNdk=true
  1. 编写native方法:
 public class JNIS {public native String helloJNI();}
  1. 定义对应的JNI

    1). 在main下创建jni文件夹

    2). 生成native方法对应的JNI函数声明头文件: 命令窗口中, 进入java文件夹

         执行命令: javah com.atguigu.jnitests2.JNIS生成头文件: com_atguigu_jnitests2_JNIS.h函数声明: JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI(JNIEnv *, jobject);
    

    3). 将生成的头文件转移到jni文件夹下

    4). 在jni下定义对应的函数文件: test.c

     #include "com_atguigu_jnitests2_JNIS.h"JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI(JNIEnv * env, jobject jobj) {return (*env)->NewStringUTF(env, "Hello from C");}
    

    5). 在jni文件夹下创建一个空的C文件: empty.c

     说明: 这是AS的bug, 必须至少2个C文件才能通过编译
    
  2. 指定编译的不同CPU

     defaultConfig {ndk{moduleName "HelloJni" //so文件: lib+moduleName+.soabiFilters "armeabi", "armeabi-v7a", "x86" //cpu的类型}}
    
  3. 编译生成不同平台下的动态链接文件

    1). 执行rebuild, 生成so文件

    2). so文件目录: build\intermediates\ndk\debug\lib…

  4. 调用native方法:

    1). 在native方法所在的类中加载so文件

         static {System.loadLibrary("HelloJni");}
    

    2). 在Activity中调用native方法:

      String result = new JNIS().helloJNI();Log.e("TAG", "result="+result);
    

NDK 环境配置看这篇就够了!相关推荐

  1. macOS 上的 Charles 配置看一篇就够了

    2021.11.9 更新,新增 iOS 模拟器抓取 Https 报文的配置方法. 文章目录 1. Charles 简介 2. Charles 工作原理 3. 组件介绍 4. macOS 代理设置 5. ...

  2. NDK撩妹三部曲(四)—NDK 开发如何优雅的定位 Native 异常,看这篇就够了

    NDK 开发如何优雅的定位 Native 异常,看这篇就够了 从何说起? 摘要 案例实操 aaddr2line objdump ndk-stack 1.假设我们已经通过 adb logcat 拿到了程 ...

  3. React入门看这篇就够了

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 很多值得了解的细节. 原文:React入门看这篇就够了 作者:Random Fundebug经授权转载,版权归原作者所 ...

  4. .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core.既 ...

  5. [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了

    园子里关于ASP.NET Core Web API的教程很多,但大多都是使用EF+Mysql或者EF+MSSQL的文章.甚至关于ASP.NET Core Web API中使用Dapper+Mysql组 ...

  6. Spring Cloud入门,看这篇就够了!

    点击▲关注 "中生代技术"   给公众号标星置顶 更多精彩 第一时间直达 概述 首先我给大家看一张图,如果大家对这张图有些地方不太理解的话,我希望你们看完我这篇文章会恍然大悟. 什 ...

  7. Docker入门实战看这篇就够了(最新详细以及踩过的坑)

    Docker入门实战看这篇就够了 前言 初识 是什么 容器与虚拟机 能干什么 去哪玩 安装 先决条件 查看自己的内核 安装所需的软件包(支持devicemapper存储类型) 设置镜像的仓库 设置yu ...

  8. groovy if 判断字符串_Groovy快速入门看这篇就够了

    原标题:Groovy快速入门看这篇就够了 来自:刘望舒(微信号:liuwangshuAndroid) 前言 在前面我们学习了和两篇文章,对Gradle也有了大概的了解,这篇文章我们接着来学习Groov ...

  9. [个人向]超快速了解微信小程序:看这篇就够了!(注册、语言、框架、配额等简要说明)

    [个人向]超快速了解微信小程序看这篇就够了+相关简要说明 本文精炼微信小程序开发文档相关内容,旨在对初次接触并准备开发小程序的童鞋(比如自己)提供一个快速了解攻略.其中包括注册相关.语言.框架模式.相 ...

最新文章

  1. [原创]CentOS下Mysql双机互为备份
  2. 史上最受程序员待见的计算机入门读物——图解X系列
  3. R语言如何画个性化词云图
  4. python 读写utf8文件_Python关于 文件读写的总结
  5. vue项目将token存在(vuex)store和localstorage中
  6. html文档的文件头的主要作用是什么,文件头
  7. java中存在对多个对象加锁的情况_Java对象锁和类锁全面解析(多线程synchronized关键字)...
  8. [转载] java(三)对象的序列化与static、final关键字
  9. html阴影 渐变,CSS3:图层阴影及渐变
  10. mysql导出数据大概得多久_MySQL 导出数据
  11. 鼎立测试软件能锁网吗,路测软件鼎利通信Pioneer操作培训PPT(ET128).ppt
  12. PostmanCn: Postman中文版
  13. O2O模式成功案例分享 汲取精华化为己用
  14. android字体大小根据分辨率自动调整
  15. 强制双休!腾讯调整加班机制,21 点前必须离开工位
  16. es6根据对象属性获取到当前值的下标
  17. MySQL、PostgreSQL、NoSQL、CynosDB,究竟谁是数据库王者?
  18. Away3d粒子系统位置初始化
  19. 汇量科技蔡超:提高云使用率是云计算市场的下一个增长点
  20. 计算机人文素养教案,小学信息技术课堂中人文素养的教学探究

热门文章

  1. jupyter中更换工作目录最简单方式
  2. 003 matlab-反三角函数
  3. 彭罗斯阶梯(Penrose stairs
  4. 关于右下角广告弹窗的解决方案_小黄鸭
  5. 凌玮科技将在创业板上市:预计募资净额约8亿元,曾踩雷民生理财
  6. 泰森︱用拳击的眼光认识身体各部位的作用
  7. 完美解决Sqlite数据库版本过期解决方法
  8. Mrakdown学习
  9. java解析excel的js页面,JavaScript_通过Javascript读取本地Excel文件内容的代码示例,读取本地Excel文件内容的Javascri - phpStudy...
  10. 字符集和数据库的维护