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

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)

验证步骤

  1. 先禁用原生对话框,测试非原生FileDialog是否能触发回调
  2. 检查ADB日志是否仍存在VK_ERROR_SURFACE_LOST_KHR错误
  3. 确认权限申请弹窗正常弹出并被允许
  4. 测试文件选择后的加载逻辑是否正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:06:18