Android

Android NDK(一)- 认识 NDK

2022-06-18  本文已影响0人  teletian

JNI 简介

在讲 NDK 之前,先要搞清楚什么是 JNI。

定义:Java Native Interface,即 Java 本地接口。
作用: 使得 Java 与本地其他类型语言(如 C、C++)交互。也就是在 Java 中调用 C/C++ 代码,或者在 C/C++ 中调用 Java 代码。

注意,JNI 是 Java 的,和 Android 无关。

NDK 简介

定义:Native Development Kit,是 Android 的一个工具开发包。

那到底 JNI 和 NDK 有什么区别呢?
NDK 可以看做是 Android 中实现 JNI 的一种手段,通过 NDK,还可以打包 C/C++ 动态库,并自动打包进 APK/AAR 中。

最简单的 NDK 项目

Android Studio 新建项目的时候可以选择各种各样的模板,选择 Native C++ 模板就可以创建一个简单的 NDK 项目。

在 app/src/main/cpp 下可以看到有 CMakeList.txt 和 native-lib.cpp。
native-lib.cpp 里面是原生代码。
CMakeList.txt 是 CMake 构建脚本,用于把原生代码构建入库。

CMakeList.txt

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.

project("myndk")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        myndk

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

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)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        myndk

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

CMakeList 的具体解释可以见注释部分。

native-lib.cpp

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_teletian_sample_myndk_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

一个简单的 C++ 方法,返回一个 Hello from C++ 的字符串。

这边还导入了一个头文件 jni.h,jni.h 中定义了 JNI 的数据类型、数据结构、接口函数、回调函数以及常量等等。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    // Used to load the 'myndk' library on application startup.
    static {
        System.loadLibrary("myndk");
    }

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Example of a call to a native method
        TextView tv = binding.sampleText;
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'myndk' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

Java 中定义和 Java_com_teletian_sample_myndk_MainActivity_stringFromJNI 相对应的方法 stringFromJNI。
在使用之前,需要提前加载 CMakeList 中定义的 myndk 动态库。

app 下的 build.gradle 文件设置如下:

android {

    defaultConfig {

        externalNativeBuild {
            cmake {
                // 支持 c++11
                cppFlags '-std=c++11'
                // 需要运行的 CPU 类型
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
            }
        }
    }
    
    // 指定 CMake 文件路径和版本 
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.18.1'
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读