JNI开发与NDK开发的基本流程

上一篇文章主要讲解有关JNI和NDK开发过程中需要理解的基本的知识,想要了解的,请移步https://blog.csdn.net/qq_36451275/article/details/95347000

开发:

一、JNI原生开发流程(Eclipse)

   (1)基本流程

       1.在java类中定义native方法

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

       3.实现生成的JNI的函数

       4.借助NDK编译生成动态链接库文件(.so)

       5. 在Java类中加载动态连接库并调用native的方法

       6. 运行安装到ARM模拟器上

(2)详细流程

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");

}

4. 借助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

5. 在Java类中加载动态连接库并调用native的方法

1). 在静态代码块中加载so文件:

static {

System.loadLibrary("hello-jni");

}

2). 调用native方法:

String result = helloJNI();

6. 运行安装到ARM模拟器上

(3)补充说明

JNIEXPORT :

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

JNICALL :

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

二、NDK集成开发流程(Eclipse)

  (1)基本流程

   1. 安装配置NDK

   2. 将NDK关联到eclipse

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

   4. 定义naitve方法

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

   6. 一锤编译生成so文件

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

   8. 运行应用安装到ARM模拟器上

(2)详细流程

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();

9. 运行应用安装到ARM模拟器上

(3)补充说明

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

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

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

1>. 参照NDK文档: APPLICATION-MK.html

2>. 在jni文件夹下创建: Application.mk

APP_ABI := all

3>. 编译时会生成多个so文件来支持不同类型的CPU

4>. 不同CPU的说明

armeabi: 是指的该so库用于ARM的通用CPU,armeabi通用性强,但速度

armeabi-v7a: CPU支持硬件浮点运算, 能充分发挥v7a CPU的能力,

x86: 用于Intel的CPU

mips : 另一种CPU, 用得特别少

   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)

(4)重要配置

   1.编写Android.mk

   2.配置关联jni.h文件

 

 

 

 

 

 

   3.编写Application.mk

三、NDK集成开发流程(Android Studio)

1. 安装配置NDK

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

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

 

2. 给AS配置关联NDK

1). local.properties中添加配置

ndk.dir=G\:\\android-ndk-r10

2). gradle.properties中添加配置

android.useDeprecatedNdk=true

 

3. 编写native方法:

public class JNIS {

public native String helloJNI();

}

 

4. 定义对应的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文件才能通过编译

 

5. 指定编译的不同CPU

defaultConfig {

ndk{

moduleName "HelloJni" //so文件: lib+moduleName+.so

abiFilters "armeabi", "armeabi-v7a", "x86" //cpu的类型

}

}

6. 编译生成不同平台下的动态链接文件

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

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

7. 调用native方法:

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

static {

System.loadLibrary("HelloJni");

}

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

String result = new JNIS().helloJNI();

Log.e("TAG", "result="+result);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值