NDK 编译可执行程序( 独立编译)(一)

什么是NDK?

定义:Native Development Kit,是Android的一种开发工具包(其实就是在安卓平台编写C和C++程序的开发包

作用:最主要的就是开发so库了,c或c++代码编译成动态链接库供java代码调用

优点:

运行效率高
代码安全性高
跨平台

使用场景

对性能要求比较高或者对安全要求比较高的Android程序可以使用NDK

ndk下载链接:https://developer.android.google.cn/ndk/downloads/
使用之后请自行配置环境变量

编写可执行程序

  • 创建一个目录(这里我创建目录为jni)
    image.png

    目录中有三个文件Android.mk,Application.mk,hello-jni.c
    下面我们分别介绍一下这三个文件
  • hello-jni.c
#include 
 int main()
{
    printf("Hello Android!\n");
    return 0;
}

hello-jni.c是源码文件,编写c或者c++代码

  • Application.mk
#### 0APP_ABI := arm64-v8a 后面接的是需要生成的.so平台文件,
#### 正常手机使用arm64处理器的即可。 all是全平台
#### APP_PLATFORM :=后面接的是使用SDK的最低等级
APP_ABI := all

Application.mk为指定平台文件

  • Android.mk
# 一个Android.mk file首先必须定义好LOCAL_PATH变量。
# 它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 
# 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。
LOCAL_PATH := $(call my-dir)
# CLEAR_VARS由编译系统提供,
# 指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,
# 因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
include $(CLEAR_VARS)
# LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。
# 注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'foo'的共享库模块,将会生成'libfoo.so'文件。
LOCAL_MODULE    := hello-jni
# LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包含文件,
# 因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。
LOCAL_SRC_FILES := hello-jni.c
# BUILD_EXECUTABLE 表示以一个可执行程序的方式进行编译
# BUILD_SHARED_LIBRARY 表示动态链接库的方式进行编译
include $(BUILD_EXECUTABLE)

Android.mk指定编译的一些参数(注释比较详细)

使用ndk-build

  • 进入到创建的jni目录使用ndk-build编译


    image.png
  • 在jni同级目录下会出现libs文件夹,进入该文件夹如下:
    image.png

    可以看到所有的平台,这里我们使用armeabi-v7a的,因为我们的虚拟机是armeabi-v7a
    注意:这里一定要创建arm架构的虚拟机,因为我们的Android手机基本都是arm架构的
    image.png
  • 进入armeabi-v7a文件夹可以看到有编译好的可执行程序:


    image.png
  • 下面就是将这个可执行程序push到手机上,然后运行它了(先启动安卓虚拟机)
#进入手机shell
adb shell
#创建文件夹
mkdir /data/tmp/
#退出shell
exit
#push可执行程序进入手机(这里路径根据自己的修改)
adb push C:\Users\15079\Desktop\libs\armeabi-v7a\hello-jni /data/tmp
#再次进入手机shell
adb shell
#进入到可执行程序的文件夹
cd /data/tmp
#给权限
chmod 777 hello-jni
#运行
./hello-jni

最后结果如下:


image.png

尾言

这里我们编写一个简单的NDK可执行程序作为例子,真正的情况一般是编译为so库,我将在下一章使用eclipse+NDK编写一个简单的so库,并使用JNI技术在java中调用这个so库,这也是我们项目中一般使用到的场景。
在IDA反汇编中so库的源码将变成ARM汇编代码,而不是Intel X86的汇编,所以我们有必要学习一下ARM汇编

ARM手册(需翻墙)
https://docs.google.com/viewer?url=http%3A%2F%2Fwww.scss.tcd.ie%2F%7Ewaldroj%2F3d1%2Farm_arm.pdf

你可能感兴趣的:(NDK 编译可执行程序( 独立编译)(一))