关于在Android中使用CMake你所需要了解的一切(一)
相信大家在开发的过程中,都或多或少的接触过JNI,然后每次要接触JNI的时候,倒吸一口冷气,太难啦!
只有Java代码和C++代码 还好,在新建项目的时候把那个 "Include C++ support"勾选上,然后一路next,最后finish,一个简单的带有C++代码的Android项目就算完成了,然后在看下CMakeLists.txt怎么写的,照猫画虎就可以了,但是实际开发中,并不简单,因为底层(C++)那里给过来的有可能是.a静态库,也有可能是.so动态库,然后如何集成进项目里就是:一脸懵逼,二脸茫然,三脸不知所措。由于客观事实只能去百度,然后百度到的全是用Android.mk实现的居多,然而现在都Android Studio 3.1+时代了,还mk?关于CMake的资料又很少,所以就有了本文。
在去年在公司还是实习的时候,老大丢给我一个.a静态库(当时并不知道这是一个静态库),很是好奇,很想知道.a是怎么构建出来的,a和so的区别又是什么,总之一大堆疑问,在转正后,也尝试过要构建一个.a静态库,无奈!百度到的都是用mk的咯,找到一篇CMake的,但竟然要去Linux下面编译,还要什么自定义工具链,总之,麻烦的一批。
所以就有了这一系列,本系列不阐述什么是CMake,什么是NDK,什么是JNI,只是写一下在Android中使用CMake常遇的问题,解决方法是什么。
本系列涉及到的有:
- 初次使用CMake构建native项目
- 如何将现有的cpp代码集成到项目中
- 拷贝源码
- 编译成库文件
- CMake链接a静态库以及so动态库及动态库和静态库的区别
初次使用CMake构建native项目
这个就很简单啦,新建项目的时候把 include C++ support 勾选上就可以了,但,我们还是自己动手来一遍,不依靠IDE,看看可不可以,新建普通项目,名字为:AndCmake,新建完成后如下:
新项目,什么都没有,我们都知道用CMake的话,必须要有CMakeLists.txt(注意名字不能写错),第二个就是需要的cpp资源啦,这就很简单了,在src/main目录下新建就好了,为了整洁在main目录下新建cpp文件夹,且在里面新建CMakeLists.txt和native_hello.cpp文件,然后在去CMakeLists.txt简单的配置下就好了,完成后,如下:
../src/main/cpp/native_hello.cpp:
// // Created by xong on 2018/9/28. // #include<jni.h> #include <string>extern "C" JNIEXPORT jstring JNICALL Java_com_xong_andcmake_jni_NativeFun_stringFromJNI(JNIEnv *env, jclass thiz) {std::string hello = "Hello,I from C++";return env->NewStringUTF(hello.c_str()); } 复制代码
这里需要说明以下,Java_com_xong_andcmake_jni_是去java的一层一层的包下面去寻找,比如这个就是去com.xong.andcmake.jni下面找,后面的NativeFun_stringFromJNI就是类和方法名了。函数的形参两个必须是这样的,第二个形参可以写成"jobject",我最近写JNI的时候,提示改成"jclass"但是,"jobject"也不能算错,也是对的。
../src/main/cpp/CMakeLists.txt
# CMake最低版本 cmake_minimum_required(VERSION 3.4.1) # 将需要打包的资源添加进来 add_library(# 库名字native_hello# 库类型SHARED# 包含的cppnative_hello.cpp ) # 链接到项目中 target_link_libraries(native_helloandroidlog ) 复制代码
这就把C++部分写好了
修改../app/build.gradle,修改后如下:
android {...defaultConfig {...externalNativeBuild {cmake {arguments '-DANDROID_STL=c++_static'}}...}...externalNativeBuild {cmake {path 'src/main/cpp/CMakeLists.txt'}}... } 复制代码
写对应的Java层代码,在com.xong.andcmake包下新建jni,然后新建NativeFun类,代码如下:
package com.xong.andcmake.jni;/*** Create by xong on 2018/9/28*/ public class NativeFun {static {System.loadLibrary("native_hello");}public static native String stringFromJNI(); }复制代码
调用NativeFun.stringFromJNI(),查看是否有正确的信息输出:这就很简单啦,在Activity中添加一个TextView然后显示下就好了,正确的话,应该会有如下显示:
OK,这样我们的第一个带有CPP代码的APP就算完成了,然后我们来思考一下,先来看native_hello.cpp的代码:
//
// Created by xong on 2018/9/28.
//
#include<jni.h>
#include <string>extern "C" JNIEXPORT
jstring JNICALL
// 这里可不可以优化一下?
Java_com_xong_andcmake_jni_NativeFun_stringFromJNI(JNIEnv *env, jclass thiz)
{std::string hello = "Hello,I from C++";// 这里呢?return env->NewStringUTF(hello.c_str());
}
复制代码
对于我们来讲:
- 尽量不写重复代码
- 代码要高效
对于上面的函数名来讲,Java_com_xong_andcmake_jni_,假如我们在Java中对应的native类和方法,感觉在这个包中不合适,要换下包名,但是我这个类中有很多native方法,只要一换包,那么对应的cpp中的函数名就要挨个改,函数少还好办,假如有1000个,改起来真的是不要太爽,而且容易丢,那么有没有办法来尽量的减少工作量呢?类和包是相对固定的,那么我们能不能把包名抽取出来用一个表达式来表示呢?没错!就是宏定义啦!
对于下面返回的那一句,我为啥要这样写呢,因为用Android Studio创建一个带有cpp项目的时候,里面就是这样写的,然后就很自然的抄来了,但是我们想一下,有这样写的必要吗?可以看到的是在最后返回的时候,string对象又经过了一层转换点进去后可以发现,是将 string对象又转成了char数组(当然在C++中是char*指针还是const的,这里不需要知道const是啥,只需要知道,c_str()其实是又将string对象转成了char[]数组),然后我们这样写是不是就…多此一举,让计算机多做了一些事情呢?所以改完后的代码如下:
//
// Created by xong on 2018/9/28.
//
#include<jni.h>
#define XONGFUNC(name)Java_com_xong_andcmake_jni_##nameextern "C" JNIEXPORT
jstring JNICALL
XONGFUNC(NativeFun_stringFromJNI)(JNIEnv *env, jclass thiz)
{return env->NewStringUTF("Hello,I from C++");
}
复制代码
这样的话,假如NativeFun不在jni包下了,而是在jnia包下,那么我们只需要将上面的宏定义改下就好了;
因为我们没有对string做操作,那么我们就不需要它啦,直接返回就好了,这样计算机就不那么累了。
make project后,发生了什么?
接触过JNI的同学应该了解,项目里面添加了cpp代码,apk会变的很大,那么原因嘞,那么我就来捋一捋,cpp的代码再make project后都发生了什么,都很清楚会生成so,那么…在默认的情况下会生成几个?
打开 ../app/build/intermediates/cmake/debug/obj 目录如下:
在默认的情况下会生成4个,v7a的是最大的,x86_64是最小的,默认情况下,这4个是都会打到apk里面的(因为不清楚到底是往那台手机上安装呀,只能将所有的资源都打到apk里面了),要想缩小apk,那么就把需要的so打入apk就好了。然后,问题来了,怎么才能生成规定的so库呢?上代码,如下:
apply plugin: 'com.android.application'android {...defaultConfig {...externalNativeBuild {cmake {arguments '-DANDROID_STL=c++_static'}ndk {abiFilters "armeabi-v7a", "x86"}}...}...
}
...
复制代码
在../app/build.gradle中添加ndk标签,且在里面写上需要生成的架构名称就可以了,重新build下项目,如下图:
这样打入apk中的就只有v7a和x86两种架构的so库啦! 下篇我们来讲解一下 现有的cpp代码集成到项目中有几种方式,以及如何操作。
点击跳转到下一篇:如何将现有的cpp代码集成到项目中
Demo链接:UseCmakeBuildLib
END
转载于:https://juejin.im/post/5bb025db5188255c38537198
关于在Android中使用CMake你所需要了解的一切(一)相关推荐
- 关于在Android中使用CMake你所需要了解的一切(三)
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 本篇基于上篇构建好的a静态库和so动态库,若自己有a或so那么可以直接看本篇了,若没有那么建议先去看上篇----如何将现有的cpp代 ...
- 关于在Android中使用CMake你所需要了解的一切(二)
虽然本篇和上篇没很大的关系,但-还是建议先去看下上篇----初次使用CMake构建native项目 初次使用CMake构建native项目 如何将现有的cpp代码集成到项目中 拷贝源码 编译成库文件 ...
- Android studio 使用Cmake完成C/C++ 的使用以及生成so文件
今天,简单讲讲android中关于Cmake进行NDK编程的相关知识. Android studio 2.2版本以后对C/C++的支持可以说很方便了,当然官方推荐使用Cmake完成对C/C++的支持 ...
- Android NDK开发之旅(2):一篇文章搞定Android Studio中使用CMake进行NDK/JNI开发
Android NDK开发之旅(2):一篇文章搞定android Studio中使用CMake进行NDK/JNI开发 (码字不易,转载请声明出处:http://blog.csdn.NET/andrex ...
- 【CMake】Android Studio 中使用 CMake 编译单个 C++ 源文件 ( 常用的 CMake 命令解析 )
文章目录 一.Android Studio 中使用 CMake 编译单个 C++ 源文件 二.cmake_minimum_required 命令设置最小 CMake 版本 三.project 命令设置 ...
- android studio 使用CMAKE
2019独角兽企业重金招聘Python工程师标准>>> 原文地址 前言 之前,每次需要边写C++代码的时候,我的内心都是拒绝的. 1. 它没有代码提示!!!这意味着我们必须自己手动 ...
- android中常用的快捷键
2019独角兽企业重金招聘Python工程师标准>>> android中常用的快捷键 Eclipse快捷键-方便查找,呵呵,记性不好 行注释/销注释 Ctrl+/ 块注释/销注释/ ...
- Java IO在Android中应用(三):Apk加固去壳
Java I/O在Android中应用(三):Apk加固去壳 前言(废话) 现在在动车上,因为最近接到一个紧急的出差任务,需要去一趟江苏我们移动应用的客户现场.说真的,本来其实我是很困的,但是车上有一 ...
- 【Android NDK 开发】Android Studio 使用 CMake 导入动态库 ( 构建脚本路径配置 | 指定动态库查找路径 | 链接动态库 )
文章目录 I . CMake 引入动态库与静态库区别 II . Android Studio 中 CMake 引入动态库流程 III . 指定动态库查找路径 IV . 链接函数库 V . 完整代码示例 ...
最新文章
- Oracle的一些经典SQL面试题
- BUUCTF的Web真题学习整理(一)
- kafka创建topic命令_0748-5.14.4-Kafka的扩容和缩容
- Apollo自动驾驶入门课程第②讲 — 高精地图
- C++primer第九章 顺序容器 9.4 vector对象是如何增长的
- linux进程调度之 FIFO 和 RR 调度策略
- 软件测试方法的分类细谈
- JVM参数调优详细过程
- 二阶振荡环节的谐振频率_晶振频率稳定性的两个重要因素
- MariaDB 10.3 解决掉了UPDATE不支持同一张表的子查询更新
- 运算符之前加加后加加的运算规则
- c语言常用基础代码大全,C语言基础入门必读
- 璞华PLM为全场景产品生命周期管理赋能,助力产品主线的企业数字化转型
- Ontology对接资源整理
- win10移动热点,手机无法连接或连接超时
- 深刻认识差模电压和共模电压
- Photoshop制作电影胶片效果
- 文字-汉字-生僻字:生僻字1
- 【前端】Axios完全使用指南
- 营业执照、组织机构代码、税务登记号规则
热门文章
- 8springboot-SpringBoot+MyBatisPlus
- 自动驾驶入门小记(第一篇)
- 35 岁佛系程序员,年后第一天被辞退 1
- 火狐倍速网盘视频方法(服务考研党)
- nsis查询mysql安装路径_NSIS目录
- “如何培养出优秀的IT驻场专家“
- 小学四年级上册中的计算机,小学四年级上册信息技术.doc
- RStudio的语法结构
- 四面蚂蚁金服成功拿下offer,分享一下我是怎么从年前的外包到现在的蚂蚁金服架构师的!
- 【每日随笔】利益分析法 ① ( 显性秩序和隐性秩序 | 利益分析法 | 买房行为的利益分析 | 利益博弈 | 借钱行为的利益博弈 )