第一步生成静态库.a文件:
cmake 语法如何生成静态库,就不介绍了,比较简单,我下文列出的参考资料里面有详细介绍。
java
add_library(${CMAKE_PROJECT_NAME} STATIC
src/CalculStatic.cpp
)

这一步有坑,我刚开始的时候,也花了不少时间,死活都没有生成.a静态库文件。但是我多方查找资料,发现是可以生成静态库文件的。关键是要配置"targets" 。这个属性只有在" defaultConfig" 下面才能配置出来,在大括号"android "下面配置的"cmake "是没有"targets"这个属性的,我就是因为在此耽搁了不少时间。一定要谨慎。
正确的build.gradle配置如下:
c
android {
defaultConfig {
:
externalNativeBuild {
cmake {
targets "calStatic" // New line here!
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
// targets "native-lib" // Not here!
}
}
}
重新运行项目或者"Make Project". 重新刷新目录,静态库.a文件就可以正确生成了。
参考资料:
android studio生成静态库没有*.a目标文件问题
android studio 3.2 使用cmake在jni生成及使用C/C++静态库
第二步使用静态库.a文件:
限制我们需要来调用我们刚刚生成的静态库.a文件

CMakeLists.txt
c
cmake_minimum_required(VERSION 3.22.1)
project("cmake")
add_library(${CMAKE_PROJECT_NAME} SHARED
native-lib.cpp
src/libtest.c
)
#导入已经编译好的静态库 或者 动态库 本例导入的静态库
add_library(calStatic STATIC IMPORTED)
#设置静态库导入的路径
set_target_properties(calStatic PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/jni/${CMAKE_ANDROID_ARCH_ABI}/libcalStatic.a
)
#通过target_link_libraries命令指明库文件,且通过target_include_directories命令指明相应的库头文件
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include/static/)
#需要链接或者编译的库
target_link_libraries(${CMAKE_PROJECT_NAME}
# List libraries link to the target library
android
calStatic
log)
native-lib.cpp
c
#include "CalculStatic.h"
//调用了libcalStatic.a静态库中的方法
jint addSum(JNIEnv *env,jobject instance,jint a,jint b,jint c){ //调用静态库
return calculAdd(a,b,c);
//动态注册
jint RegisterNatives(JNIEnv *env) {
jclass clazz = env->FindClass("com/gitbaike/cmake/MainActivity");
if (clazz == NULL) {
LOGE("con't find class: com/gitbaike/cmake/MainActivity");
return JNI_ERR;
}
JNINativeMethod methods_MainActivity[] = {
{"stringFromJNI", "()Ljava/lang/String;", (void *) stringFromJNI},
{"add", "(II)I", (void *) add},
{"changePersonName", "(Lcom/gitbaike/cmake/model/Person;)V",(void *) changeName},
{"getPerson", "()Lcom/gitbaike/cmake/model/Person;",(void *)getNewPerson},
{"getPeronList", "()Ljava/util/List;",(void *) getListPerson},
{"addSum", "(III)I",(void *)addSum}
};
// int len = sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]);
return env->RegisterNatives(clazz, methods_MainActivity,
sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]));
}
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
jint result = RegisterNatives(env);
LOGD("RegisterNatives result: %d", result);
return JNI_VERSION_1_6;
}
Java端调用:
c
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
// Used to load the 'cmake' library on application startup.
static {
System.loadLibrary("cmake");
}
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());
HNPCInit();
Person person=new Person();
person.setAge(12);
person.setName("java person");
Log.d(TAG,"调用本地方法前: person.getName:"+person.getName());
changePersonName(person);
Log.d(TAG,"调用本地方法后: person.getName:"+person.getName());
Person nPerson=getPerson();
Log.d(TAG,"调用本地方法 getPerson()后: person:"+nPerson.toString());
List<Person> personList=getPeronList();
Log.d(TAG,"调用本地方法 getPerson()后: personList:"+new Gson().toJson(personList) );
Log.d(TAG,"调用本地方法 addSum:"+addSum(10,15,65));
}
/**
* A native method that is implemented by the 'cmake' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public native void HNPCInit();
public native int add(int a,int b);
public native void changePersonName(Person mPerson);
public native Person getPerson();
public native List<Person> getPeronList();
private native int addSum(int a,int b,int c);
}
运行结果:
