WebView加載H5界面無(wú)法調(diào)用手機(jī)本地圖庫(kù)和相機(jī)

Android 的WebView有一個(gè)坑,當(dāng)接入的H5當(dāng)中如果有上傳圖片或者其他文件的時(shí)候,點(diǎn)擊添加按鈕是沒(méi)有任何反應(yīng)的,但是IOS不會(huì)有這個(gè)問(wèn)題

問(wèn)題根因:H5訪問(wèn)本地文件的時(shí)候,使用的是標(biāo)簽<input type="file">,WebView處于安全性的考慮限制了這個(gè)操作,所以H5是無(wú)法直接訪問(wèn)到安卓的本地文件的。

解決辦法:重寫WebviewChromeClient 中的WebviewChromeClient openFileChooser() 和onShowFileChooser()方法響應(yīng)<input type="file">,然后通過(guò)本地代碼調(diào)起圖庫(kù),拍照或者本地文件夾選擇的功能,左后在最后在 onActivityResult 把選擇的圖片 URI 回傳WebviewChromeClient

注意點(diǎn):
1. 在Activity中加載H5
2.Fragment中加載H5

代碼示例:

      var uploadMessage: ValueCallback<Uri?>? = null
      var uploadMessageAboveL: ValueCallback<Array<Uri?>?>? = null

        webView.webChromeClient = object : WebChromeClient() {
            // For Android < 3.0
            fun openFileChooser(valueCallback: ValueCallback<Uri?>?) {
                uploadMessage = valueCallback
     // 自己實(shí)現(xiàn)的打卡圖庫(kù)和調(diào)起攝像頭的方法
                openImageChooserActivity()
            }

            // For Android  >= 3.0
            fun openFileChooser(valueCallback: ValueCallback<*>?, acceptType: String?) {
                uploadMessage = valueCallback as ValueCallback<Uri?>?
     // 自己實(shí)現(xiàn)的打卡圖庫(kù)和調(diào)起攝像頭的方法
                openImageChooserActivity()
            }

            //For Android  >= 4.1
            fun openFileChooser(
                valueCallback: ValueCallback<Uri?>?,
                acceptType: String?,
                capture: String?
            ) {
                uploadMessage = valueCallback
      // 自己實(shí)現(xiàn)的打卡圖庫(kù)和調(diào)起攝像頭的方法
                openImageChooserActivity()
            }

            // For Android >= 5.0
            override fun onShowFileChooser(
                webView: WebView,
                filePathCallback: ValueCallback<Array<Uri?>?>,
                fileChooserParams: FileChooserParams
            ): Boolean {
                uploadMessageAboveL = filePathCallback
         // 自己實(shí)現(xiàn)的打卡圖庫(kù)和調(diào)起攝像頭的方法   
                openImageChooserActivity()
                return true
            }
        }

在Activity中加載H5

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == Activity.RESULT_OK) {
            when (requestCode) {
                CHOOSE_CERTIFICATE_IMAGE_ALBUM_REQUEST_CODE -> { //相簿
                    if (null == uploadMessage && null == uploadMessageAboveL) return
                    val pictures: java.util.ArrayList<PictureInfo>? = data?.getParcelableArrayListExtra<PictureInfo>("pictures")
                    var uri : Uri? = null
                    pictures?.takeIf { pictures.size > 0 }?.let {
                        if(!pictures[0].path.isNullOrEmpty()){
                            uri = Uri.fromFile(File( pictures[0].path))
                        }
                    }
                    if (uploadMessageAboveL != null) {
                        if(uri == null){
                            uploadMessageAboveL?.onReceiveValue(null)
                        }else{
                            uploadMessageAboveL?.onReceiveValue(arrayOf(uri))
                        }
                        uploadMessageAboveL = null
                    } else if (uploadMessage != null) {
                        uploadMessage?.onReceiveValue(uri)
                        uploadMessage = null
                    }

                }

                SetImgUtil.CODE_CAMERA_REQUEST -> { //拍照
                    val file = SetImgUtil.getOutputMediaFile(this, mCameraCacheFileName)
                    val uri = Uri.fromFile(file)
                    if (null == uploadMessage && null == uploadMessageAboveL) return
                    if (uploadMessageAboveL != null) {
                        if(uri == null){
                            uploadMessageAboveL?.onReceiveValue(null)
                        }else{
                            uploadMessageAboveL?.onReceiveValue(arrayOf(uri))
                        }
                        uploadMessageAboveL = null
                    } else if (uploadMessage != null) {
                        uploadMessage?.onReceiveValue(uri)
                        uploadMessage = null
                    }
                }
                else->{
                    //這里uploadMessage跟uploadMessageAboveL在不同系統(tǒng)版本下分別持有了
                    //WebView對(duì)象,在用戶取消文件選擇器的情況下,需給onReceiveValue傳null返回值
                    //否則WebView在未收到返回值的情況下,無(wú)法進(jìn)行任何操作,文件選擇器會(huì)失效
                    if (uploadMessage != null) {
                        uploadMessage?.onReceiveValue(null)
                        uploadMessage = null
                    } else if (uploadMessageAboveL != null) {
                        uploadMessageAboveL?.onReceiveValue(null)
                        uploadMessageAboveL = null
                    }
                }
            }
        }else{
            //這里uploadMessage跟uploadMessageAboveL在不同系統(tǒng)版本下分別持有了
            //WebView對(duì)象,在用戶取消文件選擇器的情況下,需給onReceiveValue傳null返回值
            //否則WebView在未收到返回值的情況下,無(wú)法進(jìn)行任何操作,文件選擇器會(huì)失效
            if (uploadMessage != null) {
                uploadMessage?.onReceiveValue(null)
                uploadMessage = null
            } else if (uploadMessageAboveL != null) {
                uploadMessageAboveL?.onReceiveValue(null)
                uploadMessageAboveL = null
            }
        }
    }

在Fragment中加載H5

在Fragment加載H5需要在Fragment所在的Activity中的onActivityResult中接收數(shù)據(jù),接收到到的數(shù)據(jù)可以通過(guò)廣播或者EventBus等方式傳遞到Fragment,數(shù)據(jù)解析和回傳給H5的方式和上面的onActivityResult中處理方式一樣

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容