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。
核心步骤与示例代码
- 在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
相关产品推荐
相关产品推荐

