【问题标题】:Android Webview File & Camera Upload - KotlinAndroid Webview 文件和相机上传 - 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 中的文件无法正确上传。有什么想法吗?

【问题讨论】:

    标签: android kotlin webview android-camera android-camera-intent


    【解决方案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 方法
    猜你喜欢
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    相关资源
    最近更新 更多