I have a hybrid app built using cordova and angularjs, for Android I run the app using crosswalk.
I\'ve been scouring the internet to find the solution for the html5 fi
After weeks of trying to sort this out, I finally got it to work (Cordova without Crosswalk). This was done using Cordova Tools in Windows so please pardon the filespecs below.
Step 1: Change the minSdkVersion in platforms\Android\CordovaLib\AndroidManifest.xml to 21
Explanation: onShowFileChooser
API was introduced in LOLLIPOP (API 21). It allows returning url[]
instead of url
returned by showFileChooser
in earlier API versions. This gets called only when you change the API to 21 or greater.
Step 2: Update/Replace the onActivityResult
method to retrieve multiple files.
Append the following after creating intent using fileChooserParams
to allow choosing multiple files:
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
Location: platforms\android\CordovaLib\src\org\apache\cordova\engine\SystemWebChromeClient.java
Step 3: Update the corresponding onActivityResult
method to return multiple urls using intent.getClipData()
.
Caveats:
Final Code:
Uri photoUri;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, final ValueCallback filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
// Check and use MIME Type.
String mimeType = "*/*";
int ACTION_CODE = FILECHOOSER_RESULTCODE;
try {
if (fileChooserParams.getAcceptTypes().length > 0) {
mimeType = fileChooserParams.getAcceptTypes()[0];
} else {
mimeType = "*/*";
}
} catch (Exception e) {
mimeType = "*/*";
};
// Check if Mutiple is specified
Boolean selectMultiple = false;
if (fileChooserParams.getMode() == WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE) {
selectMultiple = true;
};
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (selectMultiple) { intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); };
intent.setType(mimeType);
ACTION_CODE = FILECHOOSER_RESULTCODE;
final Intent chooserIntent = Intent.createChooser(intent, "Select Source");
// Add camera intent to the chooser if image and send URI to return full image
if (mimeType.equals("image/*")) {
photoUri = null;
try {
File photoFile = createImageFile();
photoUri = Uri.fromFile(photoFile);
}
catch (Exception ex) {
photoUri = null;
}
if (photoUri != null) {
Intent camIntent = new Intent();
camIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
camIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
camIntent.putExtra("return-data", true);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent [] {camIntent} );
}
}
try {
parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK && intent != null) {
if (intent.getData() != null)
{
Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
filePathsCallback.onReceiveValue(result);
}
else
{
if (intent.getClipData() != null) {
final int numSelectedFiles = intent.getClipData().getItemCount();
Uri[] result = new Uri[numSelectedFiles];
for (int i = 0; i < numSelectedFiles; i++) {
result[i] = intent.getClipData().getItemAt(i).getUri();
}
filePathsCallback.onReceiveValue(result);
}
else {
filePathsCallback.onReceiveValue(null);
}
}
}
else if(resultCode == Activity.RESULT_OK && (intent == null || intent.getData() == null )) {
Uri[] result = new Uri[1];
result[0] = photoUri;
filePathsCallback.onReceiveValue(result);
} else {
filePathsCallback.onReceiveValue(null);
}
}
}, chooserIntent, ACTION_CODE);
} catch (ActivityNotFoundException e) {
Log.w("No activity found to handle file chooser intent.", e);
filePathsCallback.onReceiveValue(null);
}
return true;
}