Solutions for uploading files from Android WebView

Keywords: Android html5

When we develop requirements, we will inevitably access third-party H5 pages. Some H5 pages have the function of uploading photos. WebView in Android can not open the file selection box directly.

Next, I'll give you a brief solution, first of all, I'll talk about ideas.

1. Receive notification that WebView opens the file selector

2. After receiving the notification, open the file selector and wait for the user to select the file to upload.

3. Get the Uri of the file selected by the user in onActivityResult

4. Then pass Uri to Html5

This completes the process of selecting files for H5. Next, I will post the code from the study.

 

First, WebView must support JS interaction, so open JS interaction

mWebView.getSettings().setJavaScriptEnabled(true);

 

When H5 invokes the Api for uploading files, WebView calls back the openFileChooser and onShowFileChooser methods to inform us that all we need to do at this time is to rewrite this method.

It should be noted that this method calls back different row parameter methods on different Api s.

mWebView.setWebChromeClient(new WebChromeClient() {


            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                if (newProgress == 100) {
                    mBar.setVisibility(View.GONE);
                } else {
                    mBar.setVisibility(View.VISIBLE);
                    mBar.setProgress(newProgress);
                }
                super.onProgressChanged(view, newProgress);
            }

            //For Android API < 11 (3.0 OS)
            public void openFileChooser(ValueCallback<Uri> valueCallback) {
                uploadMessage = valueCallback;
                openImageChooserActivity();
            }

            //For Android API >= 11 (3.0 OS)
            public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                uploadMessage = valueCallback;
                openImageChooserActivity();
            }

            //For Android API >= 21 (5.0 OS)
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                uploadMessageAboveL = filePathCallback;
                openImageChooserActivity();
                return true;
            }

        });

 

We first save the callback object of ValueCallback in the openFileChooser method, which is used to notify the H5 file address, and then we call the openFileChooser method to open the file selector.

 private void openImageChooserActivity() {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);
    }

 

When the user has selected the file, the onActivityResult method is called, and we rewrite and wait for the callback.

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILE_CHOOSER_RESULT_CODE) {
            if (null == uploadMessage && null == uploadMessageAboveL) return;
            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
            if (uploadMessageAboveL != null) {
                onActivityResultAboveL(requestCode, resultCode, data);
            } else if (uploadMessage != null) {
                uploadMessage.onReceiveValue(result);
                uploadMessage = null;
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
        if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)
            return;
        Uri[] results = null;
        if (resultCode == Activity.RESULT_OK) {
            if (intent != null) {
                String dataString = intent.getDataString();
                ClipData clipData = intent.getClipData();
                if (clipData != null) {
                    results = new Uri[clipData.getItemCount()];
                    for (int i = 0; i < clipData.getItemCount(); i++) {
                        ClipData.Item item = clipData.getItemAt(i);
                        results[i] = item.getUri();
                    }
                }
                if (dataString != null)
                    results = new Uri[]{Uri.parse(dataString)};
            }
        }
        uploadMessageAboveL.onReceiveValue(results);
        uploadMessageAboveL = null;
    }

 

onActivityResult is used to inform H5 users of the file address they choose. In this method, using the ValueCallback object we saved before and calling the onReceiveValue method, H5 can receive the address information we passed to it.

Posted by Clintonio on Wed, 22 May 2019 13:06:44 -0700