NDK编程--鸟瞰
目录
- 什么场景下需要NDK
- 基本概念
什么场景下需要NDK
- 项目需要调用底层的一些C/C++的一些东西(java无法直接访问到操作系统]底层(如系统硬件等),需要在su上执行的脚本等情况),或者使用成熟的C/C++开源库。NDK开发常用于驱动开发、无线热点共享、数学运算、实时渲染的游戏、音视频处理、文件压缩、人脸识别、图片处理等。
- 效率角度:将要求高性能的应用逻辑使用C/C++开发,从而提高应用程序的执行效率。但是C/C++代码虽然是高效的,在java与C/C++相互调用时却增大了开销;
- 安全角度考虑。防止代码被反编译,为了安全起见,使用C/C++语言来编写重要的部分以增大系统的安全性,最后生成so库(用过第三方库的应该都不陌生)便于给人提供方便。(任何有效的代码混淆对于会smail语法反编译你apk是分分钟的事,即使你加壳也不能幸免高手的攻击)
- 跨平台,便于移植。用C/C++写得库可以方便移植到其他嵌入式平台。
基本概念
** NDK**:Native Development Kit,是一系列工具的集合。可以把c/c++ ->编译成一个Linux下可以执行的二进制文件Java代码里面就可以通过jni调用执行二进制的文件。它提供了一系列的工具,帮助开发者快速开发C/C++的动态库,并能自动将so和Java一起打包成apk。
JNI:Java Native Interface,标准是java平台的一部分,JNI是Java语言提供的Java和C/C++相互沟通的机制。
so:shared object,即共享库,ELF(Executable and Linkable Format,在计算机科学中,是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件,是UNIX作为ABI而发布的可执行文件)文件是Linux下的动态链接库,类似于Windows下的dll。生成so文件,主要通过GCC编译将.c转成.o,然后通过GCC链接将.o转成.so。库文件分为动态库和静态库,.a为静态库。
ABI:Application Binary Interface,实际就是指应用程序基于哪种指令集来进行编译,能用到的ABI 也就四种 armeabi,armeabi-v7a ,x86 和mips ,前两者是比较常见。
- armeabi,默认选项,将创建以基于 ARM* v5TE 的设备为目标的库。 具有这种目标的浮点运算使用软件浮点运算。 使用此 ABI 创建的二进制代码将可以在所有 ARM* 设备上运行。
- armeabi-v7a’创建支持基于 ARM* v7 的设备的库,并将使用硬件 FPU 指令。
- x86 生成的二进制代码可支持包含基于硬件的浮点运算的 IA-32 指令集.
- mips 支持应用二进制接口
APP_ABI 就是为了交叉编译生成相应芯片可执行的指令集。直观的看就是如果你将APP_ABI := armeabi armeabi-v7a mips x86,那么android工程下边的 libs 里边会出现 armeabi armeabi-v7a mips x86 这四个目录下会分别生成 4个.so文件。程序在Android手机运行时,根据手机自身CPU芯片不同,去选择调用相应的.so文件。
Android.mk:向生成系统描述你的源代码
----------start----------
# Copyright (C) 2009 The Android Open Source Project
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
----------end----------
//LOCAL_PATH := $(call my-dir) 给出当前文件的路径,my-dir返回当前Android.mk所在目录的路径
//include $(CLEAR_VARS) 指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量。CLEAR_VARS:指向一个编译脚本。这个必须在开始一个新模块之前包含
//LOCAL_MODULE := hellojni_shared 这个模块的名字,它必须是唯一的,而且不能包含空格
//LOCAL_MODULE_FILENAME := libhellojni 设置你的模块的二进制文件的名称,独立于LOCAL_MODULE
//LOCAL_SRC_FILES := hellocpp/main.cpp \ ../../Classes/AppDelegate.cpp
//include $(BUILD_SHARED_LIBRARY). BUILD_SHARED_LIBRARY表示编译生成共享库(动态库),是编译系统提供的变量,指向一个GNU Makefile脚本,负责收集自从上次调用'include $(CLEAR_VARS)'以来,定义在LOCAL_XXX变量中的所有信息,并且决定编译什么,如何正确地去做。
Application.mk:描述你的工程下的native模,一般在$PROJECT/jni/,这样可以被ndk-build脚本。这个文件可以不写。
//1.指定application里要链接的标准c++库
APP_STL := gnustl_static
//2.编译选项
APP_CPPFLAGS := -frtti -DCC_ENABLE_CHIPMUNK_INTEGRATION=1 -DCOCOS2D_DEBUG=1