Android JNI NDK 开发

Android 开发过程中必然会涉及 JNI 与 NDK 开发,简单梳理下 JNI 流程

开发环境:Android Studio 3.3 、CMake :3.10 、NDK:19 ,LLDB:3.1

Android JNI NDK 开发_第1张图片
image.png

Android Studio 新建工程:
New Project → Native C++ → C++ Standard

默认已经搭建好 JNI 模板 Hello from C++

CMakeList.txt

# 有关使用CMake在Android Studio的更多信息,请阅读文档:https://d.android.com/studio/projects/add-native-code.html

# 设置CMake的最低版本构建本机所需库
cmake_minimum_required(VERSION 3.4.1)

# 创建并命名库,将其设置为静态的
# 或共享,并提供其源代码的相对路径。
# 你可以定义多个library库,并使用CMake来构建。
# Gradle会自动将包共享库关联到你的apk程序。

add_library( # 设置库的名称
             native-lib
             # 将库设置为共享库。
             SHARED
             # 为源文件提供一个相对路径。
             src/main/cpp/native-lib.cpp )
# 搜索指定预先构建的库和存储路径变量。因为CMake包括系统库搜索路径中默认情况下,只需要指定想添加公共NDK库的名称,在CMake验证库之前存在完成构建
find_library( # 设置path变量的名称
              log-lib
              # 在CMake定位前指定的NDK库名称
              log )
# 指定库CMake应该链接到目标库中,可以链接多个库,比如定义库,构建脚本,预先构建的第三方库或者系统库
target_link_libraries( # 指定目标库
                       native-lib
                       # 目标库到日志库的链接 包含在NDK
                       ${log-lib} )

native-lib.cpp

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

MainActivity 中使用 JNI 接口

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

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

编译 C++ 代码到 APP 的流程

  1. Gradle 调用外部构建脚本,CMakeLists.txt;
  2. CMake 根据构建脚本指令去编译一个 C++源文件,native-lib.cpp,编译后的产物扔进共享对象库中,并将其命名为libnative-lib.so,然后 Gradle 将其打包到 APK 中;
  3. 运行期间,app 的 MainActivity 会调用System.loadLibrary() 方法,加载 native library,而这个库的原生函数 stringFromJNI()

原项目基础上添加自己的代码

添加 getHelloJni() 接口

public class NativeUtils {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
    
    public native String stringFromJNI();

    public native String getHelloJni();
}


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

extern "C"
JNIEXPORT jstring JNICALL
Java_com_apple_jnisample03_NativeUtils_getHelloJni(
        JNIEnv *env,
        jobject instance
        ){

    return env->NewStringUTF("Hello Jni,欢迎使用 JniSample Hello World");
}

编译打包的 libnative-lib.so 路径

buildintermediatescmakedebug(release)obj*libnative-lib.so

使用已经编译好的 *.so 文件,JNI 调用 so 文件。

main 目录下新建文件夹jniLibs「注意」:文件夹名字大小写不能变。

so 文件中 Java_com_apple_jnisample_NativeUtils_getHelloJni()方法,则需建立对应包名com.apple.jnisample.NativeUtils.java 中 System.loadLibrary("native-lib");「去掉库文件的前缀 lib 以及后缀.so」
声明需要使用的方法即可;

你可能感兴趣的:(Android JNI NDK 开发)