Android WebView 文件上传功能失效问题求助
解决Android WebView文件上传失效的问题
嘿,我一眼就看出问题所在啦!你的WebView代码里没有处理文件上传的Intent请求——默认情况下,Android WebView不会自动弹出文件选择器,特别是从KitKat(API 19)开始,我们得手动实现相关回调才能让文件上传功能正常工作。
下面是具体的修复步骤和完整代码:
1. 核心问题分析
你的代码只设置了WebViewClient(负责页面导航逻辑),但文件上传需要依赖WebChromeClient来处理浏览器发起的文件选择请求。从Android 5.0(API 21)开始,官方推荐使用onShowFileChooser方法,同时我们也要兼容旧版本的openFileChooser方法来覆盖更多系统版本。
2. 修复后的完整代码
import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.webkit.ValueCallback; import android.webkit.WebChromeClient.FileChooserParams; public class MainActivity extends AppCompatActivity { private WebView myWebView; // 用于接收文件选择结果的回调对象 private ValueCallback<Uri[]> filePathCallback; private static final int FILE_CHOOSER_REQUEST_CODE = 1000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myWebView = findViewById(R.id.webView); WebSettings webSettings = myWebView.getSettings(); // 开启JavaScript(你已经完成这一步) webSettings.setJavaScriptEnabled(true); // 开启文件访问权限,确保WebView能访问本地文件 webSettings.setAllowFileAccess(true); webSettings.setAllowContentAccess(true); myWebView.loadUrl("your domain url"); myWebView.setWebViewClient(new WebViewClient()); // 关键操作:设置WebChromeClient处理文件上传请求 myWebView.setWebChromeClient(new WebChromeClient() { // Android 5.0+ 版本的文件选择回调 @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { // 先释放之前的回调,避免内存泄漏 if (MainActivity.this.filePathCallback != null) { MainActivity.this.filePathCallback.onReceiveValue(null); } MainActivity.this.filePathCallback = filePathCallback; // 启动系统默认的文件选择器 Intent intent = fileChooserParams.createIntent(); try { startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE); } catch (Exception e) { MainActivity.this.filePathCallback = null; return false; } return true; } // 兼容Android 5.0以下版本的文件选择回调 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { ValueCallback<Uri[]> filePathCallbackWrapper = new ValueCallback<Uri[]>() { @Override public void onReceiveValue(Uri[] uris) { uploadMsg.onReceiveValue(uris != null && uris.length > 0 ? uris[0] : null); } }; openFileChooser(filePathCallbackWrapper, acceptType, capture); } }); } // 处理文件选择后的返回结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == FILE_CHOOSER_REQUEST_CODE) { Uri[] results = null; // 判断文件选择是否成功 if (resultCode == Activity.RESULT_OK) { if (data != null) { String dataString = data.getDataString(); if (dataString != null) { results = new Uri[]{Uri.parse(dataString)}; } } } // 将结果返回给WebView,完成文件上传的触发逻辑 if (filePathCallback != null) { filePathCallback.onReceiveValue(results); filePathCallback = null; } } } @Override public void onBackPressed() { if(myWebView.canGoBack()){ myWebView.goBack(); } else { super.onBackPressed(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
3. 额外注意事项
- 权限配置:在
AndroidManifest.xml中添加文件读取权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- 动态权限申请:如果你的应用目标SDK版本是23及以上,还需要在代码中动态请求
READ_EXTERNAL_STORAGE权限,否则文件选择器可能无法正常访问设备存储。
这样修改后,你的WebView就能正常触发文件上传选择器,完美解决KitKat、Lollipop及更高版本的文件上传失效问题啦!
内容的提问来源于stack exchange,提问作者waheed
相关产品推荐
相关产品推荐

