Godot安卓端文件选择异常:无法触发文件选中回调函数
Godot安卓端文件选择回调失效与Vulkan表面丢失问题修复
问题背景
开发的Godot游戏/模拟器支持图片、音乐加载功能,Windows端及编辑器运行正常,但移植到安卓后出现以下问题:
- 原生文件对话框可正常打开,但选中文件后
_on_file_dialog_file_selected回调未触发,文件无法加载 - 已配置安卓权限:
permissions/read_media_images=true、permissions/read_external_storage=true、permissions/manage_external_storage=true - ADB日志出现
VK_ERROR_SURFACE_LOST_KHR错误,推测为打开文件对话框时App后台化导致Vulkan渲染表面失效
问题诊断
VK_ERROR_SURFACE_LOST_KHR会导致Godot主线程状态异常,打断文件对话框的事件派发流程——打开原生文件对话框时安卓将App置于后台,Vulkan渲染表面被销毁,恢复时若未正确重建表面,会直接导致后续回调无法触发。同时FileDialog的配置细节、权限生效状态也可能加剧问题。
针对性修复方案
1. 修正FileDialog配置与回调拼写错误
原代码中存在回调函数名拼写错误(cancled应为canceled),同时调整安卓端路径适配逻辑:
func setup_file_dialogue(): file_dialog.filters = [ "*.png ; PNG Images", "*.jpg, *.jpeg ; JPG Images" ] file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE file_dialog.access = FileDialog.ACCESS_FILESYSTEM file_dialog.title = "Select Ball Image" # 修复回调函数名拼写错误 file_dialog.canceled.connect(_on_file_dialog_canceled) file_dialog.file_selected.connect(_on_file_dialog_file_selected) if Global.main.os_name == "Android": # 使用Godot标准外部存储路径,避免硬编码 file_dialog.root_subfolder = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) # 临时禁用原生对话框,先验证回调逻辑 file_dialog.use_native_dialog = false else: file_dialog.use_native_dialog = true
2. 处理Vulkan表面丢失的恢复逻辑
在主场景的_notification函数中添加焦点变化时的渲染状态处理:
func _notification(what): if what == NOTIFICATION_WM_FOCUS_IN: # 重新初始化渲染上下文,修复Vulkan表面丢失 if VisualServer.get_rendering_device().get_device_status() != RenderingDevice.STATUS_OK: VisualServer.reset() elif what == NOTIFICATION_WM_FOCUS_OUT: # 后台时暂停渲染,避免Vulkan错误 VisualServer.set_rendering_disabled(true)
3. 动态申请安卓媒体权限
安卓13+需动态申请媒体权限,添加权限校验与申请逻辑:
func _ready(): if Global.main.os_name == "Android": # 安卓13+申请媒体图片权限 if not OS.has_permission("android.permission.READ_MEDIA_IMAGES"): OS.request_permission("android.permission.READ_MEDIA_IMAGES") # 安卓12及以下申请外部存储权限 if OS.get_version_code() < 33 and not OS.has_permission("android.permission.READ_EXTERNAL_STORAGE"): OS.request_permission("android.permission.READ_EXTERNAL_STORAGE")
4. 备选:改用安卓Intent文件选择器
若原生FileDialog问题无法解决,直接调用安卓系统文件选择器:
func open_android_file_picker(): var intent = Intent.new() intent.set_action(Intent.ACTION_GET_CONTENT) intent.set_type("image/*") intent.add_category(Intent.CATEGORY_OPENABLE) OS.start_activity(intent, "file_selected_callback") # 处理Intent返回结果 func _on_android_intent_result(request_code, result_code, data): if result_code == Activity.RESULT_OK: var uri = data.get_data() # 将URI转换为可访问路径 var path = AndroidContentProvider.get_real_path_from_uri(uri) if path: _on_file_dialog_file_selected(path)
验证步骤
- 先禁用原生对话框,测试非原生FileDialog是否能触发回调
- 检查ADB日志是否仍存在
VK_ERROR_SURFACE_LOST_KHR错误 - 确认权限申请弹窗正常弹出并被允许
- 测试文件选择后的加载逻辑是否正常
内容的提问来源于stack exchange,提问作者Surya Neupane
相关产品推荐
相关产品推荐

