Android Webview 文件和相机上传 - Kotlin
Posted
技术标签:
【中文标题】Android Webview 文件和相机上传 - Kotlin【英文标题】:Android Webview File & Camera Upload - Kotlin 【发布时间】:2020-11-30 19:12:35 【问题描述】:我已经尝试过this 并且还测试了this 代码。如果我需要从文件浏览器上传,两者都可以正常工作,但我需要在文件浏览器或相机之间进行选择。
我可以找到很多 Java 示例来执行此操作,但我找不到使用 Kotlin 完成的工作版本。下面是 webview 文件上传器的my current code:
onActivityResult:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
if(requestCode == REQUEST_SELECT_FILE)
if(uploadMessage != null)
uploadMessage?.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode,data))
uploadMessage = null
else if(requestCode == FILECHOOSER_RESULTCODE)
if(mUploadMessage!=null)
var result = data?.data
mUploadMessage?.onReceiveValue(result)
mUploadMessage = null
else
Toast.makeText(this,"Failed to open file uploader, please check app permissions.",Toast.LENGTH_LONG).show()
super.onActivityResult(requestCode, resultCode, data)
setWebChromeClient:
// For 3.0+ Devices (Start)
// onActivityResult attached before constructor
fun openFileChooser(uploadMsg : ValueCallback<Uri>, acceptType:String)
mUploadMessage = uploadMsg
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "*/*"
startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE)
// For Lollipop 5.0+ Devices
override fun onShowFileChooser(mWebView:WebView, filePathCallback:ValueCallback<Array<Uri>>, fileChooserParams:WebChromeClient.FileChooserParams):Boolean
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
if (uploadMessage != null)
uploadMessage?.onReceiveValue(null)
uploadMessage = null
uploadMessage = filePathCallback
val intent = fileChooserParams.createIntent()
try
startActivityForResult(intent, REQUEST_SELECT_FILE)
catch (e:ActivityNotFoundException)
uploadMessage = null
Toast.makeText(getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show()
return false
return true
else
return false
//For android 4.1 only
fun openFileChooser(uploadMsg:ValueCallback<Uri>, acceptType:String, capture:String)
mUploadMessage = uploadMsg
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE)
fun openFileChooser(uploadMsg:ValueCallback<Uri>)
//filePermission()
mUploadMessage = uploadMsg
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "*/*"
startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE)
是否有人提供允许通过相机或文件浏览器上传的有效代码示例?
此外,文件浏览器在选择存储在设备本身上的图像/pdf 时工作,但通过此方法从 Google Drive 中的文件无法正确上传。有什么想法吗?
【问题讨论】:
【参考方案1】:您可能缺少添加以下代码
webview.getSettings().setDomStorageEnabled(true);
webview.getSettings().setAllowContentAccess(true);
webview.getSettings().setAllowFileAccess(true);
Here我已经详细给出了答案。希望这会帮助你。如果您有任何疑问,请告诉我。
编辑
全局声明以下变量
var requiredPermissions = arrayOf<String>(Permissions.CAMERA, Permissions.WRITE_EXTERNAL_STORAGE, Permissions.READ_EXTERNAL_STORAGE/*, Permissions.WRITE_SETTINGS*/)
val REQUEST_SELECT_FILE = 100
private val FILECHOOSER_RESULTCODE = 1
var uploadMessage: ValueCallback<Array<Uri>>? = null
var link: String? = null
private var mUploadMessage: ValueCallback<*>? = null
Kotlin 代码:
@SuppressLint("SetjavascriptEnabled")
private fun startWebView(url: String)
// Create new webview Client to show progress dialog
// When opening a url or click on link
// Javascript enabled on webview
mWebView.settings.javaScriptEnabled = true
mWebView.settings.builtInZoomControls = true
mWebView.settings.displayZoomControls = true
mWebView.settings.domStorageEnabled = true
mWebView.settings.allowContentAccess = true
mWebView.settings.setAppCacheEnabled(false)
mWebView.settings.cacheMode = WebSettings.LOAD_NO_CACHE
mWebView.settings.setGeolocationEnabled(true) // life saver, do not remove
mWebView.addJavascriptInterface(WebAppInterface(this), "Android")
mWebView.webChromeClient = MyWebChromeClient()
mWebView.webViewClient = object : WebViewClient()
// If you will not use this method url links are open in new browser
// not in webview
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean
view.loadUrl(url)
return true
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
view.loadUrl(request.url.toString())
return true
override fun onReceivedError(view: WebView?, errorCode: Int, description: String?, failingUrl: String?)
super.onReceivedError(view, errorCode, description, failingUrl)
util._log(TAG, "onReceivedError ")
// Show loader on url load
override fun onLoadResource(view: WebView, url: String)
override fun onPageFinished(view: WebView, url: String)
super.onPageFinished(view, url)
progressBar.visibility = View.GONE
override fun onReceivedHttpError(view: WebView?, request: WebResourceRequest?, errorResponse: WebResourceResponse?)
super.onReceivedHttpError(view, request, errorResponse)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
util._log(TAG, "onReceivedHttpError $errorResponse?.statusCode")
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError)
super.onReceivedError(view, request, error)
util._log(TAG, "onReceivedError ")
WebViewClient.ERROR_AUTHENTICATION
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
util._log(TAG, "error code: $error.errorCode " + request.url.toString() + " , " + error.description)
override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError)
super.onReceivedSslError(view, handler, error)
util._log(TAG, "SSl error ")
// Other webview options
/*
* mWebView.getSettings().setLoadWithOverviewMode(true);
* mWebView.getSettings().setUseWideViewPort(true);
* mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
* mWebView.setScrollbarFadingEnabled(false);
* mWebView.getSettings().setBuiltInZoomControls(true);
*/
// Load url in webview
if (NetworkStatus.isOnline(this))
Handler().postDelayed( mWebView.loadUrl(url) , 400)
else
util.showToast(this, getString(R.string.no_internet), true)
internal inner class MyWebChromeClient : WebChromeClient()
// For 3.0+ Devices (Start)
// onActivityResult attached before constructor
protected fun openFileChooser(uploadMsg: ValueCallback<*>, acceptType: String)
mUploadMessage = uploadMsg
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "image/*"
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE)
// For Lollipop 5.0+ Devices
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
override fun onShowFileChooser(mWebView: WebView, filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: FileChooserParams): Boolean
if (uploadMessage != null)
uploadMessage!!.onReceiveValue(null)
uploadMessage = null
uploadMessage = filePathCallback
val intent = fileChooserParams.createIntent()
try
startActivityForResult(intent, REQUEST_SELECT_FILE)
catch (e: Exception)
uploadMessage = null
util.showToast(this@WebLink, "Cannot Open File Chooser")
return false
return true
//For Android 4.1 only
protected fun openFileChooser(uploadMsg: ValueCallback<Uri>, acceptType: String, capture: String)
mUploadMessage = uploadMsg
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "image/*"
startActivityForResult(Intent.createChooser(intent, "File Chooser"), FILECHOOSER_RESULTCODE)
protected fun openFileChooser(uploadMsg: ValueCallback<Uri>)
mUploadMessage = uploadMsg
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "image/*"
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE)
【讨论】:
谢谢你,我在 Java 中为另一个项目做的时候已经看到了。您是否有包含选择相机/文件浏览器选项的 Kotlin 版本? @VegetaZA 我已经添加了 kotlin 代码供您参考。希望它能在一定程度上帮助你。 相机选项没有什么?我最初的问题是上传文件时在文件浏览器或相机之间进行选择的选项。我在原始问题中的代码适用于文件浏览器,只需要知道如何使其也适用于相机。上述代码的唯一问题是它不会从 Google Drive 上传文件,它只适用于保存在设备上的文件。 @VegetaZA 我建议您显示一个弹出窗口,让用户在 onShowFileChooser 中选择相机和画廊之间的选项方法。根据用户输入,使用特定意图从图库中拍照/挑选图像。然后将意图的结果传递给 uploadMessage?.onReceiveValue 方法以上是关于Android Webview 文件和相机上传 - Kotlin的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法让颤动的 webview 使用 android 相机进行文件上传?如何在 webview_flutter 中打开文件选择器?
Android webview调取安卓原生相机和相册上传图片
在Android浏览器中通过WebView调用相机拍照/选择文件 上传到服务器
Android webview上传图片(调起相册/相机上传)