今天终于跑完了Google协同育人项目的协议签署,茫然四顾发现自己在一个巨坑之中==
这段时间要加班加点学习NDK学习混编,我的初步的思路是利用orb-SLAM算法进行建模,拿到模型再做其他的都好说,好歹是一个开始,要接着往前走。
下面就开始将我学习的过程中一些笔记和心得记录下来。
相关概念
首先我们要使用的工具是NDK
使用
Android NDK
可以构建任何一段原生代码将其与Android应用一起打包。
什么是NDK
Native Development Kit(NDK)是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C/C++的动态库,并能自动将so和java一起打包成apk。
详情查看官方文档:https://developer.android.com/ndk/index.html
(实际上Android Developer官方提供的只有
Android.mk
和Application.mk
对项目构建的方法==,后面再仔细叙述)
而使用java原生接口(JNI
,Java Native Interface
)可以实现java应用程序和原生代码之间的通信。
什么是JNI
Java Native Interface(JNI)标准是java平台的一部分,JNI是Java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用C/C++代码,C/C++的代码也可以调用java代码。
我们主要说说在项目中使用java调用cpp的方法
想要用java调用cpp首先要解决的一个问题是,必须要让cpp函数按着命名规则来。
命名规则为:
|
|
对应如下:1jint Java_com_ndk_testndk_TestHello_jnia(JNIEnv* env,jobject obj);
其中第二个参数为该类的对象,也就是TestHello的对象
|
|
|
|
JNI与NDK的关系
NDK可以为我们生成了C/C++的动态链接库,JNI是java和C/C++沟通的接口,两者与android没有半毛钱关系,只因为安卓是java程序语言开发,然后通过JNI又能与C/C++沟通,所以我们可以使用NDK+JNI来实现“Java+C”的开发方式。
为什么要NDK开发
NDK开发具有以下优点:
- 项目需要调用底层的一些C/C++的一些东西(java无法直接访问到操作系统底层(如系统硬件等)),或者已经在C/C++环境下实现了功能代码(大部分现存的开源库都是用C/C++代码编写的。),直接使用即可。NDK开发常用于驱动开发、无线热点共享、数学运算、实时渲染的游戏、音视频处理、文件压缩、人脸识别、图片处理等。
- 为了效率更加高效些。将要求高性能的应用逻辑使用C/C++开发,从而提高应用程序的执行效率。但是C/C++代码虽然是高效的,在java与C/C++相互调用时却增大了开销;
- 基于安全性的考虑。防止代码被反编译,为了安全起见,使用C/C++语言来编写重要的部分以增大系统的安全性,最后生成so库(用过第三方库的应该都不陌生)便于给人提供方便。(任何有效的代码混淆对于会smail语法反编译你apk是分分钟的事,即使你加壳也不能幸免高手的攻击)
- 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。
什么是CMake
脱离 Android 开发来看,c/c++的编译文件在不同平台是不一样的。Unix下会使用
makefile
文件编译,Windows下会使用 project 文件编译。而CMake
则是一个跨平台的编译工具,它并不会直接编译出对象,而是根据自定义的语言规则(CMakeLists.txt
)生成对应makefile
或project
文件,然后再调用底层的编译。
在Android Studio 2.2 之后,工具中增加了CMake
的支持,你可以这么认为,在 Android Studio 2.2 之后你有2种选择来编译你写的c/c++代码。一个是ndk-build
+Android.mk
+Application.mk
组合,另一个是CMake
+CMakeLists.txt
组合。这2个组合与Android代码和c/c++代码无关,只是不同的构建脚本和构建命令。
更多详细的参见AndroidStudio官方文档。
ABI是什么
ABI
(Application binary interface)应用程序二进制接口。不同的CPU 与指令集的每种组合都有定义的 ABI (应用程序二进制接口),一段程序只有遵循这个接口规范才能在该 CPU 上运行,所以同样的程序代码为了兼容多个不同的CPU,需要为不同的 ABI 构建不同的库文件。当然对于CPU来说,不同的架构并不意味着一定互不兼容。
armeabi设备只兼容armeabi;//默认都是这个,大多数的Android手机
armeabi-v7a设备兼容armeabi-v7a、armeabi;
arm64-v8a设备兼容arm64-v8a、armeabi-v7a、armeabi;
X86设备兼容X86、armeabi;
X86_64设备兼容X86_64、X86、armeabi;
mips64设备兼容mips64、mips;
mips只兼容mips;
通过一个例子来说明
github仓库链接
我在这个例子里自己模拟了一个cpp写的第三方库,通过NDK打包成apk,在CPP和java之间使用JNI层来调用Cpp库中的方法;并且配置了
Gradle
和Cmakelist
.在这个项目里,我通过项目本身的示例作用和一些注释,标注了一些容易出现问题的地方和值得注意的地方。
详细的问题还是看项目吧。