参考:https://developer.android.com/studio/projects/add-native-code.html#link-gradle

使用Android Studio 2.2以上版本、Android插件 Gradle 2.2.0以上版本,可以将C/C++代码编译成native库,然后Gradle将库打包到APK中。Java代码可以通过JNI(Java Native Interface)调用native库中的函数。

本文所用环境为为Android Studio 2.2.2。

  • 安装NDK

用Android Studio集成的SDK Manager安装NDK、CMake和LLDB。其中CMake是编译工具,LLDB是调试工具。

  • 新建工程

勾选Include C++ Support

到下面这一步时,有三个选项:

C++ Standard:选择要用的C++标准,我的列表里有Toolchain Default和C++ 11,由于对C++标准没要求,我直接选Default,也就是编译工具(默认为CMake)的默认配置。

Exceptions Support:如果勾选,则编译时支持C++异常处理。Android Studio会在module对应的build.gradle中的cppFlags中添加 -fexceptions,这个cppFlags会被Gradle传递给CMake。

Runtime Type Information Support:如果勾选,则支持RTTI,Android Studio会在module对应的build.gradle中的cppFlags中添加 –frtti。

注:RTTI,(Run-Time Type Identification),通过RTTI, 程序能够使用基类指针或引用来检查这些指针或引用所指的对象的实际派生类

全部勾选,点击Finish完成工程的创建。

工程新建完成后,可以看到如上的目录,其中:

cpp中包含了所有项目中使用的native源码文件、头文件和预编译库。native-lib.cpp是Android Studio自动生成的一个sample文件,放在module的src/main/cpp中。

External Build Files中包含了CMake或ndk-build的编译脚本。CMakeLists.txt是Android Studio自动生成的一个CMake脚本,放在module的根目录中。

  • 编译并运行

点击Run,编辑并运行这个工程,APP呈现如下的界面:

下面就是编译和运行这个APP时发生的事情:

1.Gradle调用外部的编译脚本CMakeLists.txt

2.CMake执行编译脚本中的命令,将C++源文件(native-lib.cpp)编译成共享对象库(libnative-lib.so),Gradle再将这个so库打包到APK中。

生成的libnative-lib.so在module对应的build\intermediates\cmake\debug\obj中,如下图所示:

用APK Analyser可以看到APK中打包了libnative-lib.so库:

Build->Analyze APK..,如下:

3.运行时,MainActivity通过System.LoadLibrary()加载native库,然后库中的native方法就可以用了。下面是MainActivity中的代码。

 

  • 添加C/C++文件到工程

1.在module的cpp文件夹中,右键,new->C++ Class或者C/C++ Source File。

新建完成后,不会马上在Android目录结构中看到文件,打开新建的文件,会提示需在编译文件中添加该文件,并且同步工程。

2.在CMakeLists.txt中,添加对新建cpp文件的配置。

3.点击Sync Now,同步完成后,就可以在Android目录结构下看到新建的文件了。

  • CMakeLists.txt

1.CMake的编译脚本必须命名为CMakeLists.txt

如果不是,就会报错,如下:

2.CMakeLists.txt最好放在module的根目录

其实放在任意目录都可以,但是文件中声明的C/C++文件路径,都是相对于编译脚本文件所在的目录。

3.CMake默认将库文件命名为:

但是在使用时,仍然使用library-name导入就行了。

4.CMake 命令:

(1)cmake_minimum_required(VERSION 3.4.1) - 指定CMake最低版本

(2)add_library(...) - 声明库名称、类型、源码文件
(3)include_directories() - 指定关联的头文件目录
(4)find_library() - 定位某个NDK库,并将其路径存储为一个变量,可以在其他地方用这个变量引用NDK库
(5)target_link_libraries() - 将NDK库链接到native库中,这样native库才能调用NDK库中的函数
5.将NDK目录下的源码编译到native库中:
其中,ANDROID_NDK是AndroidStudio自动定义好的变量。
6.添加其他预编译库
需要用IMPORT标志,告诉CMake,只需要引用这个预编译库(不需要进行编译)。
 

然后用set_target_properties()指定库的路径。

其中ANDROID_ABI这个变量列出了NDK支持的所有ABI(Application Binary Interface),用这个变量可以让CMake引用多个ABI对应的库文件。

当然,还要指定头文件路径:

最后,用target_link_libraries()将预编译库链接到native库中。

NDK 笔记(一)的更多相关文章

  1. Android NDK笔记

    目录 Android NDK笔记 AOSP Android repository Android SDK / SDK Tools NDK cmake && ninja lldb adb ...

  2. NDK笔记(二)-在Android Studio中使用ndk-build

    前面一篇我们接触了CMake,这一篇写写关于ndk-build的使用过程.刚刚用到,想到哪儿写哪儿. 环境背景 Android开发IDE版本:AndroidStudio 2.2以上版本(目前已经升级到 ...

  3. android NDK 笔记

    *************************************************华丽的分割线********************************************* ...

  4. NDK笔记(二)-在Android Studio中使用ndk-build(转)

    前面一篇我们接触了CMake,这一篇写写关于ndk-build的使用过程.刚刚用到,想到哪儿写哪儿. 环境背景 Android开发IDE版本:AndroidStudio 2.2以上版本(目前已经升级到 ...

  5. NDK(三方库引入、Mk文件)

    NDK笔记-----第三方库引入 一.字符操作: 1 二.NDK*(JNI)对象操作: 2 1.C++调用java对象 3 三.Android.mk说明: 3 四.Application.mk说明 3 ...

  6. Android JNI&NDK编程小结及建议

    前言 由于网上关于JNI/NDK相关的知识点介绍的比较零散而且不具备参照性,所以写了这篇JNI/NDK笔记,便于作为随时查阅的工具类型的文章,本文主要的介绍了在平时项目中常用的命令.JNI数据类型.签 ...

  7. NDK开发_笔记0

    自谷歌搜索退出中国以来,谷歌对全球第二大市场中国的态度一直保持冷淡.可是北京时间12月8日,谷歌2016开发者大会在北京召开,同时专门针对中国的谷歌开发者网站已经上线:https://develope ...

  8. 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化

    第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...

  9. 《android开发艺术探索》读书笔记(十四)--JNI和NDK编程

    接上篇<android开发艺术探索>读书笔记(十三)--综合技术 No1: Java JNI--Java Native Interface(java本地接口),它是为了方便java调用C. ...

随机推荐

  1. [LeetCode] Burst Balloons 打气球游戏

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...

  2. [LeetCode] Symmetric Tree 判断对称树

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  3. [LeetCode] Implement strStr() 实现strStr()函数

    Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle ...

  4. Openfire 集群部署和负载均衡方案

    Openfire 集群部署和负载均衡方案 一.   概述 Openfire是在即时通讯中广泛使用的XMPP协议通讯服务器,本方案采用Openfire的Hazelcast插件进行集群部署,采用Hapro ...

  5. 走格子 51nod

    球最少需要的能量,就是保证能量一直>=0,从头遍历取过程中能量最小值,绝对值为答案. #include<iostream> #include<algorithm> #in ...

  6. 记录rewrite url我之前不知道的地方

    大部分url重写的需求是伪静态,当然有很多第三方开源组件,但是这种需求的核心方法其实就是context.rewritePath() 要是系统像ARR那样,用重写做代理和反向代理,一般的重写就不行了,c ...

  7. Python学习--Python简介

    Python 简介 Python是一种解释型.编译性.面向对象.动态数据类型的高级程序设计语言.Python由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年. P ...

  8. SQL 基础语法(一)

    SQL 语法 数据库表 一个数据库通常包含一个或多个表.每个表由一个名字标识(例如"客户"或者"订单").表包含带有数据的记录(行). 下面的例子是一个名为 & ...

  9. 在 Linux 中查看时区

    1.date date +"%Z %z" 或者 date -R 2.timedatectl timedatectl|grep "Timezone" 可以使用 t ...

  10. Android源码——Activity组件的启动过程

    根Activity启动过程 Launcher启动MainActivity的过程主要分为6个步骤: 一.Launcher向ActivityManagerService发送一个启动MainActivity ...