Android OpenGL 教程——Native 工程初始化

NativeActivity

NDK 的适用场景官方给出三点:

  1. 平台间的 App 移植
  2. 复用现有库
  3. 对软件性能要求较高的场合比如游戏等

有两种方式可以实现 native activity。

  1. native_activity.h
  2. android_native_app_glue

由于第二种方法启用另一个线程处理回调和输入事件,NDK 的例子中就采用了这个实现方式。

工程初始化

创建 NDK 工程

NDK 工程创建完成会生成一个带有 JNI 调用 c++ 返回 HelloWorld 字符串的一个初始化工程

配置 NativeActivity

首先在 AndroidManifest.xml 文件中添加 Name 为 android.app.lib_name(不可更改) 的 MetaData

XML 复制代码
<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <meta-data android:name="android.app.lib_name" android:value="OpenGLDemo" />

</activity>

将我们 MainActivity 改为继承 NativeActivity,并加载 native 生成的 OpenGLDemo.so

java 复制代码
import android.app.NativeActivity
class MainActivity : NativeActivity() {
    companion object {
        init {
            System.loadLibrary("OpenGLDemo")
        }
    }
}

配置 CMakeList 文件

cpp 复制代码
cmake_minimum_required(VERSION 3.22.1)

# 与之前在 Manifest 文件中配置的一样
project("OpenGLDemo")

# 添加 native_app_glue
set(APP_GLUE_DIR ${ANDROID_NDK}/sources/android/native_app_glue)
include_directories(${APP_GLUE_DIR})
add_library(app-glue STATIC ${APP_GLUE_DIR}/android_native_app_glue.c)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")

# 添加源码和头文件
file(GLOB LOCAL_SOURCE  "${CMAKE_SOURCE_DIR}/*.cpp")
file(GLOB LOCAL_HEADER "${CMAKE_SOURCE_DIR}/*.h")
add_library(${CMAKE_PROJECT_NAME} SHARED
        ${LOCAL_HEADERS}
        ${LOCAL_SOURCE})

# 指定 CMake 应链接到您的目标库的库
target_link_libraries(${CMAKE_PROJECT_NAME}
        android
        EGL
        GLESv3
        jnigraphics
        app-glue
        log)

创建 main.cpp 的 native 入口文件

cpp 复制代码
#include <android_native_app_glue.h>
#include <jni.h>

static int32_t handle_input(struct android_app* app, AInputEvent* event) {
    return 0;
}

static void handle_cmd(struct android_app *app, int32_t cmd) {
    switch (cmd) {
        case APP_CMD_RESUME: {
            break;
        }
        case APP_CMD_PAUSE: {
            break;
        }
        default:
            break;
    }
}

void android_main(struct android_app *app) {
    app->onAppCmd = handle_cmd;
    app->onInputEvent = handle_input;
    // 循环等待要做的事情。
    while (!app->destroyRequested) {
        int events;
        struct android_poll_source *source;
        // 获取需要处理的事件
        if (ALooper_pollAll(0, nullptr, &events, (void **) &source) >= 0) {
            if (source) {
                source->process(app, source);
            }
        }
    }
}

至此我们的 native 工程就配置完成了,运行后你会看到一个纯黑的窗口,那是因为我们没有为当前 MainActivity 创建的 Window 绘制任何东西

要想绘制东西,需要初始化 OpenGL ,创建对应的 Display 与 Surface 与当前的 window 进行绑定

详见 Android OpenGL 教程------窗口初始化

OpenGLDemo 源码的 init_native_activity 分支

相关推荐
氦客7 小时前
Android Compose : 传统View在Compose组件中的等价物
android·compose·jetpack·对比·传统view·等价物·compose组件
神话20097 小时前
Rust 初体验与快速上手指南
android·rust
CheungChunChiu8 小时前
Linux 内核动态打印机制详解
android·linux·服务器·前端·ubuntu
aidou13149 小时前
Android中设置Dialog和自定义布局相同高度
android·dialog·弹窗高度·getwindow
氦客9 小时前
UI编程的发展史 : 结合命令式UI和声明式UI
android·compose·声明式ui·ui编程·命令式ui·ui编程发展史·标记语言
aidou131411 小时前
Android中RecyclerView实现多级列表
android·recyclerview·多级列表·layoutmanager
青风行11 小时前
Android从入门到进阶
android
方白羽12 小时前
Android 开发中,准确判断应用处于“前台(Foreground)”还是“后台(Background)
android·app·客户端
Mart!nHu13 小时前
Android 10&15 Framework 允许设置系统时间早于编译时间
android
编程之路从0到114 小时前
ReactNative新架构之Android端TurboModule机制完全解析
android·react native·源码阅读