0

I am a learning android developer trying to make my website into a simple App

While i was able to resolve most of my issue with this lovely community I am stuck at one part where input type file is not working any matter what I try. Please advice how to get input type file to work with kotlin

<input type="file">

my code till now is

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val progressBar = findViewById<ProgressBar>(R.id.MyProgress)
    val myWebView: WebView = findViewById(R.id.webview)
    myWebView.settings.javaScriptEnabled = true
    myWebView.settings.setDomStorageEnabled(true)
    myWebView.setWebChromeClient(WebChromeClient())





    myWebView.webViewClient = WebViewClient()
    myWebView.settings.setAppCacheEnabled(true)
    myWebView.settings.setCacheMode(WebSettings.LOAD_DEFAULT)
    myWebView.settings.setAllowFileAccess(true);

    myWebView.settings.getAllowFileAccess();
    myWebView.loadUrl("https://example.com")
    myWebView.setWebViewClient(object : WebViewClient() {
        override fun onReceivedSslError(
            view: WebView,
            handler: SslErrorHandler,
            error: SslError
        ) {
            handler.proceed()
        }






        override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {

            progressBar.visibility = View.VISIBLE
        }

        override fun onPageFinished(view: WebView, url: String) {
            progressBar.visibility = View.INVISIBLE
        }
        override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
            if (Uri.parse(url).host == "example.com") {
                // This is my web site, so do not override; let my WebView load the page
                return false
            }
            // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
            Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
                startActivity(this)
            }
            return true
        }


    })



}


}

<input type="file">

1 Answers1

1

I worked on a project that needed file upload via the WebView. This is how we solved it. Hope it gets you in the right direction. Also note that onActivityResult is deprecated by now and could probably replaced by registerForActivityResult. See this post for more details on that.

MainActivity.kt


companion object {
    /**
     * Request code for onActivityResult for when the user wants to pick an image
     * in the WebFragment
     */
    const val REQUEST_SELECT_FILE_IN_WEB_FRAGMENT = 328
}

/**
 * Used by [WebFragment] to upload photos to
 * the WebView. To do this, we need to catch onActivityResult after the user
 * selected the photo and pass it onto the WebView using this ValueCallback.
 */
private var uploadMessageReceiver: ValueCallback<Array<Uri>>? = null

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

    if (requestCode == REQUEST_SELECT_FILE_IN_WEB_FRAGMENT) {
        // This request was triggered from a webpage in WebFragment to select/upload a picture.
        // tell the uploadMessageReceiver about the selected image data and set it to null again.
        if (uploadMessageReceiver == null) return
        uploadMessageReceiver?.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data))
        uploadMessageReceiver = null
    }
}

// implemenation of the interface defined in WebFragment
override fun getMessageReceiver(): ValueCallback<Array<Uri>>? {
    return uploadMessageReceiver
}

// implemenation of the interface defined in WebFragment
override fun setMessageReceiver(callback: ValueCallback<Array<Uri>>?) {
    uploadMessageReceiver = callback
}

WebFragment.kt


private lateinit var uploadReceiver: UploadMessageReceiver

override fun onAttach(context: Context) {
    super.onAttach(context)
    when (context) {
        is UploadMessageReceiver -> uploadReceiver = context
        else -> throw IllegalArgumentException("Attached context must implement UploadMessageReceiver to allow image uploading in this WebView.")
    }
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {


    with(binding.webView) {
        webViewClient = WebViewClient()
        webChromeClient = BvbWebChromeClient()
        settings.javaScriptEnabled = true
        settings.allowFileAccess = true
        settings.domStorageEnabled = true
        settings.databaseEnabled = true
        settings.setAppCacheEnabled(true)

        if (savedInstanceState == null) {
            loadUrl(arguments.url)
        }
    }
}


/**
 * Let the attached Activity implement this interface to catch the
 * onActivityResult after the user selected an image to upload (see [BvbWebChromeClient])
 */
interface UploadMessageReceiver {
    fun getMessageReceiver(): ValueCallback<Array<Uri>>?
    fun setMessageReceiver(callback: ValueCallback<Array<Uri>>?)
}

/**
 * This WebChromeClient is needed to allow the user to select an image that
 * he/she wants to upload to a web page.
 */
inner class BvbWebChromeClient : WebChromeClient() {

    /**
     * Used by the HTML Feedback form to upload an image.
     * Works tightly with [MainActivity.uploadMessageReceiver]
     */
    override fun onShowFileChooser(webView: WebView, filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: FileChooserParams): Boolean {
        // make sure there is no existing message
        val uploadMessage = uploadReceiver.getMessageReceiver()
        if (uploadMessage != null) {
            uploadMessage.onReceiveValue(null)
            uploadReceiver.setMessageReceiver(null)
        }
        uploadReceiver.setMessageReceiver(filePathCallback)
        val intent = fileChooserParams.createIntent()
        try {
            requireActivity().startActivityForResult(intent, MainActivity.REQUEST_SELECT_FILE_IN_WEB_FRAGMENT)
        } catch (e: ActivityNotFoundException) {
            uploadReceiver.setMessageReceiver(null)
            Toast.makeText(requireActivity(), "Cannot open file chooser", Toast.LENGTH_LONG).show()
            return false
        }
        return true
    }
}
muetzenflo
  • 5,653
  • 4
  • 41
  • 82