手把手教你如何在android studio添加C和C++代码

5,282 阅读5分钟

本文适用于第一次想在android studio中使用原生代码的人

本文将讲解如何下载相关内容以支持项目构建,如何在android studio创建支持c/c++的新项目,以及如何添加新的c/c++文件

一、下载NDK和构建工具

如果要编译和调试原生代码,需要以下工具

NDK(Native Development Kit):

  1. NDK 是 Android Studio 中用于开发原生(C/C++)代码的工具包。

  2. 它允许开发者使用 C/C++ 编写 Android 应用程序的部分或全部代码。

  3. NDK 提供了一组 C/C++ 库,可以访问 Android 平台的底层功能,例如相机、传感器、音频、网络等。

  4. 使用 NDK 可以提高性能、访问特定硬件功能、重用现有 C/C++ 代码等。

CMake:

  1. CMake 是一个跨平台的构建工具,可以生成用于构建项目的 Makefile 或 IDE 项目文件。

  2. 在 Android Studio 中,CMake 用于配置和构建原生代码项目。

  3. 开发者可以使用 CMakeLists.txt 文件描述项目的结构和构建过程,包括源文件、库、编译选项等。

  4. Android Studio 提供了对 CMake 的集成支持,可以轻松地在项目中使用 CMake 来构建原生代码。

LLDB:

  1. LLDB 是一个用于调试应用程序的调试器,支持多种平台,包括 Android。

  2. 在 Android Studio 中,LLDB 用于调试原生代码。

  3. 开发者可以使用 LLDB 在 Android 设备上调试 C/C++ 代码,以查找和修复问题。

  4. Android Studio 提供了对 LLDB 的集成支持,包括在 IDE 中设置断点、查看变量值、执行代码等功能。

安装配置NDK和CMake

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

  2. 点击 SDK Tools 标签页。

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

sdk-tools.jpg

  1. 点击apply开始下载,安装完成后点击finish

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

7c2d336e-110a-426d-ab05-57158e67e638.jpg

二、创建支持C/C++的新项目

建新项目时选择Native C++项目类型

New_Project.png 在向导的 Customize C++ Support 部分中,使用下拉列表选择想要使用的 C++ 标准化。选择 Toolchain Default,将使用默认的 CMake 设置。

项目建成后可以看到main文件夹下多了cpp目录

文件目录.png

在 cpp 组中,可以找到项目中的所有原生源代码文件、头文件、CMake 或 ndk-build 的构建脚本,以及项目中的预构建库。对于新项目,Android Studio自动创建的示例代码会返回字符串 "Hello from C++"。

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_nativectest_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

与 build.gradle 文件指示 Gradle 如何构建应用一样,CMake 和 ndk-build 需要构建脚本才能确定如何构建原生库。对于新项目,Android Studio 会创建 CMake 构建脚本 CMakeLists.txt,并将其置于模块的根目录中。

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html.
# For more examples on how to use CMake, see https://github.com/android/ndk-samples.

# Sets the minimum CMake version required for this project.
cmake_minimum_required(VERSION 3.22.1)

# Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
# Since this is the top level CMakeLists.txt, the project name is also accessible
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
# build script scope).
project("nativectest")

# 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.
#
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
# is preferred for the same purpose.
#
# In order to load a library into your app from Java/Kotlin, you must call
# System.loadLibrary() and pass the name of the library defined here;
# for GameActivity/NativeActivity derived applications, the same library name must be
# used in the AndroidManifest.xml file.
add_library(${CMAKE_PROJECT_NAME} SHARED
        # List C/C++ source files with relative paths to this CMakeLists.txt.
        native-lib.cpp)

# Specifies libraries CMake should link to your target library. You
# can link libraries from various origins, such as libraries defined in this
# build script, prebuilt third-party libraries, or Android system libraries.
target_link_libraries(${CMAKE_PROJECT_NAME}
        # List libraries link to the target library
        android
        log)

三、运行实例项目

点击Run图标,该应用会在屏幕显示来自CPP文件的字符串。

1.png

构建时会发生的事:

  1. Gradle 调用外部构建脚本 CMakeLists.txt。

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

  3. 在运行时,应用的 MainActivity 会使用System.loadLibrary() 加载原生库。现在,应用就可以使用库的原生函数 stringFromJNI() 了。

  4. MainActivity.onCreate() 调用 stringFromJNI(),后者会返回 "Hello from C++",并使用它来更新 TextView。

四、增加一个新的C++文件

1.在cpp文件夹中新建一个cpp文件,我这里文件名为hello-lib.cpp

内容如下,实现了一个简单的加法功能


#include <jni.h>

extern "C" JNIEXPORT jint JNICALL
Java_com_example_nativectest_MainActivity_addNumbers(
        JNIEnv* env,
        jobject /* this */,
        jint num1,
        jint num2) {
    jint result = num1+num2;
    return result;
}

extern "C" JNIEXPORT jint JNICALL是一个函数声明,告诉编译器这是一个C函数,并且导出到JNI中供java使用。

Java_com_example_nativectest_MainActivity_addNumber是JNI函数的名称,它的命名规则是 Java_包名_类名_方法名

JNIEnv* env:这是指向 JNI 环境的指针。JNI 函数需要使用该指针来与 Java 虚拟机(JVM)进行通信,包括调用 Java 方法和访问 Java 对象。

jobject /* this */:这个参数表示对 Java 对象的引用,通常用于指向调用本地方法的 Java 对象。

2.在CMakeLists文件中添加这个文件

add_library(${CMAKE_PROJECT_NAME} SHARED
        # List C/C++ source files with relative paths to this CMakeLists.txt.
        native-lib.cpp
        hello-lib.cpp)

3. MainActivity

在MainActivity中添加函数声明 public native int addNumbers(int num1,int num2); 再调用函数

TextView tv = binding.sampleText;
//tv.setText(stringFromJNI());
tv.setText(String.valueOf(addNumbers(1,2)));

我这里偷懒还是用的之前那个view

这里就会显示1+2的结果了

2.png