在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++");

 

更多相关文章

  1. launchMode之的几种取值
  2. Android(安卓)SurfaceFlinger中的SharedClient
  3. 用Android(安卓)Studio在windows下面查看android源码
  4. Android(安卓)6.0系统读写文件出现FileNotFoundException:EACCES
  5. 用 Xamarin for VS 创建 aar 文件的绑定
  6. Android(安卓)Studio 工程结构介绍
  7. FFmpeg之一编译ForAndroid
  8. android studio 代码插件常用code整理
  9. android文件导出错误—— failed to pull a selection

随机推荐

  1. android测试工具MonkeyRunner--google官
  2. Android的uid与UserHandle
  3. VisionMobile:2015年Android使用的全球趋
  4. Qt on Android锛氬簲鐢ㄦ埅灞?/h1>
  5. Android应用程序的权限机制
  6. android基础总结-内部存储和外部存储的大
  7. Android之人脸识别
  8. Android的Launcher成为系统中第一个启动
  9. 基于Android的计算器(代码行数足够用来交
  10. android中listView下拉刷新