安卓小白之ndk入门篇
1.环境搭建
开发工具:AndroidStudio
打开AndroidStudio,进入settings
,找到Android SDK
目录,点击SDK tools
,分别找到如图三个配置,勾上,下载。
分别介绍一下:
- cmake
类似于Android studio中的gradle,是对ndk的一个配置管理 - LLDB
c/c++的一个调试工具,安装后可以对c/c++代码进行debug - NDK
ndk的开发工具包
安装完成后,新建一个工程,注意勾选下方的include c++ support
,一路next
,直到项目构建完成,这样,我们的整体的ndk项目开发环境就配置好了。
2.配置文件介绍
项目构建完毕后,我们会发现多了配置和文件,如图:
配置
先介绍一下这几个参数的作用:
点开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).
# 资源文件,可以多个,
# 资源路径是相对路径,相对于本CMakeLists.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} )
看注释就能明白每个方法参数代表什么意思了,如果你觉得里面注释太多,看起来不是很顺眼,可以下载CMake simple highligher
插件来提高代码亮度
效果图
关于cmake的配置还有许多,这里只是先简单介绍一个。
我们再来看一下build.gradle中的配置方法的作用,在
defultConfig
中有个这个参数,
externalNativeBuild {
cmake {
cppFlags ""
abiFilters 'armeabi','arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
}
}
我们主要关注 abiFilters
,它是用来设置编译生成什么类型的so的,我们的cup架构主要有以下几种:
- armeabi
- armeabi-v7a
- arm64-v8a
- x86
- x86_64
- mips
- mips_64
其中,armeabi-v7a
是目前大部分手机的主流架构,它是基于armeabi
的一种升级架构,因此,它们是互相兼容的,但目前各手机厂商的旗舰级,都已经开始采用arm64-v8a
的cpu,不过不要慌,它也是兼容armeabi
的,所以,如果我们只需要开发普通应用的话,我们只需要关注armeabi
和armeabi-v7a
就可以了,而像x86
等这种类型的架构多用于平板等设备,因此我们只需要了解即可。
与此相同的还有一个配置:
ndk{
abiFilters "armeabi","armeabi-v7a"
}
它也是用来配置需要什么类型的so的,但它是负责打包到apk里有什么类型的so,而不是编译出什么so,两者还是有区别的。例如我在cmake
里设置一个 "armeabi","armeabi-v7a",在ndk
里设置一个armeabi,我make project
一下,它会生成两个cpu类型的so,但是我运行打包apk,在apk的lib目录里就只有一个armeabi的so了,所以:
当我们不需要编译so库时,例如引用的第三方库,可以使用ndk
来过滤,完全不需要cmake
接下来说一下android
下的方法:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
其实很显然,它就是指定我们的CMakeLists
文件路径的,当然我们的这个路径是可以更改的。
这里教大家一个小技巧,在cmd中执行:adb shell
cat /proc/cpuinfo
可以查看当前手机的cpu架构哦,效果图如下:
CPU architecture: 8
说明我的手机是arm64-v8a
架构
接下来我们来看cpp文件,这个文件是干嘛的呢,它是c里.h文件的实现的源文件,你可以把它看作是与java交互的桥梁,里面包含了java层需要调用到的函数方法,点开可以看到以下函数:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_jie_ndkdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
主要是看这个函数:
Java_com_jie_ndkdemo_MainActivity_stringFromJNI
,它是有格式要求的,由Java_包名类名函数名组成,定义的时候一定要按照这个格式来,其中,MainActivity
是我声明native方法的类的类名。
相信看过这篇文章的同学对ndk已经有了一个初步的了解,本人打算接下来再总结两篇文章,一篇讲解ndk的调用,一篇讲解ndk的编译,相信看完这三部曲,对于ndk将会有一个全面的了解。