NDK 环境配置看这篇就够了!

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.so
    
     	LOCAL_MODULE := test2-jni
    
    
     	#指定将要编译打包进模块中的C或C++源代码文件
    
     	#如果有多个, 以空格隔开
    
     	LOCAL_SRC_FILES := test2.c
    
    
     	#编译生成动态库(也就是.so文件)
    
     	include $(BUILD_SHARED_LIBRARY)
    
    
     	#编译生成静态库(也就是.a文件)
    
     	#include $(BUILD_STATIC_LIBRARY)
    
重要配置
  1. 编写Android.mk
    编写Android.mk

  2. 配置关联jni.h文件
    配置关联jni.h文件

  3. 编写Application.mk
    编写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+.so
    
     	abiFilters "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);
    
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值