You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 9下android_createDisplaySurface替代方案及编译报错咨询

Android 9下OpenGL C应用获取显示窗口的解决方案

错误原因分析

  • 未定义引用错误:android_createDisplaySurface()是Android早期的私有内部API,Android 9开始严格限制私有API的访问,链接器无法找到该函数的公开实现,因此报错。
  • 总线错误(移除函数后):未获取到有效的显示表面(Display Surface),后续EGL渲染操作访问了非法内存地址,触发总线错误。

替代方案:使用官方公开API获取显示窗口

Android NDK提供了标准的ANativeWindow接口来获取显示窗口,推荐基于Native Activity框架开发,这是官方支持的Native OpenGL开发方式,无需依赖私有API。

核心步骤与示例代码

  1. 在Native代码中监听APP_CMD_INIT_WINDOW事件,从android_app结构体中获取ANativeWindow实例:
#include <android/native_activity.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>

EGLDisplay g_display;
EGLSurface g_surface;
EGLContext g_context;

void handle_android_cmd(struct android_app* app, int32_t cmd) {
    switch (cmd) {
        case APP_CMD_INIT_WINDOW:
            // 窗口初始化完成,获取ANativeWindow
            if (app->window == NULL) break;

            // 初始化EGL
            g_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
            eglInitialize(g_display, NULL, NULL);

            // 配置EGL参数
            const EGLint config_attrs[] = {
                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                EGL_RED_SIZE, 8,
                EGL_GREEN_SIZE, 8,
                EGL_BLUE_SIZE, 8,
                EGL_ALPHA_SIZE, 8,
                EGL_DEPTH_SIZE, 16,
                EGL_NONE
            };
            EGLConfig config;
            EGLint num_configs;
            eglChooseConfig(g_display, config_attrs, &config, 1, &num_configs);

            // 使用ANativeWindow创建EGL表面
            g_surface = eglCreateWindowSurface(g_display, config, app->window, NULL);

            // 创建并绑定EGL上下文
            const EGLint context_attrs[] = {
                EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL_NONE
            };
            g_context = eglCreateContext(g_display, config, EGL_NO_CONTEXT, context_attrs);
            eglMakeCurrent(g_display, g_surface, g_surface, g_context);

            // 后续即可进行OpenGL渲染操作
            break;

        case APP_CMD_TERM_WINDOW:
            // 窗口销毁时释放EGL资源
            eglMakeCurrent(g_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            eglDestroySurface(g_display, g_surface);
            eglDestroyContext(g_display, g_context);
            eglTerminate(g_display);
            g_display = EGL_NO_DISPLAY;
            g_surface = EGL_NO_SURFACE;
            g_context = EGL_NO_CONTEXT;
            break;
    }
}

// Native Activity入口
void android_main(struct android_app* app) {
    app->onAppCmd = handle_android_cmd;
    // 事件循环
    int events;
    struct android_poll_source* source;
    while (ALooper_pollAll(-1, NULL, &events, (void**)&source) >= 0) {
        if (source != NULL) {
            source->process(app, source);
        }
    }
}

编译配置要求

确保在构建脚本中链接必要的系统库:

  • 若使用CMake,在CMakeLists.txt中添加:
add_library(your_app_name SHARED main.c)

target_link_libraries(your_app_name
    android
    EGL
    GLESv2
    log
)
  • 若使用Android.mk,添加:
LOCAL_LDLIBS += -landroid -lEGL -lGLESv2 -llog

额外注意事项

  • 必须正确处理Native Activity的生命周期事件(如窗口初始化、销毁),避免因访问无效窗口指针导致内存错误。
  • 不要尝试使用私有API绕开限制,Android 9及以上版本会严格拦截私有API调用,可能导致应用无法运行或被系统封杀。

内容的提问来源于stack exchange,提问作者Karthik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 04:40:26