Android JNI开发系列(二)HelloWorld

入门HelloWorld

新建项目

  • Configure your new project部分选中 Include C++ Support 复选框

  • Next

  • 正常填写所有其他字段并完成向导接下来几个部分

  • 在向导的Customize C++ Support 部分,您可以使用谢列选项自定义项目:

    • C++ Standard : 使用下拉列表选择使用的C++标准。选择Toolchain Defalut 会使用默认的CMake设置。

    • Exception Support : 如果您希望启用对C++异常处理的支持,请选中该复选框,Android Studio 会将 -fexception标志添加到模块级别build.gradle 文件的cppFlag中,Gradle会将其传递到CMake.

    • Runtime Type Information Support: 如果您希望支持RTTI,请选中该复选框,如果启用Android Studio会将**-frtti标志添加到模块级别build.gradle** 文件的cppFlag中,Gradle会将其传递到CMake.

  • finish

项目结构

  • cpp 组

    您可以找到属于项目的所有原生源文件、标头和预构建库。对于新项目,Android Studio 会创建一个示例 C++ 源文件 native-lib.cpp,并将其置于应用模块的 src/main/cpp/ 目录中。本示例代码提供了一个简单的 C++ 函数 stringFromJNI(),此函数可以返回字符串“Hello from C++”。要了解如何向项目添加其他源文件,请参阅介绍如何创建新的原生源文件的部分。

  • External Build File :

    您可以找到 CMake 或 ndk-build 的构建脚本。与 build.gradle 文件指示 Gradle 如何构建应用一样,CMake 和 ndk-build 需要一个构建脚本来了解如何构建您的原生库。对于新项目,Android Studio 会创建一个 CMake 构建脚本 CMakeLists.txt,并将其置于模块的根目录中。要详细了解此构建脚本的内容,请参阅介绍如何创建 Cmake 构建脚本的部分。

构建过程

Gradle 调用您的外部构建脚本 CMakeLists.txt。 CMake 按照构建脚本中的命令将 C++ 源文件例如 native-lib.cpp 编译到共享的对象库中,并命名为 libnative-lib.so,Gradle 随后会将其打包到APK 中。

创建 CMake 构建脚本

如果您的原生源文件还没有 CMake 构建脚本,则您需要自行创建一个并包含适当的 CMake 命令。CMake 构建脚本是一个纯文本文件,您必须将其命名为 CMakeLists.txt。本部分介绍了您应包含到构建脚本中的一些基本命令,用于在创建原生库时指示 CMake 应使用哪些源文件。

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

  • 从 IDE 的左侧打开 Project 窗格并从下拉菜单中选择 Project 视图。
  • 右键点击 您的模块 的根目录并选择 New > File。
  • 输入“CMakeLists.txt”作为文件名并点击 OK。

要指示 CMake 从原生源代码创建一个原生库,请将 cmake_minimum_required()add_library() 命令添加到您的构建脚本中:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

//指定可用的CMake构建脚本版本

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
# 指定需传入三个参数(函数库名称,库类型,依赖源文件相对路径)

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

             # SHARED 动态链接库  STATIC 静态链接库 Sets the library as a shared library.
             SHARED 

             # 相对路径 Provides a relative path to your source file(s).
             
             
             src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

# 用于定位NDK中的库
# 需要传入两个参数(path变量、ndk库名称)
find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              # 指定CMake查询库的名称,即在ndk 开发包中查询liblog.so函数库,将其路径赋值给log-lib
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

# 指定关联到原生库的库

target_link_libraries( # Specifies the target library.
							# 指定目标库,与善变的函数名保持一致
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       # 链接的库,根据log-lib变量对应liblog.so函数库
                       ${log-lib} )

NOTE:

  • 使用 add_library() 向您的 CMake 构建脚本添加源文件或库时,Android Studio 还会在您同步项目后在 Project 视图下显示关联的标头文件。不过,为了确保 CMake 可以在编译时定位您的标头文件,您需要将 include_directories() 命令添加到 CMake 构建脚本中并指定标头的路径:
# Specifies a path to native header files.
include_directories(src/main/cpp/include/)
  • 将 find_library() 命令添加到您的 CMake 构建脚本中以定位 NDK 库,并将其路径存储为一个变量。您可以使用此变量在构建脚本的其他部分引用 NDK 库。以下示例可以定位 Android 特定的日志支持库并将其路径存储在 log-lib 中:
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 )
  • 为了确保您的原生库可以在 log 库中调用函数,您需要使用 CMake 构建脚本中的 target_link_libraries() 命令关联库:
find_library(...)

# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the log library to the target library.
                       ${log-lib} )
  • NDK 还以源代码的形式包含一些库,您在构建和关联到您的原生库时需要使用这些代码。您可以使用 CMake 构建脚本中的 add_library() 命令,将源代码编译到原生库中。要提供本地 NDK 库的路径,您可以使用 ANDROID_NDK 路径变量,Android Studio 会自动为您定义此变量。

以下命令可以指示 CMake 构建 android_native_app_glue.c,后者会将 NativeActivity 生命周期事件和触摸输入置于静态库中并将静态库关联到 native-lib:

add_library( app-glue
             STATIC
             ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )

# You need to link static libraries against your shared native library.
target_link_libraries( native-lib app-glue ${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} )

构建应用时,Gradle 会自动将导入的库打包到 APK 中。您可以使用 APK 分析器验证 Gradle 将哪些库打包到您的 APK 中。如需了解有关 CMake 命令的详细信息,请参阅 CMake 文档。

新建Demo时候遇到的坑

  • CMakeList.txt

    add_libary() 脚本,报错,如果写了新的Cpp/C文件,rebuld不会提示并生成,直接报错在该节点首行,

    应先在对应目录新建Cpp/C文件,再引入

  • 注意修改 target_link_libraries 下的 target Libary

    原文作者:移动开发
    原文地址: https://my.oschina.net/caipeng/blog/2243624
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞