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

Android新版本WebView文件上传按钮失效问题求助

WebView文件上传选择器修复方案

核心问题

你的WebView未实现文件上传的回调逻辑,默认情况下WebView不会响应网页的文件选择请求,这就是它和Chrome浏览器的核心区别。以下是具体修复步骤:


步骤1:添加动态权限申请逻辑

Android 6.0及以上版本,除了Manifest声明权限,还需要在运行时动态请求READ_EXTERNAL_STORAGE和CAMERA权限。在MainActivity中添加权限请求代码:

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
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 androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.List;

private static final int REQUEST_PERMISSIONS = 100;
private static final int FILE_CHOOSER_REQUEST_CODE = 101;
private ValueCallback<Uri[]> filePathCallback;
private WebView webView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 先检查权限
    checkPermissions();
}

private void checkPermissions() {
    List<String> neededPermissions = new ArrayList<>();
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        neededPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
    }
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        neededPermissions.add(Manifest.permission.CAMERA);
    }
    if (!neededPermissions.isEmpty()) {
        ActivityCompat.requestPermissions(this, neededPermissions.toArray(new String[0]), REQUEST_PERMISSIONS);
    } else {
        initWebView(); // 权限已获取,初始化WebView
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSIONS) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }
        if (allGranted) {
            initWebView();
        } else {
            Toast.makeText(this, "需要开启存储和相机权限才能使用文件上传功能", Toast.LENGTH_SHORT).show();
        }
    }
}

步骤2:实现WebChromeClient处理文件选择

创建自定义WebChromeClient,重写onShowFileChooser方法,响应网页的文件选择请求:

private class CustomWebChromeClient extends WebChromeClient {
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        // 保存回调,用于后续返回结果
        MainActivity.this.filePathCallback = filePathCallback;
        
        // 构建文件选择Intent
        Intent intent = fileChooserParams.createIntent();
        try {
            startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE);
        } catch (ActivityNotFoundException e) {
            filePathCallback.onReceiveValue(null);
            return false;
        }
        return true;
    }
}

// 处理文件选择结果
@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[] results = null;
        if (resultCode == Activity.RESULT_OK) {
            if (data != null) {
                String dataString = data.getDataString();
                android.content.ClipData clipData = data.getClipData();
                
                if (clipData != null) {
                    results = new Uri[clipData.getItemCount()];
                    for (int i = 0; i < clipData.getItemCount(); i++) {
                        android.content.ClipData.Item item = clipData.getItemAt(i);
                        results[i] = item.getUri();
                    }
                } else if (dataString != null) {
                    results = new Uri[]{Uri.parse(dataString)};
                }
            }
        }
        filePathCallback.onReceiveValue(results);
        filePathCallback = null;
    }
}

步骤3:调整WebView初始化逻辑

将原有WebView初始化代码移到initWebView方法中,并设置自定义的WebChromeClient,同时添加必要的WebSettings配置:

private void initWebView() {
    webView = findViewById(R.id.webview);
    
    // 配置WebSettings
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    // 允许访问文件
    webSettings.setAllowFileAccess(true);
    webSettings.setAllowContentAccess(true);
    // 启用DOM存储API,部分网页上传依赖此
    webSettings.setDomStorageEnabled(true);
    
    // 设置WebViewClient(合并原有逻辑,避免重复设置)
    webView.setWebViewClient(new GeoWebViewClient() {
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            webView.loadUrl("file:///android_asset/error.html");
        }
    });
    
    // 设置自定义WebChromeClient
    webView.setWebChromeClient(new CustomWebChromeClient());
    
    webView.loadUrl("https://srje.posone.one/");
}

// 保留原有GeoWebViewClient类
public class GeoWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
}

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

步骤4:清理原有重复代码

你的原有代码中重复调用了3次setWebViewClient,会覆盖之前的设置,上述代码已合并为一次设置,避免逻辑冲突。


额外注意事项

  • Android 10及以上版本,WRITE_EXTERNAL_STORAGE权限已被废弃,无需动态请求,网页上传会通过MediaStore或SAF自动适配。
  • 确保网页中的文件上传控件使用标准的<input type="file">标签,非自定义上传逻辑可能需要额外适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:31:06