在Android Studio中复现AOSP原生GL2JNI图形渲染应用
引言
在Android系统底层开发中,图形渲染是核心能力之一。AOSP(Android开源项目)中内置了许多图形测试工具,其中GL2JNI
是一个典型的OpenGL ES 2.0渲染测试应用,用于验证GPU的基础渲染能力(如三角形绘制、颜色渐变等)。本文将以从零开始在Android Studio中复现GL2JNI应用为目标,详细讲解如何将AOSP的原生代码迁移到AS项目(Android14 SDK=33),并实现图形渲染功能。
一、背景知识:GL2JNI的核心作用
GL2JNI
(全称GL2 JNI Test
)是AOSP中用于测试OpenGL ES 2.0接口的基础应用。它通过JNI(Java Native Interface)桥接Java层与C++层,调用底层图形API完成渲染逻辑。其核心功能包括:
- 初始化OpenGL上下文;
- 绘制带颜色渐变的三角形;
- 验证GPU对OpenGL ES 2.0的支持能力。
在AOSP中,GL2JNI
的源码位于frameworks/native/opengl/tests/gl2_jni
目录,包含Java层逻辑(GL2JNIActivity
、GL2JNILib
)和C++层渲染代码(gl_code.cpp
)。我们的目标是将这些代码迁移到Android Studio项目中,并实现相同效果。
AOSP原生GL2JNI目录为frameworks/native/opengl/tests/gl2_jni
c
gl2_jni/
├── src/
│ ├── com.android.gl2jni/
│ │ ├── GL2JNIActivity.java
│ │ ├── GL2JNILib.java
│ │ └── GL2JNIView.java
├── jni/
│ ├── gl_code.cpp
├── res/
│ ├── string,xml
├── Android.bp
└── AndroidManifest.xml
二、环境准备与项目初始化
1. 创建Android Studio项目
新建一个Empty Activity C++项目,包名保持与AOSP一致(com.android.gl2jni
),确保后续JNI接口的兼容性。
2. 关键目录结构规划
最终项目需要以下核心目录:
bash
app/
├── src/
│ ├── main/com.android.gl2jni/
│ │ ├── java/ # Java层代码(Activity、View)
│ │ ├── jniLibs/ # 存放不同ABI的SO库(arm64-v8a、armeabi-v7a等)
│ │ └── res/ # 资源文件(可选,本文未使用)
│ └── cpp/ # C++层代码(原gl_code.cpp)
│ │ └── CMakeLists.txt # CMake构建脚本(链接OpenGL库)
│ │ └── native-lib.cpp # gl_code.cpp复制的内容
└── build.gradle # Gradle配置(指定SO库路径)
三、Java层代码迁移与调整
1. 复制AOSP的Java代码
从AOSP的frameworks/native/opengl/tests/gl2_jni/src
目录复制以下文件到AS项目的src/main/java/com/android/gl2jni
目录:
GL2JNIActivity.java
(主Activity)GL2JNILib.java
(JNI接口封装类)GL2JNIView.java
(自定义View,用于承载OpenGL渲染)
2. 修改启动Activity
AOSP中默认启动的是MainActivity
,需在AndroidManifest.xml
中将启动Activity改为GL2JNIActivity
:
xml
xml
复制
<application
...>
<activity android:name=".GL2JNIActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
四、JNI接口适配:从对象到类的调用
1. JNI接口的变化
AOSP中的JNI接口定义在GL2JNILib.java
中,通过native
方法声明:
arduino
java
复制
public class GL2JNILib {
static {
System.loadLibrary("gl2jni");
}
public native void init(int width, int height);
public native void step();
}
但在AS项目中,由于JNI接口需与C++函数签名严格匹配,需注意以下两点:
- 参数类型调整 :Java的
jobject
(对象引用)在C++中需改为jclass
(类引用),因为静态方法通过类调用。 - 函数签名修正 :AOSP的JNI接口最初设计为静态方法(
static
),但实际调用时需通过类名而非对象实例。
2. 修改C++接口声明
将AOSP的gl_code.cpp
中的全部内容复制到AS C++项目自动创建的native-lib.cpp
中,然后将JNI函数签名调整为适配AS项目的形式:
arduino
cpp
// 原AOSP接口(对象引用)
extern "C" {
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj);
};
// 修改后(类引用)
extern "C" {
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jclass clazz, jint width, jint height);
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jclass clazz);
};
五、CMake配置:链接OpenGL库
1. 编写CMakeLists.txt
AS项目通过CMake构建原生代码,需在app
目录下创建CMakeLists.txt
,并添加以下内容:
scss
cmake
复制
cmake_minimum_required(VERSION 3.18.1)
project("gl2jni")
# 查找OpenGL ES 2.0库(GLESv2)
find_library(
GLESv2_LIB
GLESv2
)
# 目标库配置(libgl2jni.so)
add_library(
gl2jni
SHARED
native-lib.cpp # 自动创建的 并且是gl_code.cpp的内容
)
# 链接系统库(Android运行时、EGL、GLESv2、日志)
target_link_libraries(
gl2jni
android
GLESv2_LIB
EGL
log
atomic
)
2. 关键参数说明
find_library
:定位系统提供的OpenGL ES 2.0库(GLESv2
)。target_link_libraries
:将gl2jni
库与系统库链接,确保OpenGL API可用。
六、SO库打包:适配多ABI
1. 准备SO文件
AOSP编译后会生成libgl2jni.so
(位于out/target/product/<设备名>/system/lib/
或lib64/
)。需将该文件复制 到AS项目的app/src/main/jniLibs
目录下(没有jniLibs手动创建一个package),并按ABI分类,创建下面的目录格式:
css
app/src/main/
└── jniLibs/
├── arm64-v8a/
│ └── libgl2jni.so
├── armeabi-v7a/
│ └── libgl2jni.so
├── x86/
│ └── libgl2jni.so
└── x86_64/
└── libgl2jni.so
2. 配置Gradle识别SO库
在app/build.gradle
中添加以下配置,告知Gradle将jniLibs
目录下的SO文件打包到APK中:
ini
groovy
复制
android {
...
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs'] # 指定SO库路径
}
}
}
七、构建与运行验证
1. 同步项目
点击Android Studio的Sync Project with Gradle Files
按钮,确保CMake和Gradle配置生效。
2. 运行应用
选择一台支持OpenGL ES 2.0的设备(或模拟器),运行应用。若看到一个渐变绿色的三角形,则说明渲染成功。
最后如果喜欢这篇文章的话,还请点个赞多多支持!
如果存在任何问题欢迎评论区或者私信,感谢各位大佬的阅读!