Android NDK入门

本文介绍了Android NDK的基本概念和用途,包括如何使用NDK进行原生代码开发,创建.so文件,以及通过自动编译和NDK编译两种方式生成.so文件的过程。详细讲解了Android.mk和Application.mk文件的作用,以及C++代码中JNI接口的实现。最后提到了NDK的下载和环境配置方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NDK是什么

NDK是Native Development Kit,NDK允许用户使用类似C / C++之类的原生代码语言执行部分程序,还可以将我们的c或c++代码打包成.so文件,供安卓程序调用。

NDK的使用

首先看看NDK项目的目录:
在jni目录下面新建三个文件,Android.mkApplication.mk,native-lib.cpp;
在这里插入图片描述
其中Android.mk定义了“需要构建模块的名称”,“构建到模块中的 C 或 C++ 源文件列表”等,具体如下

# 构建系统提供的宏函数 my-dir 将返回当前目录(包含 Android.mk 文件本身的目录)的路径,基本上是固定的,不需要去动
LOCAL_PATH := $(call my-dir)

# 会清除很多 LOCAL_XXX 变量,不会清除 LOCAL_PATH,基本上是固定的,不需要去动
include $(CLEAR_VARS)

# 需要构建模块的名称,会自动生成相应的 libNDKSample.so 文件,每个模块名称必须唯一,且不含任何空格
LOCAL_MODULE := nativeLib

# 包含要构建到模块中的 C 或 C++ 源文件列表
LOCAL_SRC_FILES := native-lib.cpp

# 指定这个模块里会用到哪些原生 API,详见:https://developer.android.google.cn/ndk/guides/stable_apis.html
LOCAL_LDLIBS := -llog

# 帮助系统将所有内容连接到一起,固定的,不需要去动
include $(BUILD_SHARED_LIBRARY)

Application.mk定义了要编译的系统包和运行时,具体如下:

# 选择不同的 ABI,多个使用空格作为分隔符,全部是all
# APP_ABI := armeabi armeabi-v7a
APP_ABI := arm64-v8a, armeabi-v7a, x86, x86_64

# 指定要使用的运行时
APP_STL := c++_static

native-lib.cpp是我们需要实现的功能,供我们的Android端调用,我写了一个加法运算的功能,代码如下:

extern "C"
JNIEXPORT jint JNICALL
Java_com_dingxingxiang_myapplication_MainActivity_add(JNIEnv *env, jobject instance, jint a,
                                                      jint b) {
    return a + b;
}

说明:

  1. extern "C"是固定的,代表调用C
  2. JNIEXPORT jint JNICALL中,jint代表返回值的类型,对应java中的int类型,还有 8 种基本数据类型 jbyte、jchar、jshort、jint、jlong、jfloat、jdouble、jboolean,引用数据类型 jintArray、jshortArray、jlongArray 等。
  3. 方法名部分,格式为:Java_包名_类名_方法名,
  4. 参数部分,包含了,JNIEnv代表运行时环境,jobject代表 调用 Java 中 native 方法的实例或 Class 对象,如果这个 native 方法是实例方法,则该参数是 jobject,如果是静态方法,则是 jclass。

写完代码之后,我们需要运行的c代码,有两种方式

自动编译的方式

自动编译的方式是在我们呢app/buildgradle中配置我们的运行命令,这样每次都可以同步罪行的c代码:
在Android下的defaultConfig中,新建externalNativeBuild ->ndkBuild,指定application.mk的位置等,在Android下,创建externalNativeBuild->ndkBuild,指定Android.mk的位置。这样运行项目就可以运行我们的代码

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.wuxiaolong.ndkbuild"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        externalNativeBuild {
            ndkBuild {
                //指定 Application.mk 的路径
                arguments "NDK_APPLICATION_MK:=src/main/jni/Application.mk"
                //指定生成哪些平台的 so 文件
//                abiFilters "x86"
                //cFlags 和 cppFlags 是用来设置环境变量的, 一般不需要动
                cFlags "-DTEST_C_FLAG1", "-DTEST_C_FLAG2"
                cppFlags "-DTEST_CPP_FLAG2", "-DTEST_CPP_FLAG2"
            }
        }
    }
    externalNativeBuild {
        ndkBuild {
            //指定 Android.mk 的路径
            path "src/main/jni/Android.mk"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets.main {
        jni.srcDirs = []
        jniLibs.srcDir 'src/main/libs'
    }
}

运行成功之后,我们的项目中多了一个.externalNativeBuild文件,如图
生成的.so包在app/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libnativeLib.so
在这里插入图片描述

NDK编译

使用命令 ndk-build,也可以生成对应的 so 文件,然后项目中调用。弊端是C 或 C++ 代码改动了,需要再次编译。
未下载NDK在Android Studio的SDK Tools中下载
在这里插入图片描述
下载安装之后,如果没有配置系统环境变量,我们需要配置系统环境变量,在path中填写ndk的路径:如图
在这里插入图片描述
然后我们通过cmd进入项目的jni路径下面,执行ndk-build,就可以生成我们需要的.so包了,如下如:
在这里插入图片描述
生成的.so包
在这里插入图片描述
至此,ndk的入门讲完了,下一篇我们讲ndk的另一种编程方式CMake

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值