android studio 使用CMAKE
前言
之前,每次需要边写C++代码的时候,我的内心都是拒绝的。
1. 它没有代码提示!!!这意味着我们必须自己手动敲出所有的代码,对于一个新手来说,要一个字母都不错且大小写也要正确,甚至要记得住所有的jni函数等,真是太折磨人了…平时写Java代码的时候都是写几个字母会出来一大堆提示然后选择的,这样还有一个好处就是很多时候我们不知道有那些函数,但是我们可以通过obj.
,然后就可以看到它有哪些方法函数了。
2. 很多地方会显示为红色,就像是错误提示的那种,当然,如果没错的话还是能编译运行的,但是如果像编写java代码一样,写错的地方才给我红色显示不是更好吗?
这两个问题可折磨死我这个强迫症了…在网上百度了很久如何能够使用Android Studio编写C++代码时有代码提示自动补全功能,但是一直没有找到有效的(不使用CMake的情况下,若有人知道,麻烦告知)。好在一次偶然的机会,在网上看到在
Android Studio 2.2 中愉快地使用 C/C++这篇文章,看到上面说Android
Studio2.2版本完善了对C/C++的支持,还提及到CMAKE,赶紧把Android
Studio从2.0版本升级到了2.2版本,按照介绍新建了一个NDK工程,发现里面居然有我梦寐以求的C++代码自动补全提示!!!喜大普奔!!!
赶紧了解学习下Android Studio2.2版本提供的CMAKE方式。打算以后都使用这种方式了,别的不说,就冲可以有C++代码自动补全提示这个功能我就爱上它了。
工具安装
Android Studio升级到2.2之后,我们可以先配置好NDK开发的一些所需工具,如图,在SDK Tools中勾选安装CMake、LLDB、NDK。
CMake: 外部构建工具。如果你准备只使用 ndk-build 的话,可以不使用它。
LLDB: Android Studio上面调试本地代码的工具。
Android Studio自带DEMO了解CMAKE
Android Studio升级到2.2版本之后,在创建新的project时,界面上多了一个Include C++ Support
的选项。勾选它之后将会创建一个默认的C++与JAVA混编的Demo程序。就让我们先来看看这个官方标准Demo吧。
开始之前最好先下载好NDK,见NDK开发 从入门到放弃(一:基本流程入门了解),即在Project Structure界面Android NDK location处下载或选择正确的路径。或者使用上方提供的工具安装方法来进行下载。否则,创建的新project也会报错,需要配置好后clean。
File -> New -> New Project,在如下界面中勾选Include C++ Support
,然后一路 Next,直到 Finish 为止即可。
项目打开后我们查看目录结构,与常规项目不同的是多了.externalNativeBuild文件夹、cpp文件夹、CMakeLists.txt文件,如下图:
这三个东西都是NDK部分:
1. .externalNativeBuild文件夹:cmake编译好的文件, 显示支持的各种硬件等信息。系统生成。
2. cpp文件夹:存放C/C++代码文件,native-lib.cpp文件是该Demo中自带的,可更改。需要自己编写。
3. CMakeLists.txt文件:CMake脚本配置的文件。需要自己配置编写。
Gradle中也有两处不同:
java代码:
public class MainActivity extends AppCompatActivity { @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());
} /**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(); // Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
}
从native-lib.cpp的代码中我们能看到它使用的是静态注册的方式,动态注册的方式代码同传统JNI。
#include <jni.h>
#include <string> extern "C"
jstring
Java_com_example_person_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
CMakeLists.txt文件中我们需要注意的是下面这三个地方。两个library的名字(需一致)以及一个cpp文件的路径,彼此需要对应一致,当我们自己定义library以及自己创建cpp文件时需要对应修改。
运行代码,就能看到效果,调用了C++方法在界面上显示了Hello from C++
字符串。这就是CMake方式进行NDK开发的Demo。
还记得传统JNI方式中吗?我们使用了ndk
-build来编译C/C++文件为so文件,对于使用过第三方库的开发者来说,对so肯定不陌生。我们只能使用别人给的so文件,而无法看到C/C++源码,更别说去修改了。但是在这里我们好像一直没看到so文件的影子,那么,我们安装运行的apk中,有对应的so文件吗?如果想验证一下apk是否有so文件,我们可以使用
APK Analyzer:
- 选择 Build > Analyze APK。
- 选择 apk,并点击 OK。
- 如下图,在 APK Analyzer 窗口中,选择 lib/x86/,可以看见 libnative-lib.so 。
Tips:Instant Run 并不兼容使用了 native code 的项目。Android Studio 会自动禁止 Instant Run 功能。
但是我个人目前更关注的问题是C++代码自动补全提示的功能,当在cpp文件中写代码时,里面不再是一大片的红色,输入若干个字母的时候,也能给出提示了,简直叼渣天,至于原因…我就不清楚了,为什么在这里就有这个强大的功能了呢?哪位大神能解释下…
CMake编译so文件
CMake和传统 JNI在目录结构和配置文件上的区别
现在我们有了CMake和传统JNI两种开发NDK的方法,它们在目录结构和Gradle上有所区别,下面我们将分别介绍目录区别和Gradle配置的区别。
一、目录结构
传统JNI
CMake
这两种方式在目录上的区别就是两点:
1. 以前的jni目录改成cpp,名字更换了,下面还是存放C/C++文件。
2. 之前对C/C++文件的编译配置Android.mk、Application.mk文件放在jni目录下,现在改成CMakeLists.txt文件。(事实上这些文件的位置是可任意存放的,只需要配置好就行。但最好还是按照默认习惯放置。)
二、Gradle
传统JNI
CMake
事实上,我们在使用传统JNI方式的时候,上面的两处地方我们都省略了,也不会造成什么异常(若Android.mk存放位置在其他地方则需要配置)。CMake方式中第一处也可省略,但是第二处不能省略(同样,位置路径要写对),因为没有它将无法Build生成.externalNativeBuild文件夹。
另外,传统JNI开发还需要在项目根目录下的gradle.properties文件中配置
android.useDeprecatedNdk=true
- 1
- 1
否则Build项目的时候会报错。
CMake的优势
- 可以直接的在C/C++代码中加入断点,进行调试
- java引用的C/C++中的方法,可以直接ctrl+左键进入
- 对于include的头文件或者库,也可以直接进入
- 不需要配置命令行操作,手动的生成头文件,不需要配置android.useDeprecatedNdk=true属性
普通Android项目转NDK开发项目
我们之前说了,在创建新project时若勾选了Include C++ Support
选项(需Android Studio版本不低于2.2),则该项目就已经是一个NDK开发项目了。那么,若项目已经存在,该如何再转为NDK开发项目呢?
Tips: 在配置好NDK的前提下。且各种地方的配置均不再赘述。如Android.mk中如何配置、CMakeLists.txt文件中的配置、各个地方的统一等。
传统JNI方式,在NDK开发 从入门到放弃(一:基本流程入门了解)中我们了解过:
- 新建jni目录,写好C/C++代码。静态注册JNI时我们使用了javah -jni对JAVA类进行操作自动生成了jni目录以及对应的头文件(事实上,当我们有一定经验后可以自己写,而不再需要使用该辅助命令来保证不写错,另外动态注册也是一个很值得提倡的方式),然后根据头文件写了C/C++代码。但在动态注册JNI时我们可以自己先创建好jni目录且写好C/C++代码。
- 在jni目录下创建且配置好Android.mk和Application.mk两个文件。
- build.gradle文件中根据情况进行配置,可不进行配置使用默认值。
- 通过ndk-build操作,我们能得到对应的so文件,放置在相应位置,java代码中即可调用C/C++代码,运行程序。
回顾前面提到的CMake方式的NDK开发,我们得到如下步骤:
- 新建cpp目录,写好C/C++代码。
- 创建且配置CMakeLists.txt文件。
- build.gradle文件中根据情况进行配置,CMakeLists.txt文件的路径必须配置。
- java代码中即可调用C/C++代码,运行程序。
- project的build.gradle文件中,gradle版本不能低于2.2,否则会报错。
关联本地库与 Gradle
为了将本地库与 Gradle 相关联,你需要在 CMake 或 ndk-build 构建脚本中提供一个路径地址。当你构建你的 APP 时,Gradle 会将 CMake 或 ndk-build 作为一个依赖运行,然后将共享库(.so 文件)打包到你的 APK 中。Gradle 同样使用构建脚本来识别哪些文件需要导入到 Android Studio 项目,你可以从 Project 窗口面板中看到相应的文件。如果你还没有一个为 native sources 准备的构建脚本,你需要先创建一个。
使用 Android Studio 图形化界面
你可以使用 Android Studio 的图形化界面来将 Gradle 与外部 CMake 或者 ndk-build 项目关联起来。
- 打开 IDE 左边的 Project 面板,选择 Android 视图。
- 右键点击你想链接本地库的 module,比如 app module,然后从菜单中选择 Link C++ Project with Gradle。你应该能看见一个和下图很像的对话框。
在下拉菜单中,选择 CMake 或者 ndk-build。
a. 如果你选择 CMake,需要在 Project Path 中指定CMakeLists.txt
脚本文件的路径。
b. 如果你选择 ndk-build,你需要在 Project Path 中指定Android.mk
脚本文件的路径。
点击 OK。
手动配置 Gradle
如果要手动将 Gradle 与你的本地库相关联,你需要在 module 层级的 build.gradle 文件中添加 externalNativeBuild {}
代码块,并且在该代码块中配置 cmake {}
或 ndkBuild {}
:
android {
...
defaultConfig {...}
buildTypes {...} // Encapsulates your external native build configurations.
externalNativeBuild { // Encapsulates your CMake build configurations.
cmake { // Provides a relative path to your CMake build script.
path "CMakeLists.txt"
}
}
}
可选配置
你可以在你的 module 层级的 build.gradle 文件中的 defaultConfig {}
代码块中,添加 externalNativeBuild {}
代码块,为 CMake 或 ndk-build 配置一些额外参数。当然,你也可以在你的构建配置中的其他每一个生产渠道重写这些属性。
比如,如果你的 CMake 或者 ndk-build 项目中定义了多个本地库,你想在某个生产渠道使用这些本地库中的几个,你就可以使用 targets
属性来构建和打包。下面的代码展示了一些你可能会用到的属性:
android {
...
defaultConfig {
...
// This block is different from the one you use to link Gradle
// to your CMake or ndk-build script.
externalNativeBuild { // For ndk-build, instead use ndkBuild {}
cmake { // Passes optional arguments to CMake.
arguments "-DCMAKE_VERBOSE_MAKEFILE=TRUE" // Sets optional flags for the C compiler.
cFlags "-D_EXAMPLE_C_FLAG1", "-D_EXAMPLE_C_FLAG2" // Sets a flag to enable format macro constants for the C++ compiler.
cppFlags "-D__STDC_FORMAT_MACROS"
}
}
} buildTypes {...} productFlavors {
...
demo {
...
externalNativeBuild {
cmake {
...
// Specifies which native libraries to build and package for this
// product flavor. If you don't configure this property, Gradle
// builds and packages all shared object libraries that you define
// in your CMake or ndk-build project.
targets "native-lib-demo"
}
}
} paid {
...
externalNativeBuild {
cmake {
...
targets "native-lib-paid"
}
}
}
} // You use this block to link Gradle to your CMake or ndk-build script.
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
}
指定 ABI
一般情况下,Gradle 会将你的本地库构建成 .so
文件,然后将其打包到你的 APK 中。如果你想 Gradle 构建并打包某个特定的 ABI 。你可以在你的 module 层级的 build.gradle 文件中使用 ndk.abiFilters
标签来指定他们:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
} ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
'arm64-v8a'
}
}
buildTypes {...}
externalNativeBuild {...}
}
大多数情况,你只需要像上面的代码那样,在 ndk {}
代码块中指定 abiFilters
即可。如果你想控制 Gradle 构建、依赖你希望的东西,你就需要在 defaultConfig.externalNativeBuild.cmake {}
代码块或 defaultConfig.externalNativeBuild.ndkBuild {}
代码块中,配置其他的 abiFilters
标签。Gradle 会构建这些 ABI 配置,但是只会将 defaultConfig.ndk {}
代码块中指定的东西打包到 APk 中。
android studio 使用CMAKE的更多相关文章
- android studio使用CMake和NDK,实现应用自身被卸载时打开某一网址
实现应用自身被卸载时打开某一网址的c代码 MyActivity: public class MyActivity extends Activity { /** * Called when the ac ...
- 【Android Studio安装部署系列】二十五、Android studio使用NDK生成so文件和arr文件
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 Android Studio使用ndk的简单步骤. NDK环境搭建 下载NDK 下载链接:https://developer.and ...
- OpenCV - Android Studio 2.2 中利用CAMKE进行OpenCV的NDK开发
我在http://www.cnblogs.com/fx-blog/p/8206737.html一文中提到了如何在Android Studio中Java层导入OpenCV(包含opencv_contri ...
- Android开发学习之路--Android Studio cmake编译ffmpeg
最新的android studio2.2引入了cmake可以很好地实现ndk的编写.这里使用最新的方式,对于以前的android下的ndk编译什么的可以参考之前的文章:Android开发学习之路– ...
- 通过android studio的gradle强制cmake输出命令详情
https://stackoverflow.com/questions/43439549/force-cmake-in-verbose-mode-via-gradle-and-the-android- ...
- 将应用代码由eclipse导入Android studio的方法NDK-Build和Cmake两种方法(以android_serialport_api为例)
网上翻了几百篇博客,看了半天,要不就是写的乱七八糟看不懂,要不就是隐藏了一些细节,要不就是实现不了,最后还是在Android官网上看明白了,而且说得有条有理,以后遇到不懂的一定要先翻官网. 参考资料: ...
- android ndk-build 编译静态库libxx.a 以及Android studio openssl 静态库配置(cmake)
android ndk-build 编译静态库libxx.a 需求场景: 目前有安卓编码好的现在的openssl的两个.a,我们需要调用openssl的函数,并把功能再封装成.a; 这样使用时,在an ...
- Android Studio 2.2以上支持了Cmake的配置JNI的相关参数
Android Studio 2.2以上支持了Cmake的配置JNI的相关参数,简化了通过Android.mk配置.并很好的继承了C++的编辑方式.以下是对应的引入第三方so和第三方.cpp文件的路径 ...
- Android Studio中通过CMake使用NDK并编译自定义库和添加预编译库
Note:这篇文章是基于Android Studio 3.01版本的,NDK是R16. step1:创建一个包含C++的项目 其他默认就可以了. C++ Standard 指定编译库的环境,其中Too ...
随机推荐
- delphi7中添加QuickRep
具体的方法是: delphi主菜单的Project|Options命令, 在Package选项卡的Desing packages列表中如果可以看到QuickReport Components选项, 那 ...
- Office密码破解不求人!
你用Office吗?你会为你的Office文档加密吗?如果Office密码忘了求人吗?最后一个问题是不是让你很头大,求人办事不是要费钱就是要靠人情,不如自己拥有一款强大的密码破解工具,想要Office ...
- 使用matlab批量处理图像后在指定文件夹存储
使用matlab批量处理图像后在指定文件夹存储 clear;clc;close all; Files=dir('D:\文件及下载相关\文档\MATLAB\postgraduate\Kodak\*.jp ...
- Java精选笔记_其他IO流(ObjectInputStream、DataInputStream、PrintStream、标准输入输出流)
其他IO流 ObjectInputStream和ObjectOutputStream 如果希望永久将对象转为字节数据写入到硬盘上,即对象序列化,可以使用ObjectOutputStream(对象输出流 ...
- 多线程模块:threading
threading 常见用法: (1) 在 thread 中,我们是通过 thread.start_new_thread(function, args) 来开启一个线程,接收一个函数和该函数的参数,函 ...
- Objective-C中的KVC与KVO(上)
本文转载 李朴之先生博客 http://blog.csdn.net/pucker/article/details/7413280 Objective-C中的KVC与KVO是两种比较重要的技术,这里简要 ...
- cocos2dx游戏--欢欢英雄传说--为敌人添加移动和攻击动作
这里主要为敌人添加了一个移动动作和攻击动作.移动动作是很简略的我动他也动的方式.攻击动作是很简单的我打他也打的方式.效果:代码: #ifndef __Progress__ #define __Prog ...
- iOS-利用插件实时刷新模拟器(提高效率)
解决办法: 1.需要给Xcode安装一个Alcatraz插件 安装完成后:点击window 下面的 package manager 安装我们今天的主角 2. ‘Injection Plugin for ...
- Django restframwork
REST介绍 全称Representational State Transfer,即表现层状态转换,如果一个架构符合REST原则,我们就称他为Restfull架构,其主要包括如下方面: 资源Resou ...
- php 数据库练习之租房子
题目: 示例图 本次只做图4这个表,因为之前的都已做过 自己在mydb数据库建了一个house表 如图: 自己做的代码: <!DOCTYPE html PUBLIC "-//W3C// ...