Android WebView File Upload solution, androidwebview
When we develop our needs, we will inevitably access third-party H5 pages. Some H5 pages have the photo upload function, and the WebView in Android cannot directly open the file selection box.
Next, I will briefly provide a solution, and I will talk about the ideas first.
1. Receive WebView file selector opening notifications
2. After receiving the notification, open the file selector and wait for the user to select the file to be uploaded.
3. Obtain the Uri of the selected file in onActivityResult.
4. then pass the Uri to html5.
In this way, the H5 file selection process is completed. Next I will paste the code and take a look at it.
First, WebView must support JS interaction.
mWebView.getSettings().setJavaScriptEnabled(true);
When H5 calls the File Upload Api, WebView calls back the openFileChooser and onShowFileChooser methods to notify us that we need to rewrite this method at this time.
Note that this method calls back different row parameter methods on different APIs.
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 saved the ValueCallback callback object in the openFileChooser method. This object is used to notify the H5 file address. 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); }
After the file is selected, the onActivityResult method is called. We rewrite the method 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 the file address used to notify H5 users to select. In this method, use the ValueCallback object we saved previously and call the on1_evalue method. H5 will receive the address information we passed to it!