使用CMake进行android NDK开发

NDK与JNI就不多概述了,我所理解的NDK就是android开发中能够编译C/C++程序,构建SO,而JNI则是java提供的能够调用c/c++程序的接口,NDK与JNI开发也会分多篇讲解,大概会分为环境配置、JNI知识、优化三部分,其中JNI部分为android NDK开发的主要部分,主要涉及java与C/C++交互。
那么本篇涉及知识点如下,主要为配置部分:

  • 1.android studio中配置NDK开发环境
  • 2.CMake配置

android studio中配置NDK开发环境

android studio 2.2以上版本才会支持CMake,低版本只能使用ndk-build方式开发。

1.新建项目,勾选 Include C++ support
使用CMake进行android NDK开发_第1张图片
image.png

一路创建好项目,android会自动创建一个基于cmake的NDK项目.与普通项目不同的是:

  • 在main文件夹下多了一个cpp文件夹,包含了一个native-lib.cpp文件
  • 在APP目录下多了一个CMakeLists.txt文件夹
  • local.properties文件里会多了一个ndk.dir路径的配置
  • app目录下的build.gradle,会多了两处cmake的配置
externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
            }
        }
externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

直接程序运行会在屏幕上显示"Hello from C++".到此,说明一个NDK项目以及创建完成,很简单,这也是我推荐使用cmake的原因。
第一次创建,可能会出现很多环境问题,比如NDK下载不成功,运行不起来等等,需要你根据
错误查找具体的原因来解决。

2.现有项目 支持NDK配置

对于刚接触NDK配置的,其实很简单,同上面的步骤新创建一个支持NDK的项目,与旧项目结构对比不同之处,修改调整即可。你不创建新项目也可以,老司机可以直接开车,总结一下,大致为一下几点:

1.NDK下载,有NDK环境的就不用下了,下载安装下图红框的即可。


使用CMake进行android NDK开发_第2张图片
image.png

2.下载完毕,在local.properties配置你的NDK目录

ndk.dir=...
sdk.dir=...

3.在main目录下 新建一个cpp目录,用于存放cpp文件
4.在app目录下创建CMakeLists.txt文件,里面的配置内容是重点,放在本篇后面单独讲,并在app目录的build.gradle指定这个文件的路径并指定CMake配置,当然在Module中也可以,如下

defaultConfig中:
externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"//指定CMakeLists.txt配置
            }
        }
android中:
externalNativeBuild {
        cmake {
            path "CMakeLists.txt" //指定CMakeLists.txt路径
        }
    }

几个核心配置点,就是这么多。但是现在还运行不起来程序,把CMakeLists.txt配置完,写个JNI便可以了,下面我们就来看看CMake配置。

CMake配置

主要就是配置CMakeLists.txt,CMakeLists.txt就是编译so库的脚本文件,类似于原来的Android.mk,Application.mk。先看一下新建的NDK项目中CMakeLists.txt的内容:

#设置CMake插件的版本
cmake_minimum_required(VERSION 3.4.1)

#搜索指定的预构建库,并将该路径存储为一个变量
find_library( log-lib
              log )

#定义要编译的源代码和最终要生成的库文件名称及类型
add_library(
             native-lib #编译生成的库的名称,注意最终生成时会在前面加`lib`.
             SHARED #生成的库的类型,有SHARED,STATIC,MODULE
             src/main/cpp/native-lib.cpp ) #要编译的源代码文件

#如果有源码文件有头文件,指定头文件的目录
include_directories(src/main/cpp/include/)

#指定库的库应该链接到你的目标库。您可以链接多个库
target_link_libraries( 
                       native-lib
                       ${log-lib} )

以上是最基本的一个配置。

添加第三方的so库

因为已经编译好了,所以使用IMPORTED关键字

#设置so资源路径
set(my_lib_path ${CMAKE_SOURCE_DIR}/libs)
# 添加三方的so库
add_library(libfmod
            SHARED
            IMPORTED )
# 指名第三方库的绝对路径
set_target_properties( libfmod
                       PROPERTIES IMPORTED_LOCATION
                       ${my_lib_path}/${ANDROID_ABI}/libfmod.so )
当第三方库有针对不同架构编译了不同的库版本时,
有时候我们只需要引入我们想要的版本的库,当我们想要引入多个版本的库时,
可以使用ANDROID_ABI变量,它表示默认的ABI架构和NDK支持的架构,
如果我们在build.gradle中设置了过滤值,则表示过滤后的架构集合。

target_link_libraries(
                        libfmod
                       ${log-lib} )

这些配置我也是从网上学习而来。以上这些会配置了,就差不多了。
参考资料:
官方介绍CMake: https://developer.android.com/studio/projects/add-native-code.html
Cmake Api 官方帮助文档:https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html

本地方法编写

新建类Test,加载so,并写一个本地方法helloWord,如下:

public class Test {
    static {
        #这里的native-lib就是前面CMakeLists.txt中添加的库名字
        System.loadLibrary("native-lib");
        #如果有三方so,也一并引入,注意不要lib
        System.loadLibrary("第三方so");
    }

   #本地方法
    public native String helloWord();

}

对应的C/C++方法为:

extern "C"
JNIEXPORT jstring JNICALL
Java_cn_mmdet_jean_Test_helloWord(JNIEnv *env, jobject instance) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

调用Test的helloWord就能看到C返回的内容了。
也许我讲的不够详细,但是配置这一块,我相信是最简单的,结合本篇文章以及相关资料,肯定就能搞定,最简单的方法还是使用android studio直接新建一个支持C++的项目,运行一下看看结果。然后主要看一下CMakeLists.txt的配置,配置部分就结束了。相比之前的.mk简单很多。

你可能感兴趣的:(使用CMake进行android NDK开发)