我一直在努力从WebView上传文件。我在谷歌上搜索并实施了所有建议的解决方案(例如这篇SO帖子),但没有一个可行。
我有一个HTML页面与以下代码上传文件。
<form method="POST" enctype="multipart/form-data">
File to upload: <input type="file" name="uploadfile">
<input type="submit" value="Press to Upload..."> to upload the file!
</form>
它在桌面浏览器如Firefox和内置浏览器中运行良好
的模拟器/ AVD,即,当我点击“浏览…”按钮渲染
元素,浏览器打开一个对话框
框,在那里我可以选择一个文件上传。
然而,在android 3.0模拟器/ AVD中,当我点击“选择”
文件”,什么都没有发生,没有文件对话框被打开!
自定义WebChromeClient:
class AppChromeClient(private val fragmentWeakReference: WeakReference<WebViewFragment>) :
WebChromeClient() {
private var openFileCallback: ValueCallback<Array<Uri>>? = null
override fun onShowFileChooser(
webView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
if (filePathCallback == null) {
return (super.onShowFileChooser(webView, filePathCallback, fileChooserParams))
}
openFileCallback = filePathCallback
val webViewFragment = fragmentWeakReference.get() ?: return false
webViewFragment.launchGetMultipleContents("*/*")
return true
}
fun receiveFileCallback(result: Array<Uri>) {
openFileCallback?.onReceiveValue(result)
openFileCallback = null
}
}
WebViewFragment:
class WebViewFragment : Fragment() {
private var _binding: FragmentWebviewBinding? = null
private val binding get() = _binding!!
private lateinit var webView: WebView
private val chromeClient = AppChromeClient(WeakReference(this))
private var contentLauncher: ActivityResultLauncher<String> = getMultipleContentLauncher()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentWebviewBinding.inflate(inflater, container, false)
webView.webChromeClient = chromeClient
val url = requireContext().getString(R.string.app_domain)
webView.setting.javaScriptEnabled = true
webView.loadUrl(url)
return binding.root
}
private fun getMultipleContentLauncher(): ActivityResultLauncher<String> {
return this.registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { list ->
if (list.isEmpty()) {
showToast("No files selected")
}
chromeClient.receiveFileCallback(list.toTypedArray())
}
}
fun launchGetMultipleContents(type: String) {
contentLauncher.launch(type)
}
}
我花了将近一个月的时间研究这个问题。一切都失败了。在多个网站中看到的所有代码都不工作。但这里存在最好的解决方案
https://github.com/chiclaim/android-webview-upload-file
步骤
1)点击克隆或下载
2)在本地目录中获取zip fle
3)解压压缩文件
4)开放Android工作室
5)转到文件---->打开>导航到你解压内容的目录。
6)在webView中更改所需的web url。loadUrl(“您的url hre”);在MainActivity.java
7)适用于Android studio 3.4.2版本
在棒棒糖5.0中,谷歌添加了一个官方方法WebChromeClient.onShowFileChooser。它们甚至提供了一种自动生成文件选择器意图的方法,以便它使用输入接受mime类型。
public class MyWebChromeClient extends WebChromeClient {
// reference to activity instance. May be unnecessary if your web chrome client is member class.
private MyActivity activity;
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
// make sure there is no existing message
if (myActivity.uploadMessage != null) {
myActivity.uploadMessage.onReceiveValue(null);
myActivity.uploadMessage = null;
}
myActivity.uploadMessage = filePathCallback;
Intent intent = fileChooserParams.createIntent();
try {
myActivity.startActivityForResult(intent, MyActivity.REQUEST_SELECT_FILE);
} catch (ActivityNotFoundException e) {
myActivity.uploadMessage = null;
Toast.makeText(myActivity, "Cannot open file chooser", Toast.LENGTH_LONG).show();
return false;
}
return true;
}
}
public class MyActivity extends ... {
public static final int REQUEST_SELECT_FILE = 100;
public ValueCallback<Uri[]> uploadMessage;
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == REQUEST_SELECT_FILE) {
if (uploadMessage == null) return;
uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
uploadMessage = null;
}
}
}
}
对于KitKat之前的Android版本,其他答案中提到的私有方法是有效的。我还没有为KitKat(4.4)找到一个好的解决方案。
我发现我需要3个接口定义,以处理不同版本的android。
public void openFileChooser(ValueCallback < Uri > uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
FreeHealthTrack.this.startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILECHOOSER_RESULTCODE);
}
public void openFileChooser(ValueCallback < Uri > uploadMsg, String acceptType) {
openFileChooser(uploadMsg);
}
public void openFileChooser(ValueCallback < Uri > uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg);
}