本文适用于第一次想在android studio中使用原生代码的人
本文将讲解如何下载相关内容以支持项目构建,如何在android studio创建支持c/c++的新项目,以及如何添加新的c/c++文件
一、下载NDK和构建工具
如果要编译和调试原生代码,需要以下工具
NDK(Native Development Kit):
-
NDK 是 Android Studio 中用于开发原生(C/C++)代码的工具包。
-
它允许开发者使用 C/C++ 编写 Android 应用程序的部分或全部代码。
-
NDK 提供了一组 C/C++ 库,可以访问 Android 平台的底层功能,例如相机、传感器、音频、网络等。
-
使用 NDK 可以提高性能、访问特定硬件功能、重用现有 C/C++ 代码等。
CMake:
-
CMake 是一个跨平台的构建工具,可以生成用于构建项目的 Makefile 或 IDE 项目文件。
-
在 Android Studio 中,CMake 用于配置和构建原生代码项目。
-
开发者可以使用 CMakeLists.txt 文件描述项目的结构和构建过程,包括源文件、库、编译选项等。
-
Android Studio 提供了对 CMake 的集成支持,可以轻松地在项目中使用 CMake 来构建原生代码。
LLDB:
-
LLDB 是一个用于调试应用程序的调试器,支持多种平台,包括 Android。
-
在 Android Studio 中,LLDB 用于调试原生代码。
-
开发者可以使用 LLDB 在 Android 设备上调试 C/C++ 代码,以查找和修复问题。
-
Android Studio 提供了对 LLDB 的集成支持,包括在 IDE 中设置断点、查看变量值、执行代码等功能。
安装配置NDK和CMake
-
打开项目后,依次点击 Tools > SDK Manager。
-
点击 SDK Tools 标签页。
-
选中 NDK (Side by side) 和 CMake 复选框。
-
点击apply开始下载,安装完成后点击finish
-
项目会自动同步 build 文件并执行构建,修正发生的所有错误。
二、创建支持C/C++的新项目
建新项目时选择Native C++项目类型
在向导的 Customize C++ Support 部分中,使用下拉列表选择想要使用的 C++ 标准化。选择 Toolchain Default,将使用默认的 CMake 设置。
项目建成后可以看到main文件夹下多了cpp目录
在 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文件的字符串。
构建时会发生的事:
-
Gradle 调用外部构建脚本 CMakeLists.txt。
-
CMake 按照构建脚本中的命令将 C++ 源文件 native-lib.cpp 编译到共享对象库中,并将其命名为 libnative-lib.so。Gradle 随后会将其打包到应用中。
-
在运行时,应用的 MainActivity 会使用System.loadLibrary() 加载原生库。现在,应用就可以使用库的原生函数 stringFromJNI() 了。
-
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的结果了