cordova-android
cordova-android copied to clipboard
Android clicking input type=file brings up system file browser, not camera options
Bug Report
Problem
When clicking on an html type="file" input a system file picker appears instead of camera options.
What is expected to happen?
If I perform the same action in the system browser I get the expected dialog:
Version information
"cordova-android": "^8.0.0",
"cordova-plugin-camera": "^4.1.0"
cordova-cli 9.0.0
Full test case repo here
Checklist
- [x] I searched for existing GitHub issues
- [x] I updated all Cordova tooling to most recent version
- [x] I included all the necessary information above
I've added a minimal test case repo here: https://bitbucket.org/alex-crooks/android-file-test/src/master/
@alexcroox
You could use cordova-plugin-camera
's window.navigator.camera.getPicture
to trigger the right options on android. This method will let you choose your destination using https://github.com/apache/cordova-plugin-camera#cameradestinationtype--enum.
Technically add an onClick listener to your tag and handle it yourself by using the above API method, that should resolve your issue.
I guess type="file"
is more generic and hence they handle it by showing a system file picker.
The implementation of openFileChooser
function is very simple and doesn't handle capture:
https://github.com/apache/cordova-android/blob/2163c8ae0536bfde9029cfc981b945f4af93e09f/framework/src/org/apache/cordova/engine/SystemWebChromeClient.java#L235-L249
In XWalk this function got more attention:
https://github.com/crosswalk-project/crosswalk/blob/1b9b80835e83e77390bd6cdbc03beb63f2a6f550/runtime/android/core/src/org/xwalk/core/XWalkFileChooser.java
Unfortunatelly XWalk is not developed anymore so you can either use the last version of XWalk, use the cordova-camera
plugin or try and submit a PR that improves the openFileChooser
function.
I think you can submit a PR if you want to translate the HTML Image element's accept
property into intent type
for the openFileChooser
method.
<input accept="file_extension|audio/*|video/*|image/*|media_type">
I currently have the same problem. Unfortunately, I have no Java / Android skills, so I could extend the function myself.
Is there someone who can extend the function?
I agree that this is a problem. It should be handled according to the W3C recommendations, like the system browser does.
You could use
cordova-plugin-camera
'swindow.navigator.camera.getPicture
to trigger the right options on android. This method will let you choose your destination using https://github.com/apache/cordova-plugin-camera#cameradestinationtype--enum.Technically add an onClick listener to your tag and handle it yourself by using the above API method, that should resolve your issue.
This approach works but has limitations. For example, <input type="file">.files
is a FileList
instance, which does not offer a push
method (like regular Arrays) for good reasons. So, you cannot retrieve a File using the camera plugin and simply append it to <input type="file">.files
using javascript. You have to implement your own form/file handling if you use the camera plugin.
Any update on this?
Hello guys, do you have more updates / insights to fix this problem ? Thanks a lot !
This is half related to this issue, let me know if you want me to open another issue.
I'm using <input type="file">
which open the system file picker.
I then click dropbox, it opens dropbox and I select the file, it downloads it, closes dropbox, returns to the file picker but doesn't return to cordova app.
Has anyone encountered this?
I simply would like to be able to open a file saved in dropbox, nothing fancy...
Any update on this?
If anyone is interested I'm using the following workaround that uses angular/ionic directive: https://github.com/IsraelHikingMap/Site/blob/fe227a44b871f310d4f8c102714dd32bd05a3e9c/IsraelHiking.Web/sources/application/directives/image-capture.directive.ts#L13 It works good for some time in production including all kind of fixes related to picture orientation, status bar issues etc.
Any update?
If some one have any simple solution please share. I can confirm that
cordova-plugin-camera
won't help in my scenario because I need to use dropzone.js with my project the input type file work properly on iOS but android it's not
Any update on this issue? I need to support both browser and hybrid app, so I couldn't use cordova-plugin-camera
any solutions?
what I did (which is still in progress since im learning android Java for this) is to modify the onShowFileChooser() method of "platforms\android\CordovaLib\src\org\apache\cordova\engine\SystemWebChromeClient.java"
add import: import android.provider.MediaStore;
and changed the method to below:
public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
// Check if multiple-select is specified
LOG.d(LOG_TAG, "file chooser opened");
Boolean selectMultiple = false;
if (fileChooserParams.getMode() == WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE) {
selectMultiple = true;
}
String[] acceptTypes = fileChooserParams.getAcceptTypes();
LOG.d(LOG_TAG,"File types: "+ toCSV(acceptTypes));
Intent intent = fileChooserParams.createIntent();
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, selectMultiple);
// Uses Intent.EXTRA_MIME_TYPES to pass multiple mime types.
if (acceptTypes.length > 1) {
intent.setType("*/*"); // Accept all, filter mime types by Intent.EXTRA_MIME_TYPES.
intent.putExtra(Intent.EXTRA_MIME_TYPES, acceptTypes);
}
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Intent GalleryIntent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
try {
Intent chooserIntent;
chooserIntent = Intent.createChooser(intent, "Open file");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{GalleryIntent,cameraIntent, intent});
parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Uri[] result = null;
if (resultCode == Activity.RESULT_OK && intent != null) {
if (intent.getClipData() != null) {
// handle multiple-selected files
final int numSelectedFiles = intent.getClipData().getItemCount();
result = new Uri[numSelectedFiles];
for (int i = 0; i < numSelectedFiles; i++) {
result[i] = intent.getClipData().getItemAt(i).getUri();
LOG.d(LOG_TAG, "Receive file chooser URL: " + result[i]);
}
}
else if (intent.getData() != null) {
// handle single-selected file
result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
LOG.d(LOG_TAG, "Receive file chooser URL: " + result);
}
}
filePathsCallback.onReceiveValue(result);
}
}, chooserIntent, FILECHOOSER_RESULTCODE);
} catch (ActivityNotFoundException e) {
LOG.w("No activity found to handle file chooser intent.", e);
filePathsCallback.onReceiveValue(null);
}
return true;
}
I still need to figure out how to unbundle the gallery options but atleast it works for now
@kortgat can you make a pr about it ?
@kortgat can you make a pr about it ?
Unfortunately i still havent finished it to have a robust workin solution but will try to finish it and make a PR when i have some time
Thanks a lot @kortgat, do you have any idea of the delay about it ?
we use https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Taking_still_photos as workaround
Nice, but my problem is something like this should not have to be worked around, especially if you build pwa, android and ios. Im still learning the android functions in java and figuring out how, to do it in the cordova library so I can at least help others.
@korgat can you review my solution for camera mode when capture flag present on input. I think i try to resolve similar issue. Look at my PR on cordova-plugin-inappbrowser
we use https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Taking_still_photos as workaround
You should also check Capacitor PWA plugins, they directly provide UI components to take a picture, cf https://capacitorjs.com/docs/web/pwa-elements. Btw a native support for camera on these inputs would be absolutely great for many cases
SystemWebChromeClient.zip So I have a working cordova fix to enable camera for all input file fields, someone can refine it and do a PR if they want to but I attatched the file to replace "platforms\android\CordovaLib\src\org\apache\cordova\engine\SystemWebChromeClient.java"
one usefull use case is when generating forms with a tool lik formIO where you dont have control over the generated html it should will also work
@kortgat it didn't work allowing camera only on <input capture="user" type="file" >
or <input capture="environment" type="file">
?
my input is as follows
<input id="fileselect" name="file" type="file" accept="image/*,application/pdf" />
If you don't put a "capture" key, this will even not open the camera on iOS.
Check https://w3c.github.io/html-media-capture/#the-capture-attribute, and input behavior with wkwebview andchrome for android.
Do you need more details to make the pr ?
Whats the status of this issue? I thought input type="file"
behavior would be consistent with web specifications but it seems not.
I agree with a lot of people here saying this is something that we probably shouldn't need a workaround for. @kortgat , with regards to changing the Java file, Is there a way I can make sure this happens after every build or platform add
without having to manually change the file every time? The cordova project I am working on sits in a repo unbuilt so I can't really live with a solution that has me changing outputted files.