Cara Upload File Di WebView Kotlin

Ini merupakan catatanku setelah beberapa jam mencari cara untuk upload file di Webview menggunakan kotlin akhirnya bisa juga. Kode yang aku share di sini hanya untuk handling pemilihan file saja. Tidak termasuk kodingan untuk upload di sisi server. Untuk kodingan upload file di sisi server mungkin bisa melihat tutorial Cara Upload Gambar Menggunakan Ajax dan PHP.

Permasalahan

Ketika kita menggunakan WebView di sebuah aplikasi android untuk menampilkan form yang di dalamnya terdapat input type file  maka kita tidak bisa memilih file yang akan diupload. Aku tidak tahu apakah itu merupakah bug dari WebView atau memang disengaja dibuat seperti itu dengan alasan keamanan.

Solusi

Kita harus membuat handling khusus menggunakan WebChromeClient() agar Webview yang kita gunakan bisa digunakan untuk memilih file yang akan diupload. Setelah file tersebut dipilih, selanjutnya diparse kedalam WebView lagi melalui onActivityResult() .

Membuat Handling Pemilihan File

Kode di bawah ini digunakan untuk mengahdel pemilihan file pada webview.

//deklarasikan ini sebagai variabel global
var uploadMessage:ValueCallback<Array<Uri>>? = null
private val FILECHOOSER_RESULTCODE = 1
val REQUEST_SELECT_FILE = 100

//setup webChromeClient()
mWebView?.webChromeClient = object:WebChromeClient() {

            override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean {
                Log.d("alert", message)
                val dialogBuilder = AlertDialog.Builder(requireContext())

                dialogBuilder.setMessage(message)
                    .setCancelable(false)
                    .setPositiveButton("OK") { _, _ ->
                        result.confirm()
                    }

                val alert = dialogBuilder.create()
                alert.show()

                return true
            }

            // 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(requireContext(), "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)
            }
        }

Parse Hasil Pemilihan File Kedalam WebView

Kode untuk memarse hasil pemilihan file kedalam Webview adalah sebagai berikut:

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

        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(requireContext(),"Failed to open file uploader, please check app permissions.",Toast.LENGTH_LONG).show()
            super.onActivityResult(requestCode, resultCode, data)
        }


    }

 

Leave a Comment