JNI 基础- 使用 JNI 实现 Hello,World

字数 570阅读 15

前言

结束了第一阶段 C++ 基础,接下来开始 JNI 基础的学习,经过对 JNI 学习资料的筛选,最后选中了
南洋理工大学 JNI 教程,课程内容全英文的,刚好拿来锻炼一下阅读能力

由于 Java 基于虚拟机运行,有跨平台的优点,而原生代码没有这一特性,所以我们要根据手机 cpu 类型来制作对应的库文件,Android 端常见的平台类型有 arm64-v8a,armeabi,armeabi-v7a,mips,mips64,x86,x86_64

相关链接

深入理解 System.loadLibrary

南阳理工大学 JNI 教程

android lib下不同的cpu类型

Android NDK开发扫盲及最新CMake的编译使用

如何在已有项目中进行NDK开发

调用 native 代码

在 JNI 代码中我们经常看到 System.loadLibrary 语句,这句话的含义是 Java 代码调用动态链接库,其实内部进行了方法指针强制转换等一系列操作,因为 Android 基于 Linux 内核,loadLibrary 内部封装的就是 Linux 平台加载 so 动态库文件的代码,网上有大神对 loadLibrary 源代码进行了分析.

深入理解 System.loadLibrary

JNI 的开发流程

  1. 使用 Java 编写声明 Native 方法的类
  2. 将 Class 文件编译成字节码
  3. 使用 javah -jni 指令生成 .h 头文件
  4. 使用 C/C++ 代码实现定义的方法
  5. 生成 so 动态库文件(windows 平台生成 dll,linux/unix 生成 so,macOs 生成 jniLib)
  6. Java 代码使用 so 动态库

Hello,Word 程序

NDK 的环境配置在网上一搜一大把,需要下载 LLDS,NDk 和 Cmake 工具,我们再这里就不做详细说明了.

  • 定义 native 方法

首先创建 java 文件,定义原生代码的方法名以及返回值

/**
 * @author : kai.mao
 * @date :  2019/8/5
 */
public class JniUtil {

    // 定义 native 方法
    public native String sayHelloWorld();

    // 加载 so 动态库文件
    static {

        System.loadLibrary("HelloWord");

    }

}

  • 使用 javah 指令生成 .h 头文件

在 Terminal 中首先 cd 到该 java 所在的文件夹,然后使用 javah

// 需要相对路径
D:\TopAndroid\HelloJNI\app\src\main\java>javah com.bailun.kai.hellojni.JniUtil

生成如下文件,并将该文件放到 main/cpp 文件夹中

image.png
  • 根据头文件编写 cpp 文件

在 cpp 下新建 xxx.cpp 文件,代码如下:

//
// Created by Admin on 2019/8/5.
//


#include "com_bailun_kai_hellojni_JniUtil.h"

JNIEXPORT jstring JNICALL Java_com_bailun_kai_hellojni_JniUtil_sayHelloWorld
  (JNIEnv *env, jobject){


      return env->NewStringUTF("Hello,World!");
  }


  • 创建 CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.4.1)


add_library( # Specifies the name of the library.
# 这里是你so的名字。
             HelloWord

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
              #这里是刚才 创建的c++ 代码的名字
             src/main/cpp/HelloWorld.cpp )

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.
# 这里是你so的名字。

                       HelloWord

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

  • 生成 so 文件

使用 As Build 项目后,可在 cmake 目录下看到生成的 so
文件

image.png

最终结果

image.png

推荐阅读更多精彩内容