Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add android media intents on wildcard input accept #620

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
Expand Down Expand Up @@ -46,6 +48,7 @@

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -72,7 +75,8 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
private static final int PICKER = 1;
private static final int PICKER_LEGACY = 3;
final String DEFAULT_MIME_TYPES = "*/*";
private static Uri outputFileUri;
private static Uri videoOutputFileUri;
private static Uri imageOutputFileUri;

protected static final FrameLayout.LayoutParams FULLSCREEN_LAYOUT_PARAMS = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
Expand Down Expand Up @@ -810,39 +814,37 @@ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
// this filename instead
switch (requestCode) {
case PICKER:
if (resultCode != RESULT_OK) {
if (InAppWebViewFlutterPlugin.filePathCallback != null) {
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(null);
}
} else {
Uri result[] = this.getSelectedFiles(data, resultCode);
if (result != null) {
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(result);
} else {
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(new Uri[]{outputFileUri});
}
Uri[] results = null;
if (resultCode == RESULT_OK) {
results = getSelectedFiles(data, resultCode);
}

if (InAppWebViewFlutterPlugin.filePathCallback != null) {
InAppWebViewFlutterPlugin.filePathCallback.onReceiveValue(results);
}
break;

case PICKER_LEGACY:
Uri result = resultCode != Activity.RESULT_OK ? null : data == null ? outputFileUri : data.getData();
Uri result = null;
if (resultCode == RESULT_OK) {
result = data != null ? data.getData() : getCapturedMediaFile();
}

InAppWebViewFlutterPlugin.filePathCallbackLegacy.onReceiveValue(result);
break;

}

InAppWebViewFlutterPlugin.filePathCallback = null;
InAppWebViewFlutterPlugin.filePathCallbackLegacy = null;
outputFileUri = null;
imageOutputFileUri = null;
videoOutputFileUri = null;

return true;
}

private Uri[] getSelectedFiles(Intent data, int resultCode) {
if (data == null) {
return null;
}

// we have one file selected
if (data.getData() != null) {
if (data != null && data.getData() != null) {
if (resultCode == RESULT_OK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return WebChromeClient.FileChooserParams.parseResult(resultCode, data);
} else {
Expand All @@ -851,14 +853,48 @@ private Uri[] getSelectedFiles(Intent data, int resultCode) {
}

// we have multiple files selected
if (data.getClipData() != null) {
if (data != null && data.getClipData() != null) {
final int numSelectedFiles = data.getClipData().getItemCount();
Uri[] result = new Uri[numSelectedFiles];
for (int i = 0; i < numSelectedFiles; i++) {
result[i] = data.getClipData().getItemAt(i).getUri();
}
return result;
}

// we have a captured image or video file
Uri mediaUri = getCapturedMediaFile();
if (mediaUri != null) {
return new Uri[]{mediaUri};
}

return null;
}

private boolean isFileNotEmpty(Uri uri) {
Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity;

long length;
try {
AssetFileDescriptor descriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
length = descriptor.getLength();
descriptor.close();
} catch (IOException e) {
return false;
}

return length > 0;
}

private Uri getCapturedMediaFile() {
if (imageOutputFileUri != null && isFileNotEmpty(imageOutputFileUri)) {
return imageOutputFileUri;
}

if (videoOutputFileUri != null && isFileNotEmpty(videoOutputFileUri)) {
return videoOutputFileUri;
}

return null;
}

Expand Down Expand Up @@ -935,15 +971,15 @@ protected boolean needsCameraPermission() {

private Intent getPhotoIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
outputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
imageOutputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageOutputFileUri);
return intent;
}

private Intent getVideoIntent() {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
outputFileUri = getOutputUri(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
videoOutputFileUri = getOutputUri(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, videoOutputFileUri);
return intent;
}

Expand Down Expand Up @@ -971,6 +1007,20 @@ private Intent getFileChooserIntent(String[] acceptTypes, boolean allowMultiple)
return intent;
}

private Boolean acceptsAny(String[] types) {
if (isArrayEmpty(types)) {
return true;
}

for (String type : types) {
if (type.equals("*/*")) {
return true;
}
}

return false;
}

private Boolean acceptsImages(String types) {
String mimeType = types;
if (types.matches("\\.\\w+")) {
Expand All @@ -981,7 +1031,7 @@ private Boolean acceptsImages(String types) {

private Boolean acceptsImages(String[] types) {
String[] mimeTypes = getAcceptedMimeType(types);
return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "image");
return acceptsAny(types) || arrayContainsString(mimeTypes, "image");
}

private Boolean acceptsVideo(String types) {
Expand All @@ -994,7 +1044,7 @@ private Boolean acceptsVideo(String types) {

private Boolean acceptsVideo(String[] types) {
String[] mimeTypes = getAcceptedMimeType(types);
return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "video");
return acceptsAny(types) || arrayContainsString(mimeTypes, "video");
}

private Boolean arrayContainsString(String[] array, String pattern) {
Expand Down Expand Up @@ -1056,31 +1106,29 @@ private File getCapturedFile(String intentType) throws IOException {
String prefix = "";
String suffix = "";
String dir = "";
String filename = "";

if (intentType.equals(MediaStore.ACTION_IMAGE_CAPTURE)) {
prefix = "image-";
prefix = "image";
suffix = ".jpg";
dir = Environment.DIRECTORY_PICTURES;
} else if (intentType.equals(MediaStore.ACTION_VIDEO_CAPTURE)) {
prefix = "video-";
prefix = "video";
suffix = ".mp4";
dir = Environment.DIRECTORY_MOVIES;
}

filename = prefix + String.valueOf(System.currentTimeMillis()) + suffix;

// for versions below 6.0 (23) we use the old File creation & permissions model
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// only this Directory works on all tested Android versions
// ctx.getExternalFilesDir(dir) was failing on Android 5.0 (sdk 21)
File storageDir = Environment.getExternalStoragePublicDirectory(dir);
String filename = String.format("%s-%d%s", prefix, System.currentTimeMillis(), suffix);
return new File(storageDir, filename);
}

Activity activity = inAppBrowserActivity != null ? inAppBrowserActivity : Shared.activity;
File storageDir = activity.getApplicationContext().getExternalFilesDir(null);
return File.createTempFile(filename, suffix, storageDir);
return File.createTempFile(prefix, suffix, storageDir);
}

private Boolean isArrayEmpty(String[] arr) {
Expand Down