跟着官方学jni&ndk

安装及配置 NDK 和 CMake

     
 如需为您的应用编译和调试原生代码,您需要以下组件:
   1.Android 原生开发套件 (NDK):这是一套可让您在 Android 应用中使用 C 和 C++ 代码的工具。     
   2.CMake:这是一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果您只计划使用 ndk-build,则不需要此组件。
   3.LLDB:Android Studio 用于调试原生代码的调试程序。默认情况下,安装 Android Studio 时会随同安装 LLDB。

 

自动安装 NDK 和 CMake

Android Gradle 插件 4.2.0 及更高版本可在您首次构建项目时自动安装所需的 NDK 和 CMake,前提是您已预先接受其二者的许可。如果您已阅读并同意许可条款,就可以使用以下命令预先接受脚本中的相应许可:

   yes | ${sdk}/cmdline-tools/latest/bin/sdkmanager --licenses

 手动安装 NDK 和 CMake

当您安装 NDK 时,Android Studio 会选择可用的最新 NDK 版本。对于大多数项目,安装此默认版本的 NDK 已经足够。不过,如果您的项目需要一个或多个特定版本的 NDK,您可以下载并配置特定版本。当多个项目各自依赖于特定版本的 NDK 时,这样做有助于确保各个项目的 build 都可重现。Android Studio 会将所有版本的 NDK 安装在 android-sdk/ndk/ 目录中。

如需在 Android Studio 中安装 CMake 和默认 NDK,请执行以下操作:

  1. 打开项目后,依次点击 Tools > SDK Manager

  2. 点击 SDK Tools 标签页。

  3. 选中 NDK (Side by side) 和 CMake 复选框。

  4. 点击 OK

    此时系统会显示一个对话框,告诉您 NDK 软件包占用了多少磁盘空间。

  5. 安装完成后,点击 Finish

  6. 您的项目会自动同步 build 文件并执行构建。修正发生的所有错误。

   跟着官方学jni&ndk_第1张图片

注意:如果某个 NDK 安装在 ndk-bundle 文件夹中,它会显示在列表中并带有 NDK 标签。如果您使用的是 Android Gradle 插件 3.5.0 或更高版本,可以选中或取消选中该复选框。取消选中该复选框会卸载 NDK,释放磁盘空间,并在列表中移除该复选框。如果您卸载旧版 NDK,请从项目的 local.properties 文件中移除 ndk.dir 值,该值现已废弃。

配置特定版本的 CMake

SDK 管理器包含 CMake 的 3.6.0 分支版本和 3.10.2 版本。未设置特定 CMake 版本的项目使用 CMake 3.10.2 进行构建。如需设置 CMake 版本,请将以下内容添加到模块的 build.gradle 文件中:

 externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }

安装特定版本的 NDK 

  要安装特定版本的 NDK,请执行以下操作:

  1. 打开项目后,依次点击 Tools > SDK Manager

  2. 点击 SDK Tools 标签页。

  3. 选中 Show Package Details 复选框。

  4. 选中 NDK (Side by side) 复选框及其下方与您想要安装的 NDK 版本对应的复选框。Android Studio 会将所有版本的 NDK 安装在 android-sdk/ndk/ 目录中。

  5. 点击 OK

    此时系统会显示一个对话框,告诉您 NDK 软件包占用了多少空间

  6. 安装完成后,点击 Finish

  7. 您的项目会自动同步 build 文件并执行构建。修正发生的所有错误。

  8. 为每个模块配置您想要让其使用的 NDK 版本。使用 Android Studio 3.6 或更高版本时,如果您不指定版本,Android Gradle 插件会选择已知兼容的版本。

跟着官方学jni&ndk_第2张图片

注意:如果某个 NDK 安装在 ndk-bundle 文件夹中,它会显示在列表中并带有 NDK 标签。如果您使用的是 Gradle 3.5 或更高版本,可以选中或取消选中该复选框。取消选中该复选框会卸载已安装的 NDK,释放磁盘空间,并在列表中移除该复选框。如果您卸载旧版 NDK,请从项目的 local.properties 文件中移除 ndk.dir 值,该值现已废弃。

在项目中配置特定版本的 NDK

如果满足以下任一条件,您可能需要在项目中配置 NDK 版本:

1.项目是继承的,您需要使用特定版本的 NDK 和 Android Gradle 插件 (AGP)。如需了解详情,请参阅为 Android Gradle 插件配置 NDK。

2.您安装了多个版本的 NDK,但想要使用某个特定版本。在这种情况下,请在模块的 build.gradle 文件中使用 android.ndkVersion 属性指定相应的版本,如以下代码示例所示。

跟着官方学jni&ndk_第3张图片

每个 AGP 版本有对应的默认 NDK 版本

在发布之前,每个 AGP 版本都会使用当时最新的 NDK 稳定版进行全面测试。对于 AGP 3.6 及更高版本,如果您在 build.gradle 文件中指定 NDK 版本,系统将使用上述 默认NDK 版本构建项目。AGP 版本说明中介绍了默认 NDK 版本。下表列出了当前的默认 NDK 版本:

Android Studio/Gradle 插件版本 为 AGP 版本指定的
默认 NDK 版本
8.1 25.1.8937393
8.0 25.1.8937393
7.4 23.1.7779620
7.3 23.1.7779620
7.0 21.4.7075529
4.2 21.4.7075529
4.1 21.1.6352462
4.0 21.0.6113669
3.6 20.0.5594570
3.5 及更早版本 未指定默认版本

为 Android Gradle 插件 (AGP) 配置 NDK版本

  本页介绍了如何根据项目使用的 Android Gradle 插件 (AGP) 版本在项目中配置 NDK。

注意:如有可能,应尝试将项目中的 AGP 更新为版本 4.1 或更高版本。这些 AGP 版本会在 Android Studio 中自动下载 NDK。

AGP 版本 4.1 及更高版本配置 NDK版本

 跟着官方学jni&ndk_第4张图片

可以通过以下方式配置 NDK:

  • (推荐)使用 ndkVersion 属性设置 NDK 版本。

跟着官方学jni&ndk_第5张图片

  • 不设置任何属性。Android Studio 会自动下载特定 AGP 版本的默认 NDK 版本(在本例中为 NDK 版本 21.0.6113669),您也可以从命令行安装 NDK。Android Studio 会将所有版本的 NDK 安装在 android-sdk/ndk/ 目录中。每个版本都位于一个以版本号命名的子目录中。对于
  • 特殊用例,请使用 ndkPath 属性:
android {
  ndkPath "/Users/ndkPath/ndk21"  // Point to your own NDK
}

Android Gradle 插件API版本更新说明

Android Gradle 插件版本说明  |  Android 开发者  |  Android Developers (google.cn)

Android Studio 构建系统以 Gradle 为基础,并且 Android Gradle 插件添加了几项专用于构建 Android 应用的功能。虽然 Android 插件通常会与 Android Studio 的更新步调保持一致,但插件(以及 Gradle 系统的其余部分)可独立于 Android Studio 运行并单独更新。

本页将介绍如何让 Gradle 工具保持最新状态,以及最近的更新包含哪些内容。如需查看 Android Gradle 插件过往版本的版本说明,请参阅过往版本说明。

 更新 Android Gradle 插件

在更新 Android Studio 时,您可能会收到将 Android Gradle 插件自动更新为最新可用版本的提示。您可以选择接受该更新,也可以根据项目的构建要求手动指定版本。

您可以在 Android Studio 的 File > Project Structure > Project 菜单中指定插件版本,也可以在顶级 build.gradle 文件中指定。该插件版本适用于在相应 Android Studio 项目中构建的所有模块。以下示例从 build.gradle 文件中将插件的版本号设置为 7.4.1:

plugins {
    id 'com.android.application' version '7.4.1' apply false
    id 'com.android.library' version '7.4.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.5.31' apply false
}

注意:不应在版本号中使用动态依赖项(如 'com.android.tools.build:gradle:2.+')。使用此功能可能会导致意外的版本更新,而且难以解析版本差异。

如果指定的插件版本尚未下载,则 Gradle 会在您下次构建项目时进行下载;或者,您也可以在 Android Studio 菜单栏中依次点击 File > Sync Project with Gradle Files 进行下载。

更新 Gradle

在更新 Android Studio 时,您可能会收到一并将 Gradle 更新为最新可用版本的提示。您可以选择接受该更新,也可以根据项目的构建要求手动指定版本。

下表列出了各个 Android Gradle 插件版本所需的 Gradle 版本。为了获得最佳性能,您应使用 Gradle 和插件这两者的最新版本。

插件版本 所需的最低 Gradle 版本
8.1 8.0
8.0 8.0
7.4 7.5
7.3 7.4
7.2 7.3.3
7.1 7.2
7.0 7.0
4.2.0+ 6.7.1

我的as的项目目前插件版本和Gradle版本

 classpath 'com.android.tools.build:gradle:7.2.2'

distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip

Android Gradle 插件和 Android Studio 兼容性

Android Studio 构建系统以 Gradle 为基础,并且 Android Gradle 插件添加了几项专用于构建 Android 应用的功能。下表列出了各个 Android Studio 版本所需的 Android Gradle 插件版本。

Android Studio 版本 所需插件版本
Giraffe | 2022.3.1 3.2-8.1
Flamingo | 2022.2.1 3.2-8.0
Electric Eel | 2022.1.1 3.2-7.4
Dolphin | 2021.3.1 3.2-7.3
Chipmunk | 2021.2.1 3.2-7.2
Bumblebee | 2021.1.1 3.2-7.1
Arctic Fox | 2020.3.1 3.1-7.0

Android Gradle 插件 (AGP) 的版本API编号变更(自2020 年 11 月)

  7.4.0(AGP)(2022 年 12 月)

  Android Gradle 插件 7.4.0 是一个主要版本,包含各种新功能和改进。

最低版本 默认版本 备注
Gradle 7.5 7.5 如需了解详情,请参阅更新 Gradle。
SDK Build Tools 30.0.3 30.0.3 安装或配置 SDK Build Tools。
NDK 不适用 23.1.7779620 安装或配置其他版本的 NDK。
JDK 11 11 如需了解详情,请参阅设置 JDK 版本。

AGP补丁版本

 7.4.2(AGP)(2023 年 2 月)
 7.4.1(AGP)(2023 年 2 月)



配置 CMake

CMake 构建脚本是一个纯文本文件,您必须将其命名为 CMakeLists.txt,并在其中包含 CMake 构建您的 C/C++ 库时需要使用的命令。如果您的原生源代码文件还没有 CMake 构建脚本,您需要自行创建一个,并在其中包含适当的 CMake 命令。如需了解如何安装 CMake,请参阅安装及配置 NDK 和 CMake。

在配置新的 CMake 构建脚本后,您需要配置 Gradle 以将 CMake 项目作为构建依赖项包含在内,从而让 Gradle 构建原生库,并将其与应用的 APK 打包在一起。

注意:如果项目使用的是 ndk-build,您不需要创建 CMake 构建脚本。您只需配置 Gradle 以包含现有的原生库项目即可;为此,您需要提供 Android.mk 文件的路径。

创建 CMake(CMakeLists.txt) 构建脚本

 如需创建一个可以用作 CMake 构建脚本的纯文本文件,请按以下步骤操作:

   1.从 IDE 的左侧打开 Project 窗格,然后从下拉菜单中选择 Project 视图。
   2.右键点击 your-module 的根目录,然后依次选择 New > File。
   3.输入“CMakeLists.txt”作为文件名,然后点击 OK。

注意:您可以在所需的任何位置创建构建脚本。不过,在配置 build 脚本时,原生源代码文件和库的路径将与 build 脚本的位置相关。

现在,您可以通过添加 CMake 命令来配置您的构建脚本。如需指示 CMake 根据原生源代码创建原生库,请向您的构建脚本添加 cmake_minimum_required() 和 add_library() 命令:

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.
project("hellojni")


add_library( # Specifies the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp  #制定本地创建的cpp文件路径
        )


find_library(  
              log-lib
              log )


target_link_libraries( 
                       native-lib

                      ${log-lib} )




#1.在cpp中创建一个src文件夹,并在该文件夹下创建hellojni.cpp文件
#2.在cpp中创建一个include文件夹,并在该文件夹下创建hellojni.h头文件
message("CMAKE_SOURCE_DIR:")
message(${CMAKE_SOURCE_DIR})


 #为了演示此处使用动态注册方式
#3.创建一个新的库
add_library(
        hello-jni #库名
        SHARED #设置为so共享库
        src/hellojni.cpp #添加cpp文件的路径
)



target_include_directories(hello-jni #库名
        PUBLIC
        include/hellojni.h  #添加头文件hellojni.h的路径
        )


target_link_libraries(hello-jni

        ${log-lib})


target_link_libraries(native-lib
        hello-jni)





提示:与指示 CMake 根据源代码文件创建原生库的方式一样,您可以使用 add_executable() /target_include_directories()命令指示 CMake 改为根据这些源代码文件来创建可执行文件。不过,根据原生源代码文件构建可执行文件是可选操作,构建原生库以将其打包到 APK 中即可满足大多数项目的要求。

例如,如果您在构建脚本中指定“native-lib”作为共享库的名称,CMake 就会创建一个名为 libnative-lib.so 的文件。不过,在 Java 或 Kotlin 代码中加载此库时,请使用您在 CMake build 脚本中指定的名称:

companion object {
    init {
        System.loadLibrary("native-lib");
    }
}
static {
    System.loadLibrary("native-lib");
}

跟着官方学jni&ndk_第6张图片

注意:如果重命名或移除了 CMake build 脚本中的库,您需要在 Gradle 应用相关更改或从 APK 中移除旧版库之前清理您的项目。如需清理项目,请在菜单栏中依次选择 Build > Clean Project

添加 NDK API

Android NDK 提供了一套您可能会觉得非常实用的原生 API 和库。通过在项目的 CMakeLists.txt 脚本文件中包含 NDK 库,您可以使用其中任何 API。

Android 平台上已存在预构建的 NDK 库,因此您无需构建 NDK 库或将其打包到 APK 中。由于这些 NDK 库已位于 CMake 搜索路径中,因此您甚至无需指定本地安装的 NDK 库的位置,您只需为 CMake 提供您想要使用的库的名称,并将其与您自己的原生库相关联即可。

向 CMake 构建脚本添加 find_library() 命令以找到 NDK 库并将其路径存储为一个变量。您可以使用此变量在构建脚本的其他部分引用 NDK 库。以下示例会找到 Android 专有的日志支持库,并将其路径存储在 log-lib 中:

为了让您的原生库能够调用 log 库中的函数,您需要使用 CMake 构建脚本中的 target_link_libraries() 命令来关联这些库:

NDK 还以源代码的形式包含一些库,您需要构建这些代码并将其关联到您的原生库。您可以使用 CMake 构建脚本中的 add_library() 命令将源代码编译到原生库中。如需提供本地 NDK 库的路径,您可以使用 Android Studio 自动为您定义的 ANDROID_NDK 路径变量。

以下命令可以指示 CMake 将 android_native_app_glue.c(负责管理 NativeActivity 生命周期事件和触控输入)构建至静态库,并将其与 native-lib 关联:

​
add_library(  
             native-lib

             
             SHARED

${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c, 
 native-lib.cpp
 )


find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              log-lib

              # Specifies the name of the NDK library that
              # CMake needs to locate.
              log )

​

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

添加其他预构建库

添加预构建库的步骤与为 CMake 指定其他要构建的原生库的步骤相似。不过,由于库已构建,因此您需要使用 IMPORTED 标志指示 CMake 您只想要将此库导入到您的项目中:

add_library( imported-lib
             SHARED
             IMPORTED )

然后,您需要使用 set_target_properties() 命令指定库的路径,具体命令如下所示。

某些库会针对特定的 CPU 架构或应用二进制接口 (ABI) 提供单独的软件包,并将其整理到单独的目录中。此方法既有助于库充分利用特定的 CPU 架构,又能让您只使用所需的库版本。如需向 CMake 构建脚本添加库的多个 ABI 版本,而不必为库的每个版本编写多个命令,您可以使用 ANDROID_ABI 路径变量。此变量使用的是 NDK 支持的一组默认 ABI,或者您手动配置 Gradle 而让其使用的一组经过过滤的 ABI。例如:

add_library(...)
set_target_properties( # Specifies the target library.
                       imported-lib

                       # Specifies the parameter you want to define.
                       PROPERTIES IMPORTED_LOCATION

                       # Provides the path to the library you want to import.
                       imported-lib/src/${ANDROID_ABI}/libimported-lib.so )

为了让 CMake 能够在编译时找到头文件,您需要使用 include_directories() 命令并包含相应头文件的路径:

include_directories( imported-lib/include/ )

如需将预构建库关联到您自己的原生库,请将其添加到 CMake 构建脚本的 target_link_libraries() 命令中:

target_link_libraries( 
native-lib 
imported-lib
 app-glue
 ${log-lib} 
)



target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )


target_link_libraries(hello-jni

        ${log-lib})


target_link_libraries(native-lib
        hello-jni)



#调用第三方库的类库
target_link_libraries( # Specifies the target library.
                        third-call-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )


#将第三方库链接到调用库中
target_link_libraries( # Specifies the target library.
        third-call-lib

        # Links the target library to the log library
        # included in the NDK.
        hellojni-lib)






将 Gradle 关联到您的原生库(手动配置Gradle )

 如需添加您的原生库项目作为 Gradle 构建依赖项,您需要向 Gradle 提供 CMake 或 ndk-build 脚本文件的路径。构建应用时,Gradle 会运行 CMake 或 ndk-build,并将共享的库与应用打包到一起。Gradle 还会使用构建脚本来了解要将哪些文件添加到 Android Studio 项目中,以便您可以从 Project 窗口访问这些文件。如果您没有原生源代码文件的构建脚本,您需要先创建 CMake 构建脚本,然后再继续。

Android 项目中的每个模块只能关联到一个 CMake 或 ndk-build 脚本文件。例如,如果您想要构建并打包来自多个 CMake 项目的输出,就需要使用一个 CMakeLists.txt 文件作为顶级 CMake 构建脚本(然后将 Gradle 关联到该脚本),并添加其他 CMake 项目作为该构建脚本的依赖项。同样,如果您使用的是 ndk-build,您可以在顶级 Android.mk 脚本文件中包含其他 Makefile。

将 Gradle 关联到原生项目后,Android Studio 会更新 Project 窗格,以在 cpp 组中显示源代码文件和原生库,并在 External Build Files 组中显示外部构建脚本。

注意:更改 Gradle 配置后,请务必点击工具栏中的 Sync Project 图标 

,以便让所做的更改生效。此外,如果在将 CMake 或 ndk-build 脚本文件关联到 Gradle 之后要对文件进行更改,您应当从菜单栏中依次选择 Build > Refresh Linked C++ Projects,将 Android Studio 与您的更改进行同步。

跟着官方学jni&ndk_第7张图片

手动配置 Gradle

如需手动配置 Gradle 以关联到您的原生库,您需要将 externalNativeBuild 块添加到模块级 build.gradle 文件中,并使用 cmake 或 ndkBuild 块对其进行配置:

注意:如果您要将 Gradle 关联到现有的 ndk-build 项目,请使用 ndkBuild 块(而不是 cmake 块),并提供指向 Android.mk 文件的相对路径。如果 Application.mk 文件与您的 Android.mk 文件位于同一目录下,Gradle 也会包含此文件。

android {
  ...
  defaultConfig {...}
  buildTypes {...}

  //android 里面的 externalNativeBuild 
  externalNativeBuild {

    // Encapsulates your CMake build configurations.
    cmake {

      // Provides a relative path to your CMake build script.
      path "CMakeLists.txt"
       path "src/main/cpp/CMakeLists.txt"
       version "3.10.2"
     }
  }
}

指定可选配置

您可以在模块级 build.gradle 文件的 defaultConfig 块中配置另一个 externalNativeBuild 块,以为 CMake 或 ndk-build 指定可选参数和标记。与 defaultConfig 块中的其他属性类似,您也可以在构建配置中为每个产品变种替换这些属性。

例如,如果您的 CMake 或 ndk-build 项目定义了多个原生库和可执行文件,您可以使用 targets 属性为指定产品变种构建和打包其中的部分工件。以下代码示例说明了您可以配置的部分属性:

android {
  //defaultConfig 里面的externalNativeBuild 
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {

      // For ndk-build, instead use the ndkBuild block.
      cmake {

        // Passes optional arguments to CMake.
 arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
 arguments '-DANDROID_PLATFORM=android-24', '-DANDROID_STL=c++_static', '-DANDROID_STL=c++_shared'
  arguments '-DANDROID_STL=c++_static'

        // Sets a flag to enable format macro constants for the C compiler.
        cFlags "-D__STDC_FORMAT_MACROS"

        // Sets optional flags for the C++ compiler.
        cppFlags "-fexceptions", "-frtti"
        cppFlags "-std=c++11"
        cppFlags ""
      }
    }
  }

  buildTypes {...}

  productFlavors {
    // demo  里面的externalNativeBuild 
    demo {
      ...
      externalNativeBuild {
        cmake {
          ...
          // Specifies which native libraries or executables to build and package
          // for this product flavor. The following tells Gradle to build only the
          // "native-lib-demo" and "my-executible-demo" outputs from the linked
          // CMake project. If you don't configure this property, Gradle builds all
          // executables and shared object libraries that you define in your CMake
          // (or ndk-build) project. However, by default, Gradle packages only the
          // shared libraries in your app.
          targets "native-lib-demo",
                  // You need to specify this executable and its sources in your CMakeLists.txt
                  // using the add_executable() command. However, building executables from your
                  // native sources is optional, and building native libraries to package into
                  // your app satisfies most project requirements.
                  "my-executible-demo"
        }
      }
    }

  // paid   里面的externalNativeBuild 
    paid {
      ...
      externalNativeBuild {
        cmake {
          ...
          targets "native-lib-paid",
                  "my-executible-paid"
        }
      }
    }
  }

 //android 里面的 externalNativeBuild 
  externalNativeBuild {
    cmake {

      path "CMakeLists.txt"
       path "src/main/cpp/CMakeLists.txt"
       version "3.10.2"

     }
    // or ndkBuild {...}
  }
}

 配置 build

Android 构建系统会编译应用资源和源代码,然后将它们打包成 APK 或 Android App Bundle 文件,供您测试、部署、签名和分发。

Android Studio 使用高级构建工具包 Gradle 来自动执行和管理构建流程,同时也允许您自行指定灵活的 build 配置。每项 build 配置均可定义各自的一组代码和资源,同时重复利用所有应用版本共用的部分。

Android 构建系统非常灵活,让您可以在不修改应用核心源代码文件的情况下创建自定义的 build 配置。本页介绍了 Android 构建系统的工作原理,以及它如何帮助您对多项 build 配置进行自定义和自动化处理。如需详细了解如何部署应用,请参阅构建和运行应用。如要立即开始使用 Android Studio 创建自定义 build 配置,请参阅配置 build 变体。

配置 build  |  Android 开发者  |  Android Developers (google.cn)

配置 build 变体

配置 build 变体  |  Android 开发者  |  Android Developers (google.cn)

你可能感兴趣的:(android)