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
相关产品推荐
相关产品推荐

