JNI - CMake 的 demo

369 阅读1分钟

目标是 java 层通过 jni 调用拿到一个 cpp 层返回的 string。

开始。

第零步,配置好 ndk 等

去官方下载 ndk,目前最新版是 r21b;然后放到合适位置;
回到 Androidstudio,打开 local.properties 文件,加上 ndk 的路径;

ndk.dir=/Users/xxx/Library/android-ndk-r21b
sdk.dir=/Users/xxx/Library/Android/sdk

第一步,先建一个 cpp 目录,在 java 的同级目录下

  • /app/src/main/java(这下面是java文件)
  • /app/src/main/cpp(在这下面建cpp文件)
// 新建 native_test.cpp 文件

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

// 需要绑定一个 java 类
#define JNI_CLASS_PATH "com/anything/sample/CppActivity"

extern "C" JNIEXPORT jstring JNICALL
//Java + 包名 + 类名 + 函数名
Java_com_anything_sample_CppActivity_stringFromJNI(
        JNIEnv *env,
        jobject ) {

    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());

}

注意函数名要和调用的Java类格式对上。

第二步,编写 cmake 脚本文件

  • /app 路径下,新建 CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.4.1)

# 引入cpp源文件
add_library( 
        native-lib # so 名
        SHARED
        src/main/cpp/native_test.cpp)
        
# 引入系统库
find_library(
        log-lib # 别名
        log) # 原生的ndk的log库

# 链接起来
target_link_libraries(
        native-lib
        ${log-lib})   

第三步,build_gradle 中引入 cmake

  • 在 app 模块的 build_gradle 中的 android 块下,增加:
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
  • 然后在 android 块中的 defaultConfig 块下,增加参数配置:
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }

第四步,调用

public class MainActivity extends AppCompatActivity {

    // 加载
    static {
        System.loadLibrary("native-lib");
    }
    
    // 声明
    public native String stringFromJNI();
    
    // 调用
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = (TextView) findViewById(R.id.sample_text);
        String hello = stringFromJNI();
        tv.setText(hello);
    }

第五步,编译执行

小结

该中方法,比 ndk-build 的当时简洁很多,

  • 免去了 头文件的编写
  • 免去了 Android.mk 文件的编写
  • 免去了 单独编译 so 文件的流程
  • cpp 引入头文件的写法,比较复杂