Android 12 编译 JNI 库的初探
在 Android 应用开发中,使用 JNI(Java Native Interface)可以让我们在 Java 中调用 C/C++ 代码,从而提升性能或者利用某些特定的系统功能。然而,组合 Java 和 C/C++ 需要一些设置和配置,特别是在 Android 12 环境下。本文将详细介绍如何编译 JNI 库,并提供代码示例。
1. JNI 库结构
一个标准的 JNI 库通常包含以下几个部分:
- C/C++ 源代码
- Java 接口类
- 构建配置文件(如 CMakeLists.txt 或 Android.mk)
1.1 目录结构示例
MyApplication/
├── app/
│ ├── src/
│ │ ├── main/
│ │ │ ├── cpp/
│ │ │ │ └── native-lib.cpp
│ │ │ ├── java/
│ │ │ │ └── com/example/myapplication/
│ │ │ │ └── MainActivity.java
│ │ │ └── CMakeLists.txt
└── build.gradle
在上述结构中,native-lib.cpp
是我们的 JNI 实现代码,MainActivity.java
是调用 JNI 方法的 Java 部分,而 CMakeLists.txt
是构建过程的配置文件。
2. 编写 C++ 代码
首先,我们需要编写 C++ 代码并声明 JNI 方法。以下是一个简单的 C++ 示例,它定义了一个返回字符串的方法。
2.1 C++ 示例代码
在 native-lib.cpp
中:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(JNIEnv* env, jobject) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
这里,我们使用 extern "C"
来保证 C++ 的命名不会被修改,并创建了一个 JNI 方法 stringFromJNI
。这个方法返回一个 jstring
,即 Java 字符串。
3. Java 接口类
接下来,我们需要 Java 类来调用这个 JNI 方法。在 MainActivity.java
文件中,我们需要添加加载库和调用方法的代码。
3.1 Java 示例代码
package com.example.myapplication;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.sample_text);
textView.setText(stringFromJNI());
}
public native String stringFromJNI();
}
在这个 Java 类中,System.loadLibrary("native-lib");
语句用于加载我们的 JNI 库,而 stringFromJNI()
是声明的 JNI 方法,将返回 C++ 返回的字符串。
4. 配置 CMakeLists.txt
为了让 Android Studio 知道如何构建 JNI 库,我们需要配置 CMakeLists.txt
文件。以下是一个基本的配置:
4.1 CMakeLists.txt 示例代码
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib SHARED native-lib.cpp)
find_library(log-lib log)
target_link_libraries(native-lib ${log-lib})
在以上配置中,我们指明了创建一个名为 native-lib
的共享库,同时连接了 Android 的日志库。
5. 构建与运行
完成所有代码后,你可以通过 Android Studio 的 Build 功能来构建项目。这时,C++ 代码将被编译为 JNI 库,并与 Java 代码一起打包到 APK 中。
6. 关系图
为了更好地理解 JNI 的工作机制,下面用 mermaid 语法展示 JNI 与 Android 组件之间的关系图:
erDiagram
JNI {
+string stringFromJNI()
}
MainActivity {
+void onCreate()
+String stringFromJNI()
}
MainActivity ||--o{ JNI : calls
在这个关系图中,我们可以看到 MainActivity
类通过 JNI 方法 stringFromJNI
进行交互。
7. 状态图
下面是用 mermaid 语法展示的应用在 JNI 调用中的状态图:
stateDiagram
[*] --> Idle
Idle --> CallingJNI
CallingJNI --> Returning
Returning --> Idle
在状态图中,应用首先处于 Idle
(空闲)状态,当调用 JNI 方法后,它进入 CallingJNI
状态,然后返回到 Idle
状态。
8. 结论
本文简要介绍了如何在 Android 12 中编译 JNI 库的基础知识。通过示例代码和图示,我们了解到涉及 C/C++ 代码与 Java 代码交互的过程。随着 Android 应用日益复杂,掌握 JNI 的使用能够帮助开发者在 Android 平台上更高效地运行特定任务。
编写和调试 JNI 代码可能会遇到许多挑战,但理解其工作原理和构建流程无疑是克服这些挑战的第一步。希望这篇文章对您在 Android 开发过程中使用 JNI 有所帮助。