How can I make the file upload in my app's WebView behave like in the browser app?
I am trying to make a WebView in my Android application allow uploading multiple images taken with the camera.
When I have the HTML code below open in the browser app, I can attach multiple pictures. When I have the same code in my WebView in my app, the button won't even open a dialog.
<form method="post" action="/save/images" name="send" id="send" enctype="multipart/form-data">
<input type="file" name="data[]" id="camera" multiple="">
<input type="submit" name="send">
</form>
Here's a link to the above HTML if you want to try it out: http://codereaper.com/bugspray/so/25251993/html-sendimages/
The point here is the Android application itself have nothing to do with this, the loaded URL contain a webpage made to function in Android's browser application where you can use the camera to upload a bunch of images.
The current state of my attempts consists of giving permissions to the app:
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT"/>
Allowing JavaScript and FileAcess when creating the WebView:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report);
WebView webView = (WebView) findViewById(R.id.report_webview);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setAllowFileAccess(true);
showProgressDialog(R.string.please_wait_title, R.string.please_wait_description);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
closeProgressDialog();
}
}
);
webView.loadUrl("http://codereaper.com/bugspray/so/25251993/html-sendimages/");
}
In my searches I have found a lot of references to use an undocumented feature 'openFileChooser':
new WebChromeClient() {
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
Cv5appActivity.this.startActivityForResult(
Intent.createChooser(i, "Image Browser"),
FILECHOOSER_RESULTCODE);
}
}
I am supporting only newer Android versions (4.3 and above) and would like to do this in supported and documented way, but will use this method if no other method exist. However I do not see how the 'openFileChooser' method will:
Any advice would be appreciated in order to make the WebView act like the browser app on Android or making WebChromeClient able to handle multiple images and "hand them back to the WebView".
Cheers
I did solve all my problems a while back using the other answers on SO that involves the 'openFileChooser' methods. The key piece of information I needed to discover/understand was the ValueCallback<Uri>
which is both the way of handing the selected images back, but also puts the responsibility of handling multiple images to the WebView.
You are handed a ValueCallback<Uri>
while implementing the 'openFileChooser' methods and you are then responsible for calling its callback to hand back with the selected image or null, like:
mUploadMessage.onReceiveValue(null);
Also note that if you do not call the callback, your WebView will stop working right.
UPDATE:
Recently the issue reappeared so now I am using a fork of https://github.com/delight-im/Android-AdvancedWebView - so far it is working beautifully and I didn't have to code it.
add this line to onShowFileChooser
:
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
And this code is for parsing the result (Note that uploadMessages
is a ValueCallback<Uri[]>
):
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
Uri[] results = null;
try {
if (resultCode == RESULT_OK) {
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)};
}
}
} catch (Exception e) {
e.printStackTrace();
}
uploadMessages.onReceiveValue(results);
uploadMessages = null;
}
see also this post...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With