前提:Android Studio 3.0,预先通过SDK Manager安装好CMake(生成so库的编译相关工具),3.6.4版
- 定义一个Java类,其中定义native方法,并调用System.loadLibrary加载so库
public class TestJni {
static {
System.loadLibrary("test-jni");
}
public static native String getStringFromNativeMethod();
}
测试调用的例子:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// call native method, LogUtils是封装的Log类
LogUtils.d("print: " + TestJni.getStringFromNativeMethod());
}
}
- 通过javah指令生成C/C++头文件.h
sudo javah -jni com.kevin.test.TestJni
生成的头文件名称:com_kevin_test_TestJni.h,内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_kevin_test_TestJni */
#ifndef _Included_com_kevin_test_TestJni
#define _Included_com_kevin_test_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_kevin_test_TestJni
* Method: getStringFromNativeMethod
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_kevin_test_TestJni_getStringFromNativeMethod
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
注意,javah前:
a. 需要先make project一次,生成TestJni.class文件
b. 先cd至命令执行的路径:app/build/intermediates/classes/debug,否则会找不到TestJni.class
- 复制头文件至源代码路径下面,例如:app/src/main/jni,并新建一个cpp文件,名字:com_kevin_test_TestJni.cpp,完成函数getStringFromNativeMethod的C++定义,如下:
#include "com_kevin_test_TestJni.h"
JNIEXPORT jstring JNICALL Java_com_kevin_test_TestJni_getStringFromNativeMethod
(JNIEnv *env, jclass thiz) {
return (*env).NewStringUTF("this is c++ code");
}
注意:
这里C/C++都可以,C的source文件结尾为.c,C++的source文件结尾为.cpp,但是语法实现时不能有错,否则编译时会报错。这里选用C++
- Java代码,C++代码都准备完成后,这时要准备编译C++的CMakeList.txt,新建即可。作用是CMake工具的配置文件,必不可少。简单配置如下:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Specifies the name of the library.
test-jni
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
com_kevin_test_TestJni.cpp )
注意:这里定义了编译生成的库文件名字,test-jni,编译完成后,文件名称为:libtest-jni.so。
- 更新app下build.gradle文件,添加Cmake相关信息
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' // 定义编译的ABI类型,每种会编译生成一个对应的so库文件
}
}
}
...
externalNativeBuild {
cmake {
path 'src/main/jni/CMakeLists.txt'
}
}
}
- 重新编译新的Project,并安装至手机,运行。此时打印的日志:
12-03 18:47:03.636 9016 9016 D kevintest: print: this is c++ code
说明Activity运行时,调用native方法getStringFromNativeMethod成功,方法实现在libtest-jni.so库中。另外,可以通过Build->Anaylze APK,查看apk中,lib路径下已打包4个libtest-jni.so库,分别存放至arm64-v8a等文件夹下,提供不同的ABI支持
最后,附上示例Project结构的截图:
参考文档:https://developer.android.com/studio/projects/add-native-code#create-cmake-script
作者:kevin song,2018.12.3于南京建邺区