Android:NDK的简单使用

斟酌参考


JNI可以把c程序按照格式,封装成java可以调用的函数接口。

1、javac 生成 .class文件

2、javah -jni 生成 .h文件

3、根据.h文件,修改.c文件。

NDK则是把通过JNI封装之后,把.c文件通过一定的规则编译成库的工具。

1、这里的规则是指:Android.mk文件。

2、可以编译为动态库,也可以编译为静态库。

1、NDK下载:

https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip

这里下载的是目前最新版本的:r14b

2、配置环境

下面进行环境配置

ubuntu14.04下新建/usr/local/ndk目录,

① :把刚才下载的ndk源码包,拷贝到 该目录下,解压。

②:打开~/.bashrc文件,在文件最后,添加如下内容:

export PATH=/usr/local/ndk/android-ndk-r14b/:$PATH 

使用source ~/.bashrc 命令,更新环境变量。

3、测试NDK

ubuntu下使用如下命令,测试ndk是否配置正确:

root@ubuntu:/neo/c# ndk-build -v
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for x86_64-pc-linux-gnu
root@ubuntu:/neo/c#

如上所示,ndk环境配置完成。

4、通过NDK编译动态库

为了便于理解,在JNI的基础上编译动态库。

JNI程序的参考链接:

https://blog.csdn.net/weixin_38184741/article/details/91461231

4.1 Android.mk配置文件

使用ndk-build工具进行ndk编译时,需要按照配置文件中的规则进行编译。这里说的配置文件就是Android.mk文件。

Android.mk的内容为:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE:= HelloWorldNDK
LOCAL_SRC_FILES:= HelloWorld.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_EXPORT_LDLIBS := -llog

#include $(BUILD_STATIC_LIBRARY)
include $(BUILD_SHARED_LIBRARY)

其中:

LOCAL_PATH:= $(call my-dir) 表示当前目录。

include $(CLEAR_VARS) 表示清除之前的配置。一般和

include $(BUILD_STATIC_LIBRARY)	
include $(BUILD_SHARED_LIBRARY)
include $(PREBUILT_STATIC_LIBRARY)
include $(PREBUILT_SHARED_LIBRARY)

配合使用(应该还有其他的,我没有深入研究。我的理解是清除之前模块的配置(LOCAL_PATH除外))。

LOCAL_MODULE 表示编译出的库的名称

LOCAL_SRC_FILES 表示源文件的路径以及命令

LOCAL_EXPORT_C_INCLUDES 表示头文件所在目录。

LOCAL_EXPORT_LDLIBS表示需要加载的标准库。-llog 表示加载 liblog库,用于输出调试信息。

include $(BUILD_SHARED_LIBRARY)表示编译成动态库,

include $(BUILD_STATIC_LIBRARY) 表示编译成静态库,这里我们给屏蔽了。静态库一般都很大。

4.2 编译NDK

下面编译NDK动态库,配置文件就是上面所示。

root@ubuntu:~/ken/jni# ndk-build 
[arm64-v8a] Compile: HelloWorldNDK <= HelloWorld.c
In file included from /root/ken/jni/HelloWorld.c:1:
/root/ken/jni/jni.h:45:10: fatal error: 'jni_md.h' file not found
#include "jni_md.h"
 ^
1 error generated.
make: *** [/root/ken/obj/local/arm64-v8a/objs/HelloWorldNDK/HelloWorld.o] Error 1

显示找不到jni中引用的头文件,之前我们是使用-I参数,加载头文件路径解决的。

现在我们可以把jni.h文件删除掉,因为ndk的库中也有jni.h头文件。

删除jni.h文件之后,继续编译。

root@ubuntu:~/ken/jni# ndk-build 
[arm64-v8a] Compile: HelloWorldNDK <= HelloWorld.c
[arm64-v8a] SharedLibrary  : libHelloWorldNDK.so
[arm64-v8a] Install: libHelloWorldNDK.so => libs/arm64-v8a/libHelloWorldNDK.so
[x86_64] Compile: HelloWorldNDK <= HelloWorld.c
[x86_64] SharedLibrary  : libHelloWorldNDK.so
[x86_64] Install: libHelloWorldNDK.so => libs/x86_64/libHelloWorldNDK.so
[mips64] Compile: HelloWorldNDK <= HelloWorld.c
[mips64] SharedLibrary  : libHelloWorldNDK.so
[mips64] Install: libHelloWorldNDK.so => libs/mips64/libHelloWorldNDK.so
[armeabi-v7a] Compile thumb  : HelloWorldNDK <= HelloWorld.c
[armeabi-v7a] SharedLibrary  : libHelloWorldNDK.so
[armeabi-v7a] Install: libHelloWorldNDK.so => libs/armeabi-v7a/libHelloWorldNDK.so
[armeabi] Compile thumb  : HelloWorldNDK <= HelloWorld.c
[armeabi] SharedLibrary  : libHelloWorldNDK.so
[armeabi] Install: libHelloWorldNDK.so => libs/armeabi/libHelloWorldNDK.so
[x86] Compile: HelloWorldNDK <= HelloWorld.c
[x86] SharedLibrary  : libHelloWorldNDK.so
[x86] Install: libHelloWorldNDK.so => libs/x86/libHelloWorldNDK.so
[mips] Compile: HelloWorldNDK <= HelloWorld.c
[mips] SharedLibrary  : libHelloWorldNDK.so
[mips] Install: libHelloWorldNDK.so => libs/mips/libHelloWorldNDK.so
root@ubuntu:~/ken/jni# 

发现不是在当前目录下生成库文件,而是在前一目录下。这个不符合我们的习惯。

ndk-build clean后,添加参数,继续编译:

root@ubuntu:~/ken/jni# 
root@ubuntu:~/ken/jni# ndk-build clean
[arm64-v8a] Clean  : HelloWorldNDK [arm64-v8a]
[arm64-v8a] Clean  : stdc++ [arm64-v8a]
[x86_64] Clean  : HelloWorldNDK [x86_64]
[x86_64] Clean  : stdc++ [x86_64]
[mips64] Clean  : HelloWorldNDK [mips64]
[mips64] Clean  : stdc++ [mips64]
[armeabi-v7a] Clean  : HelloWorldNDK [armeabi-v7a]
[armeabi-v7a] Clean  : stdc++ [armeabi-v7a]
[armeabi] Clean  : HelloWorldNDK [armeabi]
[armeabi] Clean  : stdc++ [armeabi]
[x86] Clean  : HelloWorldNDK [x86]
[x86] Clean  : stdc++ [x86]
[mips] Clean  : HelloWorldNDK [mips]
[mips] Clean  : stdc++ [mips]
root@ubuntu:~/ken/jni# ndk-build NDK_PROJECT_PATH=. 
Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk
/usr/local/ndk/android-ndk-r14b/build/core/add-application.mk:198: *** Android NDK: Aborting....  Stop.
root@ubuntu:~/ken/jni# ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk 
[arm64-v8a] Compile: HelloWorldNDK <= HelloWorld.c
[arm64-v8a] SharedLibrary  : libHelloWorldNDK.so
[arm64-v8a] Install: libHelloWorldNDK.so => libs/arm64-v8a/libHelloWorldNDK.so
[x86_64] Compile: HelloWorldNDK <= HelloWorld.c
[x86_64] SharedLibrary  : libHelloWorldNDK.so
[x86_64] Install: libHelloWorldNDK.so => libs/x86_64/libHelloWorldNDK.so
[mips64] Compile: HelloWorldNDK <= HelloWorld.c
[mips64] SharedLibrary  : libHelloWorldNDK.so
[mips64] Install: libHelloWorldNDK.so => libs/mips64/libHelloWorldNDK.so
[armeabi-v7a] Compile thumb  : HelloWorldNDK <= HelloWorld.c
[armeabi-v7a] SharedLibrary  : libHelloWorldNDK.so
[armeabi-v7a] Install: libHelloWorldNDK.so => libs/armeabi-v7a/libHelloWorldNDK.so
[armeabi] Compile thumb  : HelloWorldNDK <= HelloWorld.c
[armeabi] SharedLibrary  : libHelloWorldNDK.so
[armeabi] Install: libHelloWorldNDK.so => libs/armeabi/libHelloWorldNDK.so
[x86] Compile: HelloWorldNDK <= HelloWorld.c
[x86] SharedLibrary  : libHelloWorldNDK.so
[x86] Install: libHelloWorldNDK.so => libs/x86/libHelloWorldNDK.so
[mips] Compile: HelloWorldNDK <= HelloWorld.c
[mips] SharedLibrary  : libHelloWorldNDK.so
[mips] Install: libHelloWorldNDK.so => libs/mips/libHelloWorldNDK.so
root@ubuntu:~/ken/jni# 
root@ubuntu:~/ken/jni# ls
Android.mk  HelloWorld.c  HelloWorld.class  HelloWorld.h  HelloWorld.java  libHelloWorld.so  libs  obj
root@ubuntu:~/ken/jni# 

由上面可以,我们在使用ndk-build时,添加了两个参数NDK_PROJECT_PATHAPP_BUILD_SCRIPT,用于指定工程路径,以及配置文件路径。

查看编译出的库的情况:

root@ubuntu:~/ken/jni/libs# file */*
arm64-v8a/libHelloWorldNDK.so:   ELF 64-bit LSB  shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=a63502fc8bb3907cd4f122d6aa1867b7423dc7dd, stripped
armeabi/libHelloWorldNDK.so: ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=56d98623f4f90a52ca681bd88768c520a999b722, stripped
armeabi-v7a/libHelloWorldNDK.so: ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=f66ea129183665d8384f0df51dbe3c655890b35e, stripped
mips64/libHelloWorldNDK.so:  ELF 64-bit LSB  shared object, MIPS, version 1 (SYSV), dynamically linked, BuildID[sha1]=087e1f1cd4859a68c7ea2a06c6932cd10cbb87dc, stripped
mips/libHelloWorldNDK.so:ELF 32-bit LSB  shared object, MIPS, MIPS32 version 1 (SYSV), dynamically linked, BuildID[sha1]=d49923384cc67942af6f3b1dd83fa7a89a4c1139, stripped
x86_64/libHelloWorldNDK.so:  ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=fa7710bd5ce6964995bcc8be52aadcd422cf8acb, stripped
x86/libHelloWorldNDK.so: ELF 32-bit LSB  shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=f91da4f4c467ebd8cf4b28d237336a48a719d308, stripped
root@ubuntu:~/ken/jni/libs# cd ../obj/
root@ubuntu:~/ken/jni/obj# tree */*
local/arm64-v8a
├── libHelloWorldNDK.so
└── objs
└── HelloWorldNDK
├── HelloWorld.o
└── HelloWorld.o.d
local/armeabi
├── libHelloWorldNDK.so
└── objs
└── HelloWorldNDK
├── HelloWorld.o
└── HelloWorld.o.d
local/armeabi-v7a
├── libHelloWorldNDK.so
└── objs
└── HelloWorldNDK
├── HelloWorld.o
└── HelloWorld.o.d
local/mips
├── libHelloWorldNDK.so
└── objs
└── HelloWorldNDK
├── HelloWorld.o
└── HelloWorld.o.d
local/mips64
├── libHelloWorldNDK.so
└── objs
└── HelloWorldNDK
├── HelloWorld.o
└── HelloWorld.o.d
local/x86
├── libHelloWorldNDK.so
└── objs
└── HelloWorldNDK
├── HelloWorld.o
└── HelloWorld.o.d
local/x86_64
├── libHelloWorldNDK.so
└── objs
└── HelloWorldNDK
├── HelloWorld.o
└── HelloWorld.o.d

14 directories, 21 files
root@ubuntu:~/ken/jni/obj# 

此时编译出的库就可以给app调用了。

你可能感兴趣的:(Android)