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

Android WebView中HTML文件选择对话框无法弹出的解决求助

解决WebView中无法唤起选择界面的问题

WebView默认不会处理文件选择的交互逻辑,需要手动配置WebChromeClient并处理权限,以下是完整解决方案:

1. 添加必要权限

在AndroidManifest.xml中添加文件访问和网络权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 13+ 替换为媒体权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

<!-- Android 10+ 适配分区存储(兼容旧文件访问逻辑) -->
<application
    ...
    android:requestLegacyExternalStorage="true">
</application>

2. 修改MainActivity.java代码

替换原代码为以下实现,核心是通过WebChromeClient处理文件选择回调:

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.webkit.ValueCallback;

public class MainActivity extends AppCompatActivity {
    private WebView webView;
    private static final int FILE_CHOOSER_REQUEST_CODE = 1001;
    private static final int PERMISSION_REQUEST_CODE = 1002;
    private ValueCallback<Uri[]> filePathCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = findViewById(R.id.webview);

        // 初始化WebView基础设置
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setDomStorageEnabled(true);

        // 设置自定义WebViewClient处理内部链接跳转
        webView.setWebViewClient(new MyWebView());

        // 设置WebChromeClient处理文件选择弹窗逻辑
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                MainActivity.this.filePathCallback = filePathCallback;
                // 唤起系统文件选择界面
                Intent intent = fileChooserParams.createIntent();
                try {
                    startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE);
                } catch (Exception e) {
                    filePathCallback.onReceiveValue(null);
                    Toast.makeText(MainActivity.this, "无法打开文件选择器", Toast.LENGTH_SHORT).show();
                    return false;
                }
                return true;
            }
        });

        // Android 6.0+ 动态申请存储权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String[] permissions = {android.Manifest.permission.READ_EXTERNAL_STORAGE};
            if (checkSelfPermission(permissions[0]) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(permissions, PERMISSION_REQUEST_CODE);
            }
        }

        webView.loadUrl("https://www.mysitenamegoeshear.com/");
    }

    // 处理文件选择结果回传
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILE_CHOOSER_REQUEST_CODE) {
            if (filePathCallback == null) return;
            // 解析选择的文件Uri并传递给WebView
            Uri[] results = WebChromeClient.FileChooserParams.parseResult(resultCode, data);
            filePathCallback.onReceiveValue(results);
            filePathCallback = null;
        }
    }

    // 处理权限申请结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限已授予,可正常使用文件上传功能
            } else {
                Toast.makeText(this, "存储权限被拒绝,无法上传文件", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private class MyWebView extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            // 让WebView内部处理链接跳转,不打开外部浏览器
            view.loadUrl(request.getUrl().toString());
            return true;
        }
    }

    @Override
    public void onBackPressed() {
        if (webView.isFocused() && webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}

关键说明

  • WebChromeClient:文件选择的UI交互由WebChromeClient负责,必须重写onShowFileChooser方法来唤起系统选择界面
  • 权限处理:Android 6.0+需要动态申请存储权限,否则无法访问本地文件
  • 回调传递:保存ValueCallback并在onActivityResult中返回选择结果,确保WebView能接收到文件信息

你的HTML代码没有问题,问题根源在于WebView默认未配置文件选择的处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 10:29:55