1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > NDK开发入门终极教程

NDK开发入门终极教程

时间:2020-01-27 06:40:00

相关推荐

NDK开发入门终极教程

文章目录

0 前言1 准备工作1.1 下载 NDK1.2 添加NDK依赖1.3 添加cmake支持 2 新建支持NDk工程3 给工程添加NDK支持3.1 cmake3.2 ndk-build 4 实践4.1 生成头文件4.2 编写 C 源码4.3 运行截图 5 源码获取

0 前言

NDK技术的渊源始于3年前,使用so文件的时候了解到NDK技术,并且C语言一直是强项,就鼓捣起NDK开发。在AndroidStduio还没推广的年代,基于eclipse搭建NDK开发环境需要安全依赖开发工具,并且调试起来具备难度。随后AndroidStudio也先后支持nkd-buildcmake使用NDK开发。

参见之前的博客:

eclipse下使用NDK开发so库

AndroidStudio配置NDK开发环境

1 准备工作

1.1 下载 NDK

当前 NDK 稳定版已经 发布到r15c。附上各个平台的下载地址:

android-ndk-r15c-windows-x86

android-ndk-r15c-windows-x86_64

android-ndk-r15c-darwin-x86_64

android-ndk-r15c-linux-x86_64

1.2 添加NDK依赖

解压下载好的文件在本地,在 AndroidStudio 工程配置(注意不是 AndroidStudio 工具配置)中指定 NDK 路径。

或者在local.properties文件中指定NDK路径。

1.3 添加cmake支持

在 AndroidStudio 工具配置中,选择 Android SDK -> SDK Tools 中,勾选CMake并安装。

2 新建支持NDk工程

现在的AndroidStduio更支持一种极简方式集成NDK开发支持,即在下图中勾选include C++ support。然后选择C++标准。如C++ 11。建选默认的ToolChain Default

之后正常 run 即可将 C 语言部分生成出 so 文件并打包到 apk 文件中。

3 给工程添加NDK支持

上述方式适合在新的工程中添加 NDK 支持。如何要在现有的项目中添加 NDK 支持,现提供cmakendk-build两种方式。

由于在同一个工程中,同时支持cmakendk-build两种方式编译 so 文件,因此将 C 源码单独放在cpp-src目录。且将cmakendk-build区分不同的module进行编译。

3.1 cmake

这是目前最受欢迎的集成方式,AndroidStduio 在创建新工程时默认使用该方式添加 NDK 支持。但在现有的工程中添加 NDK支持,需要手动配置。

创建 cmake module 添加个三个文件。

CMakeLists.txt cmake编译配置文件

cmake_minimum_required(VERSION 3.4.1)add_library(hello-jni # so 库的名称 libhello-jni.soSHARED # 设置为分享库# 指定C源文件的路径,指向公共cpp-src目录../../../../cpp-src/hello-jni.c)find_library(log-lib # 设置路径变量名称log # 指定CMake需要加载的NDK库)# 链接hello-jni库依赖的库,注意下面变量名的配置target_link_libraries(hello-jni${log-lib})

AndroidManifest.xml 每个module必须的配置文件,指定packageName。

<?xml version="1.0" encoding="UTF-8" ?><manifest package="com.flueky.cmake"></manifest>

Build.gradle 每个module必须的配置文件,用于构建项目。

apply plugin: 'com.android.library'android {compileSdkVersion 28defaultConfig{externalNativeBuild {cmake {// 指定配置参数,更多参数设置见 https://developer./ndk/guides/cmakearguments "-DCMAKE_BUILD_TYPE=DEBUG"// 添加CPP标准//cppFlags "-std=c++11"}}}externalNativeBuild {cmake {// 指定CMake编译配置文件路径path "src/main/cpp/CMakeLists.txt"}}}

关于 CMake 编译参数的设置,更多内容请阅读官方资料。

眼尖的小伙伴已经发现两处配置了externalNativeBuild。其中第二处的externalNativeBuild配置是生成Gradle Task可以不运行工程,直接在 ndk-cmake -> Tasks -> other 找到编译 so 文件有关的四个任务。

双击exeternalNativeBuildDebug执行任务,如图:

根据路径即可找到生成的so文件。

3.2 ndk-build

这是最传统的 ndk 编译方式。在配置得当的情况下,可以在不打开 AndroidStudio 情况下完成so文件的编译和输出。

创建 ndk-build module ,添加4个文件。

Android.mk

# 讲真,这个参数我看不懂。从 官方demo 抄来的。用于指定源文件的时候使用abspath_wa = $(join $(filter %:,$(subst :,: ,$1)),$(abspath $(filter-out %:,$(subst :,: ,$1))))# 指定当前路径LOCAL_PATH := $(call my-dir)# 指定源文件路径JNI_SRC_PATH := $(call abspath_wa, $(LOCAL_PATH)/../../../../cpp-src)# 声明 clear 变量include $(CLEAR_VARS)# 指定 so 库的名称 libhello-jni.soLOCAL_MODULE := hello-jni# 指定 c 源文件LOCAL_SRC_FILES := $(JNI_SRC_PATH)/hello-jni.c# 添加需要依赖的NDK库LOCAL_LDLIBS := -llog -landroid# 指定为分享库include $(BUILD_SHARED_LIBRARY)

关于 Android.mk 编译参数的设置,更多内容请阅读官方资料

Application.mk

# 指定编译的的so版本APP_ABI := all# 指定 APP 平台版本。比 android:minSdkVersion 值大时,会有警告APP_PLATFORM := android-28

关于 Application.mk 编译参数的设置,更多内容请阅读官方资料

AndroidManifext.xml

<?xml version="1.0" encoding="UTF-8" ?><manifest package="com.flueky.ndk"></manifest>

build.gradle

apply plugin: 'com.android.library'android {compileSdkVersion 28externalNativeBuild {ndkBuild {// 指定mk文件路径path 'src/main/jni/Android.mk'}}defaultConfig {}}

上面的externalNativeBuild作用同CMake方式的一样,用于编译生成 so 文件。

但是 ndk-build 还支持使用命令ndk-build编译 so 文件。需要将 NDK 路径添加至环境变量。

需要在jni目录下执行该命令:

最后生成的so文件路径如图;

4 实践

4.1 生成头文件

在主 module 中的 MainActivity中添加 native 方法 。使用 javah 编译出头文件。 使用-d参数指定头文件的输出目录。

public class MainActivity extends Activity {static {// 加载 JNI 库System.loadLibrary("hello-jni");}......// 声明 Native 方法private native String hello();}

app/src/main/java目录下执行命令javah

4.2 编写 C 源码

hello-jni.c文件引用生成的头文件,并编写测试代码。

#include <string.h>#include <jni.h>#include "com_flueky_demo_MainActivity.h"#include "util/log.h"/*** JNI 示例,演示native方法返回一个字符串,Java 源码见** ndk-sample/app/src/main/java/com/flueky/demo/MainActivity.java*/JNIEXPORT jstring JNICALLJava_com_flueky_demo_MainActivity_hello( JNIEnv* env,jobject thiz ){#if defined(__arm__)#if defined(__ARM_ARCH_7A__)#if defined(__ARM_NEON__)#if defined(__ARM_PCS_VFP)#define ABI "armeabi-v7a/NEON (hard-float)"#else#define ABI "armeabi-v7a/NEON"#endif#else#if defined(__ARM_PCS_VFP)#define ABI "armeabi-v7a (hard-float)"#else#define ABI "armeabi-v7a"#endif#endif#else#define ABI "armeabi"#endif#elif defined(__i386__)#define ABI "x86"#elif defined(__x86_64__)#define ABI "x86_64"#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */#define ABI "mips64"#elif defined(__mips__)#define ABI "mips"#elif defined(__aarch64__)#define ABI "arm64-v8a"#else#define ABI "unknown"#endifLOGD("日志输出示例");return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");}

4.3 运行截图

页面截图:

日志截图:

5 源码获取

工程源码已开放在GitHub,下载地址。如果您有多余的CSDN积分,不防从这里下载。可以直接编写 C 源码并进行调试和生成 so 文件。

Google 官方资料需要翻墙才可以阅读。想了解翻墙方法,请点SSR

觉得有用?那打赏一个呗。我要打赏

此处是广告:Flueky的技术小站

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。