专栏首页QQ音乐技术团队的专栏Android Studio 2.2 Native 开发新特性
原创

Android Studio 2.2 Native 开发新特性

一、Android Studio Native 开发新特性扫描

  • 提供对 CMake(官方默认)、ndk-build 两种构建方式的支持。原来的 Experimental Gradle Plugin 构建方式仍然可用,官方建议迁移。
  • 构建生成的 .so 文件将直接被 Gradle 打包在 apk 中。
  • 以 LLDB 为 Native 层的调试器,提供跨 Java 层和 Native 层的 Hybrid Debugger。
  • 开发环境提供对 Native 代码编辑的支持。

对 Native 方法查找引用,可以看到 IDE 同时列出 Java 层和 Native 层的方法(函数)及其引用

  • 新特性要求 Android Gradle Build Tools 版本必须为 2.2.0 及以上,且 Gradle 版本必须为 2.14.1 及以上。

二、将现有 Native 代码链接到 Android Studio 项目

考虑到 ndk-build 构建方式已经有很大的使用量,Google 支持在 Android Studio 使用 ndk-build 构建。开发者需提供 Android.mk 和可选的 Application.mk,并更新 build.gradle。执行构建时,Gradle 将调用 ndk-build,并将生成的 .so 文件打包进 apk 当中。

方法一 : 使用 Android Studio IDE

Android Studio 提供了一个自动配置 Gradle,使之链接 Native 源代码的方式:

  1. 在 Project 选项卡选中当前项目,进入 “File” 菜单,选择 “Link C++ Project with Gradle”;
  2. 在弹出的对话框中,构建方式选择 “ndk-build”,并定位要引入代码的 Android.mk 文件位置;
  3. 点击 “OK”,如果幸运的话,等待 Gradle Build 完成后,即可开始享受在 Android Studio 继续开发现有 Native 项目的乐趣了。

以上过程针对 ndk-build 构建方式。要链接 CMake 方式构建的 Native 代码,需提供 CMakeLists.txt 的路径,操作过程类似。

方法二 : 修改 build.gradle

如果需要对执行构建时的具体参数进行调整,就需要通过修改 build.gradle 来实现。在不指定额外参数时,Gradle 将采用默认配置完成 Native 库构建,例如 Gradle 将告知 ndk-build 构建所有 ABI 的 .so 库 (即便已经在 Application.mk 添加了 APP_ABI 参数),这可能是不需要的。

三、认识 build.gradle 的新成员

本节介绍 build.gradle 中与 Native 代码构建有关的新字段。

1. android/externalNativeBuild 块

如果通过上述“方法一”链接了 Native 源代码,build.gradle 将在 android 块下新增:

externalNativeBuild {
    ndkBuild {
        path '[被链接的 Native 代码的相对目录]/Android.mk'
    }
}

其中,ndkBuild 指定了构建工具,如果使用 CMake,该字段即为 cmake,path 字段的值为 CMakeLists.txt 文件的相对位置。

2. android/defaultConfig/ndkBuild(cmake) 块

可以在这个代码块中添加构建参数、C/C++ 编译标志等。例如:

android {
  ...
  defaultConfig {
    ...
    ndkBuild {
        arguments "NDK_DEBUG=1" // ndk-build 参数
        cFlags "-D_EXAMPLE_C_FLAG" // C 编译标志
        cppFlags "-D__STDC_FORMAT_MACROS" // C++ 编译标志
    }
}

另外,参考资料 6 提供了在使用 CMake 构建工具时,可以添加的一些自定义构建参数。比如 arguments "-DANDROID_STL=gnustl_static" 指定 CMake 使用 GNU 的静态标准库。

3. abiFilters 字段

该字段用于设定要构建和打包进 apk 的 ABI。该字段可存在于 android/defaultConfig/ndk 块,也可在 android/defaultConfig/ndkbuild(cmake) 块。其中前者指定构建和打包的 ABI (较为常用),后者仅指定构建的 ABI。abiFilters 的可选参数与在 Application.mk 添加的 APP_ABI 参数一致(详见参考资料 3)。例如:

android {
  ...
  defaultConfig {
    ...
    ndk {
      abiFilters 'x86','armeabi','armeabi-v7a','arm64-v8a'
    }
}

四、CMake 初探

自 Android Studio 的最新版本起,CMake 成为其用于构建 Native 库的默认工具。CMake (解释为 Cross-Platform Make) 起源于 21 世纪初,是目前主流的跨平台构建工具。CMake 脚本可以视为对构建过程中使用的 Makefile 进行了一层封装,因此具有更好的可读性和易用性。本节试图把在构建 Android Native 库时需用到的的 CMakeLists.txt 脚本进行简单的梳理。

1. 先举一个小栗子

下面的 CMakeLists.txt 构建了一个简单的 Native 库的框架。经 Gradle 调用 CMake 后,将会生成 libnative-lib.so 文件,并可在 Java 代码中通过 System.loadLibrary("native-lib"); 加载这个 Native 库。

# CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib src/main/cpp/native-lib-src.cpp)
find_library(ndk_log log)
target_link_libraries(native-lib ${ndk_log})

2. cmake_minimum_required (VERSION *.*.*)**

一般作为 CMakeLists.txt 正文的首行,用于指示脚本可被执行的 CMake 最低版本。对于 Android Native 库的构建来说,CMake 版本不应低于 3.4.0。

3. add_library (<name> [STATIC | SHARED | MODULE] source1 [source2 ...])**

添加一个 Native 库。需指定库的名字(唯一识别一个库,也是 .so 文件的命名来源。这里与 ndk-build 一致)和源文件相对路径列表。对于 Android Native 库,一般需添加 SHARED 或者 STATIC 标志,指明加载方式。

Android Studio 会将这里列出的所有源文件添加到 Project 选项卡的 Android/Module/cpp 分组里。

4. include_directories (dir1/ [dir2/ ...])

指定头文件的目录。用于告知 CMake 在编译期寻找合适的头文件。

5. ind_library (<VAR> lib [path1 path2 ...])

将由 NDK API 预先构建的库的路径以变量形式存储,为后面链接构建库提供预备参数。例如: find_library (ndk_log log) 即为将 log 库作为变量 ndk_log 的引用。

这里的库名称参数与在 Android.mk 添加的 LOCAL_LDLIBS 参数一致,可用的预构建库与 Android 版本有关(详见参考资料 5)。

6. `ANDROID_NDK、ANDROID_ABI 变量

Android Studio 会自动定义 ANDROID_NDK、ANDROID_ABI 等变量,其值分别为 NDK 的根目录路径和将生成的 Native 库的目标 ABI。

7. target_link_libraries (<target> <item> ...)

向将要构建的库中链接其他库。常见的可链接类型包括:

(1) NDK API 的预构建库,比如要链接上面的 log 库,则需添加:

find_library (ndk_log log)
target_link_libraries (<name> ${ndk_log})

(2) 通过 add_library 新建的,引用源代码的静态库,例如:

add_library(native-util STATIC dependencies/Util4Native.cpp)
target_link_libraries(native-lib native-util)

也可以利用 NDK API 提供的源代码进行链接:

add_library(app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
target_link_libraries(native-lib app-glue)

(3) 另外,如果需要链接已构建的库,可以通过包含 IMPORTED 标志的 add_library 完成添加。例如:

# 添加已构建的库,名字为 imported-lib
add_library(imported-lib SHARED IMPORTED)
# 设置 imported-lib 的属性,指定 .so 库的位置
set_target_properties(imported-lib PROPERTIES IMPORTED_LOCATION imported-lib/src/${ANDROID_ABI}/libimported-lib.so)
# 指定包含文件夹,以便能在源代码中引用这个库 (参考前述第 4 小节)
include_directories(imported-lib/include/)
# 链接 imported-lib 到 native-lib
target_link_libraries(native-lib imported-lib)

8 . 应用更改并同步

在更新 CMakeLists.txt 之后,可以执行 “Build”→“Refresh Linked C++ Projects” 应用更改,Gradle 触发执行 CMake 以备构建。应用更改后,Project 选项卡的 “cpp” 节点将会同步更新。

当项目中包含多个 Native 库时,Project 选项卡将会分开显示这些库

五、总结与展望

与更早引入 Android Studio 开发环境下的,用于 Native 构建的 Experimental Gradle Plugin 方案相比,官方支持 CMake 和 ndk-build 配合 Gradle 用于构建,颇有一种“返璞归真”的意味。Android Studio 2.2 对 Native 开发的支持程度,已经足够吸引开发者们主动改变跨环境开发的现状了。

在本文所述之外,参考资料 1 中还提供了利用向导工具创建具有 Native 支持的 Android 新项目的方法。由于这个新特性比较明显,本文未做详述。另外,如果所处的网络环境不适宜在官方镜像下载所需的开发工具,可以访问腾讯 Bugly 提供的镜像 : https://dsx.bugly.qq.com.

参考资料

  1. Add C and C++ Code to Your Project https://developer.android.com/studio/projects/add-native-code.html
  2. ndk-build Guidelines https://developer.android.com/ndk/guides/ndk-build.html
  3. ABI Management https://developer.android.com/ndk/guides/abis.html
  4. Document for add_library https://cmake.org/cmake/help/latest/command/add_library.html
  5. Android NDK Native APIs https://developer.android.com/ndk/guides/stable_apis.html
  6. Additional Information for CMake Build https://developer.android.com/ndk/guides/cmake.html
  7. CMake vs Make https://prateekvjoshi.com/2014/02/01/cmake-vs-make

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用 Xposed 强制 androidwebView 开启 debug 模式

    从 《远程调试 Android 设备使用入门》文章中我们可以知道在 android 4.4+可以通过在apk中使用下面的代码开启 webview 的 chrom...

    腾讯IVWEB团队
  • 一种 Android 端 Web 多进程情况下支持 Web 自动化测试的方法

    本文介绍一种在Web多进程情况下支持Web自动化测试的方案。介绍当前Web自动化的简要原理、Web多进程后的问题、相应的解决方案及使用方法。

    腾讯移动品质中心TMQ
  • RxJava && Agera 从源码简要分析基本调用流程(2)

    RxJava能够帮助我们对数据流进行灵活的变换,以达到链式结构操作的目的,然而它的强大不止于此。下面我们就来看看它的又一利器,调度器`Scheduler`:就像...

    QQ空间开发团队
  • Android开发入门的正确姿势

    对于从事移动客户端开发者的初学者而言,不论是Android还是iOS开发,对客户端开发有一个整体的认识,然后再逐步深入,这样会有事半功倍的效果。

    刘宁
  • RxJava && Agera 从源码简要分析基本调用流程(1)

    相信很多做Android或是Java研发的同学对RxJava应该都早有耳闻了,尤其是在Android开发的圈子里,RxJava渐渐开始广为流行。同样有很多同学已...

    QQ空间开发团队
  • 遇见 Kotlin 先导篇:Kotlin 相比 Java 好在哪里?

    Kotlin 是一种为现代多平台应用而诞生的静态编程语言相比于Java而言,它有很多优点,待会笔者会就几个写一下,并给出实际例子。

    YingJoy_
  • iOS 测试利器:idb

    对于android的开发以及测试人员,对adb命令一定会很熟悉,adb工具可谓android测试的入门神器,安装、卸载、抓log、截图等等一应俱全。很多自动化以...

    腾讯移动品质中心TMQ
  • 深入理解React(二) :数据流和事件原理

    在React中,数据流是自上而下单向的从父节点传递到子节点,所以组件是简单且容易把握的,他们只需要从父节点提供的props中获取数据并渲染即可。如果顶层组件的某...

    小时光
  • 5分钟教你打造一个秒开的 Android App

    近日在开发过程中,发现每次点击 app 从桌面启动都有一个在桌面明显的等待时间,机型越低端的越明显,冷启动优化看来已经势在必行,所以怒而一顿研究再解决之。

    MatthewF
  • 用 Kotlin 写 Android ,难道只有环境搭建这么简单?

    话说我们入坑 Kotlin 之后,要怎样才能把它运用到 Android 开发当中呢?我们作为有经验的开发人员,大家都知道 Android 现在基本上都用 gra...

    bennyhuo

扫码关注云+社区

领取腾讯云代金券