IDE:Android Studio 3.0.1
编译器:cmake(studio 2.2以上支持的编译工具,个人感觉很好,很舒服,对于我这种C和C++才学了一个多月的人来说,至少有提示,)。
创建新项目可以直接使用包含c/c++支持,这边主要介绍向现有项目添加c/c++来生成so文件。
1.新建cpp文件夹,在文件夹中添加c/c++文件,先什么都不写,如下图所示
2.编写CMakeLists.txt脚本文件
在moudle目录下新建CMakeLists.txt文件,如下图所示
脚本文件内容如下:
cmake_minimum_required(VERSION 3.6) //必须指定cmake编译版本 add_library( # Sets the name of the library. native-lib //so文件的名字 # Sets the library as a shared library. SHARED //生成共享库 # Provides a relative path to your source file(s). # Associated headers in the same location as their source # file are automatically included. "src/main/cpp/jni2.cpp") //指定编译的源文件,这边有说法等会在下面再说。
其他相关配置项参考官网:https://developer.android.com/studio/projects/add-native-code.html
3.将脚本文件和gradle关联
右击moudle,选择第二项
然后选择你的脚本文件目录
编译成功之后会在你的gradle下自动生成这个
4.建立native方法和加载so文件
这时你会发现你的方法时红色的,然后移到方法上,按住Alt+Enter,就会自动生成相关方法。
这边就有个奇怪的点了,他会在src/main文件夹下生成一个jni文件,然后实现方法在这里面,这就和你指定编译的源文件有关了,如果你创建的是和so文件名一样的c/cpp文件,它就会把相关方法实现在其中,不然他就会新建个以so文件名一样的c文件,因为考虑我后期可能编译多个c/cpp文件,不可能写在同一个文件里面,所以我们就把具体里面的方法拷贝到我们创建的c/c++文件中即可。
把方法复制过来并做修改
#include <jni.h> extern "C" //如果你创建的是cpp文件,这句话必须加上,不然编译通过不了 JNIEXPORT jstring JNICALL Java_com_jacky_myapplication_MainActivity_getStringFromJni(JNIEnv *env, jobject instance) { // TODO return env->NewStringUTF( "hello,jni2"); }
5. 编译项目
Build——>make project
生成的各个so架构如下
6.通过gradle来配置指定生成的不同架构
android { compileSdkVersion 26 defaultConfig { applicationId "com.jacky.myapplication" minSdkVersion 15 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "" abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a' //架构配置 } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } externalNativeBuild { cmake { path 'CMakeLists.txt' } } }
然后再make project,生成如下
7.调用我们的native方法试试是否成功
成功!!!!!好开心呀。
问题1:如果我有多个c/cpp如何同时编译?
可以通过修改CMakeLists.txt文件可以进行修改。
我在cpp文件夹下又新建了个jni1.c文件,也什么也不写
cpp文件夹目录
修改CMakeLists.txt脚本文件,然后再编译
cmake_minimum_required(VERSION 3.6) file(GLOB_RECURSE cpp_srcs_c "src/main/cpp/*.c") //添加该目录下的所有c文件 (包括子目录) file(GLOB_RECURSE cpp_srcs_cpp "src/main/cpp/*.cpp") //添加该目录下的所有cpp文件 (包括子目录) set(cpp_srcs ${cpp_srcs_c} ${cpp_srcs_cpp}) //设置这两个路径 add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). # Associated headers in the same location as their source # file are automatically included. ${cpp_srcs}) //配置编译这些目录下的文件
添加native方法
继续按住Alt+Enter键让它自己生成,不出意外又跑到jni目录的那个c文件去了,复制出来,拷贝到我们的jni1.c中
运行效果图:
问题2:如何生成多个so?
参考这篇博客 https://www.cnblogs.com/chenxibobo/p/7678389.html
其他相关参考地址:
https://developer.android.com/studio/projects/add-native-code.html#specify-abi
https://developer.android.com/ndk/guides/cmake.html#variables
https://stackoverflow.com/questions/45209369/android-cmakelist-add-multi-source-file