JNI和NDK简单入门

文章目录

      • 一、简介
      • 二、为什么要使用NDK
      • 三、使用NDK编译代码主要有三种方法
      • 四、搭建环境
        • 1、下载ndk-build和CMake
        • 2、配置ndk-build环境变量
        • 3、验证ndk-build环境变量是否正确
      • 五、第一种方法使用基于Make的ndk-build方法生成.so库
        • 1、新建一个java工具类用于加载.so库并定义native方法
        • 2、在main目录下新建一个jni目录用于存放一些jni配置文件和jni代码,然后再jni目录新建一个Application.mk配置文件目录结构如下图所示
        • 3、在jni目录中新建Android.mk配置文件
        • 4、在jni目录中新建test.c源文件(C语言源文件.c后缀结尾,C++源文件.cpp结尾)
        • 5、到2步骤新建的jni目录下执行ndk-build的目录即可生成so库文件
        • 6、java代码进行调用so库文件中的方法
      • 六、第二种使用CMake进行jni编程
        • 1、新建一个java工具类用于加载.so库并定义native方法
        • 2、在main目录下新建cpp目录用于存放CMakeLists.txt配置文件和test.c源文件如下图所示
        • 3、在cpp目录下新建test.c源文件(C语言源文件.c后缀结尾,C++源文件.cpp结尾)
        • 4、在build.gradle文件中对CMake进行配置
        • 5、在代码中调用so库

一、简介

  • Android NDK 是一套允许您使用 C 和 C++ 等语言,以原生代码实现部分应用的工具集。在开发某些类型的应用时,这有助于您重复使用以这些语言编写的代码库。

二、为什么要使用NDK

  • 利用Java代码开发的打包生成的apk容易被反编译,安全性不高,而利用ndk开发的库不容易被反编译,保密性好,安全性高
  • C和C++的运行速度和效率都比java快。
  • 现如今很多开源工程都是C和C++的代码,要你去重复造轮子,用Java实现这些功能显然是不可能的,这就必须使用JNI技术。

三、使用NDK编译代码主要有三种方法

  • 基于Make的ndk-build
  • CMake
  • 独立工具链,用于与其他编译系统集成,或基于configure的项目搭建使用
    本篇博客主要介绍几于Make的ndk-build和Cmake方法

四、搭建环境

1、下载ndk-build和CMake

JNI和NDK简单入门_第1张图片

2、配置ndk-build环境变量

JNI和NDK简单入门_第2张图片

3、验证ndk-build环境变量是否正确

JNI和NDK简单入门_第3张图片

五、第一种方法使用基于Make的ndk-build方法生成.so库

1、新建一个java工具类用于加载.so库并定义native方法

	package com.excellence.testjni;
	
	/**
	 * @author weijingsong
	 * @date 2020/3/4
	 */
	public class TestJni {
	    static {
	        System.loadLibrary("Test");
	    }
	
	    public static native void setStringToJni(String str);
	    public static native String getStringFromJni();
	}

其中 System.loadLibrary(“Test”);表示加载名字为libTest.so的so库,最后两行定义了两个native方法

2、在main目录下新建一个jni目录用于存放一些jni配置文件和jni代码,然后再jni目录新建一个Application.mk配置文件目录结构如下图所示

JNI和NDK简单入门_第4张图片

  • Application.mk配置信息如下
APP_PLATFORM := android-19
APP_ABI :=  armeabi-v7a arm64-v8a
APP_CFLAGS += -DSTDC_HEADERS

其中APP_PLATFORM表示编译平台,APP_ABI 表示CPU架构类型,目前主流的有armeabi armeabi-v7a arm64-v8a

3、在jni目录中新建Android.mk配置文件

	LOCAL_PATH := $(call my-dir)
	include $(CLEAR_VARS)
	
	LOCAL_MODULE := Test
	LOCAL_SRC_FILES := test.c
	
	LOCAL_LDLIBS += -llog
	
	include $(BUILD_SHARED_LIBRARY)

其中LOCAL_PATH 表示模块名,LOCAL_MODULE表示生产的so库名称会自带lib前缀,LOCAL_SRC_FILES 表示参与编译的源文件,如果有多个源文件可以往变量后面继续添加

4、在jni目录中新建test.c源文件(C语言源文件.c后缀结尾,C++源文件.cpp结尾)

#include 
#include 
 char *helloStr = "";
JNIEXPORT jstring JNICALL Java_com_excellence_testjni_TestJni_getStringFromJni(JNIEnv *env, jobject thiz)
{
    return (*env)->NewStringUTF(env, helloStr);
}

JNIEXPORT void JNICALL Java_com_excellence_testjni_TestJni_setStringToJni(JNIEnv *env, jobject thisz, jstring jstr) {
    helloStr = (*env)->GetStringUTFChars(env,jstr, NULL);
}






代码解释如下图所示
JNI和NDK简单入门_第5张图片

5、到2步骤新建的jni目录下执行ndk-build的目录即可生成so库文件

JNI和NDK简单入门_第6张图片
到此为止基于Make的ndk-build生成so库方法如上所以

6、java代码进行调用so库文件中的方法

JNI和NDK简单入门_第7张图片

  • 上图在build.gradle文件中添加打包时加载so库路径,并且在java中进行调用native方法与运行效果如下图
    JNI和NDK简单入门_第8张图片
    JNI和NDK简单入门_第9张图片

六、第二种使用CMake进行jni编程

  • CMake是一种跨平台的免费开源软件工具,用于使用与编译器无关的方法来管理软件的构建过程。 它支持依赖于多个库的目录层次结构和应用程序。 它与本机构建环境(例如Make,Qt Creator,Ninja,Apple的Xcode和Microsoft Visual Studio)结合使用。 它具有最小的依赖关系,仅需要在其自己的构建系统上使用C ++编译器。
  • 优点:
    1.在Android Studio中使用Cmake相对ndk-build不用自己去手动编译库文件。
    2.能够实现代码的跳转。
    3.Alt+Enter 一键生成本地接口方法。

1、新建一个java工具类用于加载.so库并定义native方法

	package com.excellence.testjni;
	
	/**
	 * @author weijingsong
	 * @date 2020/3/4
	 */
	public class TestJni {
	    static {
	        System.loadLibrary("Test");
	    }
	
	    public static native void setStringToJni(String str);
	    public static native String getStringFromJni();
	}

其中 System.loadLibrary(“Test”);表示加载名字为libTest.so的so库,最后两行定义了两个native方法

2、在main目录下新建cpp目录用于存放CMakeLists.txt配置文件和test.c源文件如下图所示

JNI和NDK简单入门_第10张图片

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             Test

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
            test.c)

find_library( # Sets the name of the path variable.
             log-lib

             # Specifies the name of the NDK library that
             # you want CMake to locate.
             log )

target_link_libraries( # Specifies the target library.
             Test

             # Links the target library to the log library
             # included in the NDK.
             ${log-lib} )

CMakeLists.txt内容如上所示,其中test代表的是so库名称,test.c表示参与编译的源文件

3、在cpp目录下新建test.c源文件(C语言源文件.c后缀结尾,C++源文件.cpp结尾)

···
#include
#include
char *helloStr = “”;
JNIEXPORT jstring JNICALL Java_com_excellence_testjni_TestJni_getStringFromJni(JNIEnv *env, jobject thiz)
{
return (*env)->NewStringUTF(env, helloStr);
}

JNIEXPORT void JNICALL Java_com_excellence_testjni_TestJni_setStringToJni(JNIEnv *env, jobject thisz, jstring jstr) {
    helloStr = (*env)->GetStringUTFChars(env,jstr, NULL);
}

···

4、在build.gradle文件中对CMake进行配置

JNI和NDK简单入门_第11张图片

5、在代码中调用so库

JNI和NDK简单入门_第12张图片

  • CMake中途不产生so库文件,但是编译apk的时候会把so库打包如apk,下图是运行效果和apk中的so库图

    JNI和NDK简单入门_第13张图片

JNI和NDK简单入门_第14张图片

你可能感兴趣的:(jni,and,ndk,android)