NDK学习

1.下载NDK

官网下载地址: http://developer.android.com/ndk/downloads/index.html
国内下载地址: http://www.androiddevtools.cn/

2.安装NDK

因为我用的是Ubuntu14.04
需要执行命令解压下载的bin包:
1.chmod a+x android-ndk-r10d-linux-x86_64.bin
2. ./android-ndk-r10d-linux-x86_64.bin
(在windows下直接解压即可)

3.配置环境

使用命令:sudo gedit /etc/profile打开配置文件,添加以下的代码,对应的ndk目录替换就可以
export NDK_HOME=/home/cgc/软件/android-ndk-r10d

export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$NDK_HOME:$PATH  
(此处需要重启电脑,并且PATH需要在NDK_HOME之后) 
   然后,配置eclipse
选择 Window > Preferences>Android>NDK,配置刚刚解压的NDK的所在目录.  

4.校验NDK配置是否正确

首先,在ndk/samples目录下有一个官方提供的demo,有一个hello-jni项目,在eclipse中导入这个项目.
方式1:  
1.右键选择导入的hello-jni目录, Android Tools > Add Native Support,选择"hello-jni",点击完成.  
2.运行项目,看到界面上显示Hello from JNI ! Compiled with ABI.+对应的平台就表示配置完成  
方式2:  
1.打开命令窗口,cd到导入项目的根目录,调用ndk-build命令编译  
2.刷新项目,运行项目,看到上面方式1的结果就是配置完成了.

5.关于ABI

5.1 什么是ABI

现在环境配置好了,现在我们就开始看看如何进行ndk的开发了,首先,我们先看看,在所谓的交叉编译之后,到底生成了什么东西.在经过以上的第四步之后,我们可以看到在项目中新增了obj/local和libs下的很多包,如:
- armeabi
- armeabi-v7a
- arm64-v8a
- x86
- x86_64
- mips
- mips64

这些文件名是什么意思呢,我们从官网可以看到,这些文件名对应的就是ABI(Application Binary Interface),中文名字是应用二进制接口,什么是ABI,什么鬼啊?原文是:The ABI defines, with great precision, how an application’s machine code is supposed to interact with the system at runtime.我的理解是:在运行时,应用的机器代码跟系统之间是如何交互的.它包括了以下的内容:
- 机器代码能够使用的CPU指令集.
- 运行时,内存保存和加载的字节顺序
- 可执行的二进制文件的格式
- 不同的关于你的代码和系统之间如何交换数据的约定或者协定
- 提供给你的机器代码的函数符号集合
(以上高能,我也不懂啥意思,不想看的直接略过)
我的观点是,==不同的CPU可能使用不一样的ABI,根据具体的机子配上对应的ABI就好,==例如64位的cpu跟32位之间,两者使用的ABI肯定是不一样的吧.所以对上号就好.

5.2 怎样生成的ABI

ndk默认会帮我们编译生成armeabi这种的ABI,我们可以通过在jni目录下添加一个Application.mk的文件,并在文件中来指定要编译的ABI,例如:
- APP_ABI := armeabi-v7a 就代表生成armabi-v7a的ABI
- APP_ABI := armeabi armeabi-v7a 就代表生成 armeabi armeabi-v7a两种ABI,两者以空格分开.

5.3 apk如何选择ABI

当前的设备中会有两种可支持的ABI,为主要ABI和次要ABI,系统会在安装apk文件时,会扫描apk包中对应的主要ABI目录lib//lib.so,如果主要ABI目录没有,就会继续扫描次要ABI目录lib//lib.so,如果有的话,就会拷贝到data/data//lib/目录中,如果两者都没有的话,当应用运行时就会崩溃.

系统是以这种规则去选择ABI的,例如:ARMv7-based的设备就以armeabi-v7a为主要ABI,以armeabi为次要ABI
但是,并不是所有设备都支持两种ABI,例如:一个典型的MIPS-based的设备就仅仅支持mips这种ABI

6 生成ABI的配置文件

6.1Android.mk文件

一个简单的demo:

    LOCAL_PATH := $(call my-dir)  
    include $(CLEAR_VARS)  
    LOCAL_MODULE    := hello-jni  
    LOCAL_SRC_FILES := hello-jni.c  
    include $(BUILD_SHARED_LIBRARY)  

现在一个一个解释什么意思:
LOCAL_PATH := $(call my-dir)
Android.mk文件必须以LOCAL_PATH开头,调用一个叫my-dir的宏来获取当前Android.mk文件所在的文件夹
include $(CLEAR_VARS)
声明CLEAR_VARS变量是为了清除构建文件中的一些本地的变量(像LOCAL_MODULE,LOCAL_SRC_FILES等),但是LOCAL_PATH除外,这是因为所有的构建文件需要合并成一个文件,而在这一个文件中,这些本地变量是全局变量.
LOCAL_MODULE := hello-jni
LOCAL_MODULE这个变量是必须要定义的,且必须是唯一不含空格的名字.会生成lib+LOACL_MODULE+.so的库
注意:如果你的LOCAL_MODULE是以lib开头的,那么在编译之后的库文件名不会在添加lib的前缀.
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES中需要罗列你需要编译的c或者c++文件的列表,需要注意的是,你并不需要将依赖的文件或者头文件罗列在此,因为编译系统会自动帮你导入.注意:一般c++的源代码文件是以.cpp结尾的,在这里你可以通过自定义LOCAL_CPP_EXTENSION这个变量来改变c++代码的后缀名(需要添加.eg: .xdd有效,而xdd则无效)
include $(BUILD_SHARED_LIBRARY)
这里的BUILD_SHARED_LIBRARY代表要生成一个动态库,BUILD_STATIC_LIBRARY则代表一个静态库,编译系统会收集所有的LOCAL信息,知道最后一个include出现,来知道如何进行编译,需要进行那些操作.
更多复杂的配置请参考NDK提供的demo(NDK目录中的samples中)以及官方文档.

6.2 Application.mk文件

在上面5.2中就提到过,这个文件是为了指定生成什么ABI而来.所有ABI的配置如下:
- APP_ABI := armeabi-v7a
- APP_ABI := arm64-v8a
- APP_ABI := x86
- APP_ABI := x86_64
- APP_ABI := mips
- APP_ABI := mips64
或者进行组合,如:

APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a x86_64 mips64 

又或者生成所有:

APP_ABI := all

更多配置,请参考官方文档.

==注意事项==:
- 1.在选择适配的ABI的过程中,需要注意apk包大小和适配范围的考量.有一个fat binary这样一个名词,表示选用多个ABI兼容多种cpu的应用.
- 2.即使,你的应用中使用了多个ABI,在安装的时候只会解压最合适的ABI.
- 3.在4.0.3和之前的系统中,如果所有的ABI都存在的情况下,armv7的设备会从armabi目录中加载.so,原因是 This is because /lib/armeabi/ comes after /lib/armeabi-v7a/ in the APK. 反正我愣是没看懂.

你可能感兴趣的:(android,NDK)