3

I have been struggling to upload files from WebView since last few days and there is no progress. I googled and implemented all suggested solutions but none works, like: solutions suggested here, and so on.

formWebView.setWebChromeClient(new WebChromeClient() {
                // openFileChooser for Android 3.0+
                public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType){
                    // Update message
                    mUploadMessage = uploadMsg;
                }
    
                // openFileChooser for Android < 3.0
                public void openFileChooser(ValueCallback<Uri> uploadMsg){
                    openFileChooser(uploadMsg, "");
                }
    
                //openFileChooser for other Android versions
                public void openFileChooser(ValueCallback<Uri> uploadMsg,
                                            String acceptType,
                                            String capture) {
    
                    openFileChooser(uploadMsg, acceptType);
                }
    
                @Override
                public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                    if (uploadMessage != null) {
                        uploadMessage.onReceiveValue(null);
                        uploadMessage = null;
                    }
                    uploadMessage = filePathCallback;
                    try {
                        Intent intent;
                        intent = fileChooserParams.createIntent();
                        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                        intent.setType("*/*");
                        startActivityForResult.launch(intent);
                    } catch (ActivityNotFoundException e) {
                        uploadMessage = null;
                        toast("Cannot Open File Chooser");
                        return false;
                    }
                    return true;
                }
    
                // The webPage has 2 filechoosers and will send a
                // console message informing what action to perform,
                // taking a photo or updating the file
    
                public boolean onConsoleMessage(ConsoleMessage cm) {
                    onConsoleMessage(cm.message(), cm.lineNumber(), cm.sourceId());
                    return true;
                }
    
                public void onConsoleMessage(String message, int lineNumber, String sourceID) {
                    Log.d("androidruntime", "Show console messages, Used for debugging: " + message);
    
                }
            });   // End setWebChromeClient


 ActivityResultLauncher<Intent> startActivityForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
        if (result.getResultCode() == BaseActivity.RESULT_OK) {
            Intent data = result.getData();
            if (data != null) {
                if (uploadMessage == null)
                    return;
                uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));
                uploadMessage = null;
            }
        }
    });

D/androidruntime: Show console messages, Used for debugging: TypeError: Cannot read properties of null (reading '1')
D/androidruntime: Show console messages, Used for debugging: Uncaught TypeError: Cannot read properties of null (reading '1')
D/androidruntime: Show console messages, Used for debugging: [object Object]

I tried this, for some devices file path of .zip, like this - content://media/external/file/353616, the WebView not accept this kind of path. any solution for this?

Thanks in advance.

  • That is a pretty normal content scheme. You will get such a scheme too for non .zip files. Further i see no upload code. And where is it that the webview does not accept that 'path'? – blackapps Feb 11 '22 at 09:43
  • here by using startActivityForResult ,i implemented the "uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));" – Raghul Thavamani Feb 11 '22 at 09:53
  • I added log statement kindly check that. – Raghul Thavamani Feb 11 '22 at 11:05
  • Sorry but i see no upload code and i have no idea what uploadMessage would be. And it is unclear where you call that statement that uses a 'result'.. Also unclear which code would cause for thos log messages. I really cannot follow all. – blackapps Feb 11 '22 at 11:07

1 Answers1

1

After a lot of try I found this answer, working on android 12 also.

Declare this to globally in your activity,

private var mUploadMessage: ValueCallback<Uri>? = null
private var uploadMessage: ValueCallback<Array<Uri>>? = null

Set your WebChrome client like this.

binding.webView.webChromeClient = object : WebChromeClient() {

        fun openFileChooser(uploadMsg: ValueCallback<Uri>, acceptType: String?) {
            mUploadMessage = uploadMsg
            val i = Intent(Intent.ACTION_GET_CONTENT)
            i.addCategory(Intent.CATEGORY_OPENABLE)
            i.type = "*/*"
            startActivityForResult.launch(i)
        }

        // For Lollipop 5.0+ Devices
        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.launch(intent)
            } catch (e: ActivityNotFoundException) {
                uploadMessage = null
                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 = "*/*"
            startActivityForResult.launch(intent)
        }

        protected fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
            mUploadMessage = uploadMsg
            val i = Intent(Intent.ACTION_GET_CONTENT)
            i.addCategory(Intent.CATEGORY_OPENABLE)
            i.type = "*/*"
            startActivityForResult.launch(i)
        }
    }

StartActivityForResult like this,

    var startActivityForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        uploadMessage = if (result.resultCode == RESULT_OK) {
            if (uploadMessage == null)
                return@registerForActivityResult
            uploadMessage!!.onReceiveValue(
                WebChromeClient.FileChooserParams.parseResult(
                    result.resultCode,
                    result.data
                )
            )
            null
        } else {
            uploadMessage!!.onReceiveValue(null)
            null
        }
    }

For reference click here