Android(安卓)NDK开发(二)——CMake脚本构建项目
在Android Studio 2.2 之后,工具中增加了CMake的支持,也就是说,Android Studio 2.2 之后有两种选择来编译C/C++代码,一个是上篇ndk-build + Android.mk + Application.mk组合编译,另一个是CMake + CMakeList.txt组合构建项目
CMake的使用
1、配置环境
2、创建CMake工程
方式一、在工程创建的时候添加
使用AS3.0新建一个NDKDemo工程,注意勾选Include C++ support
创建成功后,可以看到和普通的Android有以下4个不同:
- main 下面增加了 cpp 目录,即放置 C/C++ 代码的地方
- Module下的 build.gradle 有修改
- 增加了 CMakeLists.txt 文件
- 多了一个 .externalNativeBuild 目录
app/build.gradle下多了如下配置:
android { ... defaultConfig { ... externalNativeBuild { cmake { //主要填写CMake的命令参数 cppFlags "" } } ... } ... externalNativeBuild { cmake { path "CMakeLists.txt"// cmake配置文件路径 } }}
CMakeLists.txt文件中主要定义了哪些文件需要编译,以及和其他库的关系等,内容如下:
# For more information about using CMake with Android Studio, read the# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.4.1)# Creates and names a library, sets it as either STATIC# or SHARED, and provides the relative paths to its source code.# You can define multiple libraries, and CMake builds them for you.# Gradle automatically packages shared libraries with your APK.# 配置so库信息add_library( # Sets the name of the library. # 生成的so库名称,此处生成的so文件名称是libnative-lib.so native-lib # Sets the library as a shared library. # STATIC:静态库,是目标文件的归档文件,在链接其他目标的时候使用 # SHARED:动态库,会被动态链接,在运行时被加载 # MODULE:模块库,是不会被链接到其他目标中的插件,但是可能会在运行时使用dlopen-系列的函数动态链接 SHARED # Provides a relative path to your source file(s). # 资源文件,可以多个 # 资源路径时相对路径,相对于本CMakeList.txt所在目录 src/main/cpp/native-lib.cpp )# Searches for a specified prebuilt library and stores the path as a# variable. Because CMake includes system libraries in the search path by# default, you only need to specify the name of the public NDK library# you want to add. CMake verifies that the library exists before# completing its build.# 从系统查找依赖库find_library( # Sets the name of the path variable. # android系统每个类型的库会存放一个特定的位置,而log库存放在log-lib中 log-lib # Specifies the name of the NDK library that # you want CMake to locate. # android系统在c环境下打log到logcat的库 log )# Specifies libraries CMake should link to your target library. You# can link multiple libraries, such as libraries you define in this# build script, prebuilt third-party libraries, or system libraries.# 配置库的链接(依赖关系)target_link_libraries( # Specifies the target library. # 目标库 native-lib # Links the target library to the log library # included in the NDK. ${log-lib} )
我们发现系统已经帮我们把native-lib.cpp源文件写好了,根据函数名可以知道,函数的native申明在MainActivity中
#include #include extern "C" JNIEXPORT jstring JNICALLJava_com_example_jin_ende_1test_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); }
再看看MainActivity文件,与以前的jni调用方式完全一样
public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib");//加载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 = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI());//jni调用 } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI();//native申明}
现在我们在MainActivity中再申明一个native方法,光标放在函数名上,然后alt + enter
选择创建jni方法的选项,确认后会发现再native-lib.cpp中发现对应的本地代码框架已经写好
extern "C"JNIEXPORT jstring JNICALLJava_com_example_jin_ende_1test_MainActivity_getStringFromJNI(JNIEnv *env, jobject instance) { // TODO return env->NewStringUTF(returnValue);}
方式二:在项目开发过程中添加
有时候,我们的项目已经在进行中或者维护中,突然需要使用jni调用咋办?Android Studio也提供了相应的方法。
首先在app/src/main/jni下创建native-lib.c文件:
然后在app目录下新建一个CMakeLists.txt:
接着配置模块支持jni调用,项目模块右键:
点击ok后,系统开始编译,编译成功后build.gradle发生如下变化:
然后我们新建一个java调用本地代码的工具类JNIUtils.class,加载库,申明本地方法,选中方法alt+enter
发现自动在native-lib.c中为我们创建了本地代码的框架:
我们完善native-lib.c代码内容如下:
#include JNIEXPORT jstring JNICALLJava_com_example_jin_jnidemo2_JNIUtils_getStringFromJNI(JNIEnv *env, jobject instance) { return (*env)->NewStringUTF(env, "Hello from C++");}
上述两种方式中,实现JNI方法的区别在于,一个是用C++来实现,一个是用C来实现,它们的区别主要集中在对 env 的操作上,其他都是类似的,如下所示:
C++: env->NewStringUTF("Hello from C++");C: (*env)->NewStringUTF(env,"Hello from C++");
更多相关文章
- launchMode之的几种取值
- Android(安卓)SurfaceFlinger中的SharedClient
- 用Android(安卓)Studio在windows下面查看android源码
- Android(安卓)6.0系统读写文件出现FileNotFoundException:EACCES
- 用 Xamarin for VS 创建 aar 文件的绑定
- Android(安卓)Studio 工程结构介绍
- FFmpeg之一编译ForAndroid
- android studio 代码插件常用code整理
- android文件导出错误—— failed to pull a selection