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

[image_picker] getMedia platform implementations #4175

Merged
merged 10 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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
4 changes: 4 additions & 0 deletions packages/image_picker/image_picker_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.8.7

* Adds `getMedia` method.

## 0.8.6+20

* Bumps androidx.activity:activity from 1.7.0 to 1.7.1.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
# org.gradle.parallel=true
#Fri Jan 27 08:52:19 CST 2023
org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1536M"
android.useAndroidX=true
tarrinneal marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public class ImagePickerDelegate
@VisibleForTesting static final int REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA = 2343;
@VisibleForTesting static final int REQUEST_CAMERA_IMAGE_PERMISSION = 2345;
@VisibleForTesting static final int REQUEST_CODE_CHOOSE_MULTI_IMAGE_FROM_GALLERY = 2346;
@VisibleForTesting static final int REQUEST_CODE_CHOOSE_MEDIA_FROM_GALLERY = 2347;

@VisibleForTesting static final int REQUEST_CODE_CHOOSE_VIDEO_FROM_GALLERY = 2352;
@VisibleForTesting static final int REQUEST_CODE_TAKE_VIDEO_WITH_CAMERA = 2353;
Expand Down Expand Up @@ -279,6 +280,52 @@ Messages.CacheRetrievalResult retrieveLostImage() {
return result.build();
}

public void chooseMediaFromGallery(
@NonNull Messages.MediaSelectionOptions options,
@NonNull Messages.GeneralOptions generalOptions,
@NonNull Messages.Result<List<String>> result) {
if (!setPendingOptionsAndResult(options.getImageSelectionOptions(), null, result)) {
finishWithAlreadyActiveError(result);
return;
}

launchPickMediaFromGalleryIntent(generalOptions);
}

private void launchPickMediaFromGalleryIntent(Messages.GeneralOptions generalOptions) {
Intent pickMediaIntent;
if (generalOptions.getUsePhotoPicker() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (generalOptions.getAllowMultiple()) {
pickMediaIntent =
new ActivityResultContracts.PickMultipleVisualMedia()
.createIntent(
activity,
new PickVisualMediaRequest.Builder()
.setMediaType(
ActivityResultContracts.PickVisualMedia.ImageAndVideo.INSTANCE)
.build());
} else {
pickMediaIntent =
new ActivityResultContracts.PickVisualMedia()
.createIntent(
activity,
new PickVisualMediaRequest.Builder()
.setMediaType(
ActivityResultContracts.PickVisualMedia.ImageAndVideo.INSTANCE)
.build());
}
} else {
pickMediaIntent = new Intent(Intent.ACTION_GET_CONTENT);
pickMediaIntent.setType("*/*");
String[] mimeTypes = {"video/*", "image/*"};
pickMediaIntent.putExtra("CONTENT_TYPE", mimeTypes);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
pickMediaIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, generalOptions.getAllowMultiple());
}
}
activity.startActivityForResult(pickMediaIntent, REQUEST_CODE_CHOOSE_MEDIA_FROM_GALLERY);
}

public void chooseVideoFromGallery(
@NonNull VideoSelectionOptions options,
boolean usePhotoPicker,
Expand All @@ -291,9 +338,9 @@ public void chooseVideoFromGallery(
launchPickVideoFromGalleryIntent(usePhotoPicker);
}

private void launchPickVideoFromGalleryIntent(Boolean useAndroidPhotoPicker) {
private void launchPickVideoFromGalleryIntent(Boolean usePhotoPicker) {
Intent pickVideoIntent;
if (useAndroidPhotoPicker && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (usePhotoPicker && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
pickVideoIntent =
new ActivityResultContracts.PickVisualMedia()
.createIntent(
Expand Down Expand Up @@ -389,9 +436,9 @@ public void chooseMultiImageFromGallery(
launchMultiPickImageFromGalleryIntent(usePhotoPicker);
}

private void launchPickImageFromGalleryIntent(Boolean useAndroidPhotoPicker) {
private void launchPickImageFromGalleryIntent(Boolean usePhotoPicker) {
Intent pickImageIntent;
if (useAndroidPhotoPicker && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (usePhotoPicker && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
pickImageIntent =
new ActivityResultContracts.PickVisualMedia()
.createIntent(
Expand All @@ -406,9 +453,9 @@ private void launchPickImageFromGalleryIntent(Boolean useAndroidPhotoPicker) {
activity.startActivityForResult(pickImageIntent, REQUEST_CODE_CHOOSE_IMAGE_FROM_GALLERY);
}

private void launchMultiPickImageFromGalleryIntent(Boolean useAndroidPhotoPicker) {
private void launchMultiPickImageFromGalleryIntent(Boolean usePhotoPicker) {
Intent pickMultiImageIntent;
if (useAndroidPhotoPicker && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (usePhotoPicker && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
pickMultiImageIntent =
new ActivityResultContracts.PickMultipleVisualMedia()
.createIntent(
Expand Down Expand Up @@ -563,6 +610,9 @@ public boolean onActivityResult(
case REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA:
handlerRunnable = () -> handleCaptureImageResult(resultCode);
break;
case REQUEST_CODE_CHOOSE_MEDIA_FROM_GALLERY:
handlerRunnable = () -> handleChooseMediaResult(resultCode, data);
break;
case REQUEST_CODE_CHOOSE_VIDEO_FROM_GALLERY:
handlerRunnable = () -> handleChooseVideoResult(resultCode, data);
break;
Expand All @@ -589,17 +639,59 @@ private void handleChooseImageResult(int resultCode, Intent data) {
finishWithSuccess(null);
}

public class MediaPath {
public MediaPath(@NonNull String path, @Nullable String mimeType) {
this.path = path;
this.mimeType = mimeType;
}

final String path;
final String mimeType;

public @NonNull String getPath() {
return path;
}

public @Nullable String getMimeType() {
return mimeType;
}
}

private void handleChooseMediaResult(int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK && intent != null) {
ArrayList<MediaPath> paths = new ArrayList<>();
if (intent.getClipData() != null) {
for (int i = 0; i < intent.getClipData().getItemCount(); i++) {
Uri uri = intent.getClipData().getItemAt(i).getUri();
String path = fileUtils.getPathFromUri(activity, uri);
String mimeType = activity.getContentResolver().getType(uri);
paths.add(new MediaPath(path, mimeType));
}
} else {
paths.add(new MediaPath(fileUtils.getPathFromUri(activity, intent.getData()), null));
}
handleMediaResult(paths);
return;
}

// User cancelled choosing a picture.
finishWithSuccess(null);
}

private void handleChooseMultiImageResult(int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK && intent != null) {
ArrayList<String> paths = new ArrayList<>();
ArrayList<MediaPath> paths = new ArrayList<>();
if (intent.getClipData() != null) {
for (int i = 0; i < intent.getClipData().getItemCount(); i++) {
paths.add(fileUtils.getPathFromUri(activity, intent.getClipData().getItemAt(i).getUri()));
paths.add(
new MediaPath(
fileUtils.getPathFromUri(activity, intent.getClipData().getItemAt(i).getUri()),
null));
}
} else {
paths.add(fileUtils.getPathFromUri(activity, intent.getData()));
paths.add(new MediaPath(fileUtils.getPathFromUri(activity, intent.getData()), null));
}
handleMultiImageResult(paths);
handleMediaResult(paths);
return;
}

Expand Down Expand Up @@ -649,26 +741,6 @@ private void handleCaptureVideoResult(int resultCode) {
finishWithSuccess(null);
}

private void handleMultiImageResult(ArrayList<String> paths) {
ImageSelectionOptions localImageOptions = null;
synchronized (pendingCallStateLock) {
if (pendingCallState != null) {
localImageOptions = pendingCallState.imageOptions;
}
}

if (localImageOptions != null) {
ArrayList<String> finalPath = new ArrayList<>();
for (int i = 0; i < paths.size(); i++) {
String finalImagePath = getResizedImagePath(paths.get(i), localImageOptions);
finalPath.add(i, finalImagePath);
}
finishWithListSuccess(finalPath);
} else {
finishWithListSuccess(paths);
}
}

void handleImageResult(String path, boolean shouldDeleteOriginalIfScaled) {
ImageSelectionOptions localImageOptions = null;
synchronized (pendingCallStateLock) {
Expand All @@ -679,7 +751,7 @@ void handleImageResult(String path, boolean shouldDeleteOriginalIfScaled) {

if (localImageOptions != null) {
String finalImagePath = getResizedImagePath(path, localImageOptions);
//delete original file if scaled
// Delete original file if scaled.
if (finalImagePath != null && !finalImagePath.equals(path) && shouldDeleteOriginalIfScaled) {
new File(path).delete();
}
Expand All @@ -697,7 +769,34 @@ private String getResizedImagePath(String path, @NonNull ImageSelectionOptions o
outputOptions.getQuality().intValue());
}

void handleVideoResult(String path) {
private void handleMediaResult(@NonNull ArrayList<MediaPath> paths) {
ImageSelectionOptions localImageOptions = null;
synchronized (pendingCallStateLock) {
if (pendingCallState != null) {
localImageOptions = pendingCallState.imageOptions;
}
}

ArrayList<String> finalPaths = new ArrayList<>();
if (localImageOptions != null) {
for (int i = 0; i < paths.size(); i++) {
MediaPath path = paths.get(i);
String finalPath = path.path;
if (path.mimeType == null || !path.mimeType.startsWith("video/")) {
finalPath = getResizedImagePath(path.path, localImageOptions);
}
finalPaths.add(finalPath);
}
finishWithListSuccess(finalPaths);
} else {
for (int i = 0; i < paths.size(); i++) {
finalPaths.add(paths.get(i).path);
}
finishWithListSuccess(finalPaths);
}
}

private void handleVideoResult(String path) {
finishWithSuccess(path);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@
import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.imagepicker.Messages.CacheRetrievalResult;
import io.flutter.plugins.imagepicker.Messages.FlutterError;
import io.flutter.plugins.imagepicker.Messages.GeneralOptions;
import io.flutter.plugins.imagepicker.Messages.ImagePickerApi;
import io.flutter.plugins.imagepicker.Messages.ImageSelectionOptions;
import io.flutter.plugins.imagepicker.Messages.MediaSelectionOptions;
import io.flutter.plugins.imagepicker.Messages.Result;
import io.flutter.plugins.imagepicker.Messages.SourceCamera;
import io.flutter.plugins.imagepicker.Messages.SourceSpecification;
import io.flutter.plugins.imagepicker.Messages.VideoSelectionOptions;
import java.util.List;

@SuppressWarnings("deprecation")
Expand Down Expand Up @@ -279,7 +285,7 @@ final ImagePickerDelegate constructDelegate(final Activity setupActivity) {

private void setCameraDevice(
@NonNull ImagePickerDelegate delegate, @NonNull SourceSpecification source) {
Messages.SourceCamera camera = source.getCamera();
SourceCamera camera = source.getCamera();
if (camera != null) {
ImagePickerDelegate.CameraDevice device;
switch (camera) {
Expand All @@ -298,9 +304,8 @@ private void setCameraDevice(
@Override
public void pickImages(
@NonNull SourceSpecification source,
@NonNull Messages.ImageSelectionOptions options,
@NonNull Boolean allowMultiple,
@NonNull Boolean usePhotoPicker,
@NonNull ImageSelectionOptions options,
@NonNull GeneralOptions generalOptions,
@NonNull Result<List<String>> result) {
ImagePickerDelegate delegate = getImagePickerDelegate();
if (delegate == null) {
Expand All @@ -311,12 +316,12 @@ public void pickImages(
}

setCameraDevice(delegate, source);
if (allowMultiple) {
delegate.chooseMultiImageFromGallery(options, usePhotoPicker, result);
if (generalOptions.getAllowMultiple()) {
delegate.chooseMultiImageFromGallery(options, generalOptions.getUsePhotoPicker(), result);
} else {
switch (source.getType()) {
case GALLERY:
delegate.chooseImageFromGallery(options, usePhotoPicker, result);
delegate.chooseImageFromGallery(options, generalOptions.getUsePhotoPicker(), result);
break;
case CAMERA:
delegate.takeImageWithCamera(options, result);
Expand All @@ -325,12 +330,26 @@ public void pickImages(
}
}

@Override
public void pickMedia(
@NonNull MediaSelectionOptions mediaSelectionOptions,
@NonNull GeneralOptions generalOptions,
@NonNull Result<List<String>> result) {
ImagePickerDelegate delegate = getImagePickerDelegate();
if (delegate == null) {
result.error(
new FlutterError(
"no_activity", "image_picker plugin requires a foreground activity.", null));
return;
}
delegate.chooseMediaFromGallery(mediaSelectionOptions, generalOptions, result);
}

@Override
public void pickVideos(
@NonNull SourceSpecification source,
@NonNull Messages.VideoSelectionOptions options,
@NonNull Boolean allowMultiple,
@NonNull Boolean usePhotoPicker,
@NonNull VideoSelectionOptions options,
@NonNull GeneralOptions generalOptions,
@NonNull Result<List<String>> result) {
ImagePickerDelegate delegate = getImagePickerDelegate();
if (delegate == null) {
Expand All @@ -341,12 +360,12 @@ public void pickVideos(
}

setCameraDevice(delegate, source);
if (allowMultiple) {
if (generalOptions.getAllowMultiple()) {
result.error(new RuntimeException("Multi-video selection is not implemented"));
} else {
switch (source.getType()) {
case GALLERY:
delegate.chooseVideoFromGallery(options, usePhotoPicker, result);
delegate.chooseVideoFromGallery(options, generalOptions.getUsePhotoPicker(), result);
break;
case CAMERA:
delegate.takeVideoWithCamera(options, result);
Expand All @@ -357,7 +376,7 @@ public void pickVideos(

@Nullable
@Override
public Messages.CacheRetrievalResult retrieveLostResults() {
public CacheRetrievalResult retrieveLostResults() {
ImagePickerDelegate delegate = getImagePickerDelegate();
if (delegate == null) {
throw new FlutterError(
Expand Down
Loading