Android中设置WebChromeClient后无法调用WebView的onPageStarted及文件上传问题
针对你遇到的两个Android WebView问题的解决方案
问题1:设置WebChromeClient后无法调用WebView的onPageStarted方法
这是个很容易混淆的点——onPageStarted是WebViewClient的专属回调方法,和WebChromeClient完全是两个独立的类,职责完全不同。
你只设置WebChromeClient并不会影响WebViewClient的回调,大概率是你没给WebView配置自定义的WebViewClient,或者不小心忽略了它的设置。解决方法很简单:同时给WebView设置WebViewClient并重写onPageStarted即可,两个Client可以共存,互不干扰:
webView.setWebViewClient(new WebViewClient() { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); // 在这里写你的页面开始加载逻辑,比如显示加载进度条 } }); // 你的WebChromeClient设置依然保留,它负责处理浏览器UI相关的逻辑(比如文件选择、JS弹窗) webView.setWebChromeClient(new WebChromeClient() { // 你的WebChromeClient逻辑 });
简单总结:WebViewClient管页面加载生命周期,WebChromeClient管浏览器交互UI,两者各司其职,同时设置就好。
问题2:WebView文件上传的完整实现
从你给出的代码片段来看,你已经处理了权限申请的第一步,但完整的文件上传还需要在WebChromeClient中处理文件选择的回调,还要适配不同Android版本的差异。下面是完整的实现方案:
1. 补全权限申请的回调逻辑
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); // 假设权限请求的code是100 if (requestCode == 100) { boolean allPermissionsGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allPermissionsGranted = false; break; } } if (allPermissionsGranted) { // 权限全部通过,重新加载WebView或者触发文件选择操作 loadWebView(yourTargetUrl); } else { // 提示用户需要权限才能完成文件上传 Toast.makeText(getActivity(), "需要存储和相机权限才能上传文件", Toast.LENGTH_SHORT).show(); } } }
2. 在WebChromeClient中重写文件选择回调(适配多版本)
// 定义全局变量保存回调,用于在onActivityResult中返回结果 private ValueCallback<Uri[]> mFilePathCallback; private ValueCallback<Uri> mUploadMsg; private static final int FILE_CHOOSER_REQUEST_CODE = 101; // 在loadWebView方法中设置WebChromeClient webView.setWebChromeClient(new WebChromeClient() { // 适配Android 5.0及以上版本 @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { mFilePathCallback = filePathCallback; // 调用系统文件选择器 Intent intent = fileChooserParams.createIntent(); try { startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE); } catch (ActivityNotFoundException e) { mFilePathCallback = null; Toast.makeText(getActivity(), "无法打开文件选择器", Toast.LENGTH_SHORT).show(); return false; } return true; } // 适配Android 4.1-4.4版本 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { mUploadMsg = uploadMsg; Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); // 允许选择所有类型文件 startActivityForResult(Intent.createChooser(intent, "选择文件"), FILE_CHOOSER_REQUEST_CODE); } });
3. 在onActivityResult中处理返回的文件Uri
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == FILE_CHOOSER_REQUEST_CODE) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (mFilePathCallback == null) return; Uri[] results = null; // 处理选择的文件结果 if (resultCode == Activity.RESULT_OK && data != null) { String dataString = data.getDataString(); ClipData clipData = data.getClipData(); if (clipData != null) { results = new Uri[clipData.getItemCount()]; for (int i = 0; i < clipData.getItemCount(); i++) { ClipData.Item item = clipData.getItemAt(i); results[i] = item.getUri(); } } else if (dataString != null) { results = new Uri[]{Uri.parse(dataString)}; } } // 将结果返回给WebView mFilePathCallback.onReceiveValue(results); mFilePathCallback = null; } else { // 处理低版本逻辑 if (mUploadMsg == null) return; Uri result = (resultCode == Activity.RESULT_OK && data != null) ? data.getData() : null; mUploadMsg.onReceiveValue(result); mUploadMsg = null; } } }
4. 补全WebView的基础配置
@SuppressLint("SetJavaScriptEnabled") private void loadWebView(String url) { if (getActivity() == null) return; // 权限检查 if (Build.VERSION.SDK_INT >= 23 && (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 100); return; } // WebView基础配置 WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setAllowFileAccess(true); settings.setAllowFileAccessFromFileURLs(true); settings.setAllowUniversalAccessFromFileURLs(true); // 同时设置WebViewClient和WebChromeClient webView.setWebViewClient(new WebViewClient() { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); // 页面开始加载的逻辑 } }); // 上面的WebChromeClient设置写在这里 webView.loadUrl(url); }
内容的提问来源于stack exchange,提问作者user4813855
相关产品推荐
相关产品推荐

