Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[image_picker] Switch Android to internal method channel #5958

Merged
Merged
Show file tree
Hide file tree
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
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.5+1

* Switches to an internal method channel implementation.

## 0.8.5

* Updates gradle to 7.1.2.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ ImagePickerDelegate getDelegate() {
private static final String METHOD_CALL_RETRIEVE = "retrieve";
private static final int CAMERA_DEVICE_FRONT = 1;
private static final int CAMERA_DEVICE_REAR = 0;
private static final String CHANNEL = "plugins.flutter.io/image_picker";
private static final String CHANNEL = "plugins.flutter.io/image_picker_android";

private static final int SOURCE_CAMERA = 0;
private static final int SOURCE_GALLERY = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';

const MethodChannel _channel =
MethodChannel('plugins.flutter.io/image_picker_android');

/// An Android implementation of [ImagePickerPlatform].
class ImagePickerAndroid extends ImagePickerPlatform {
/// The MethodChannel that is being used by this implementation of the plugin.
@visibleForTesting
MethodChannel get channel => _channel;

/// Registers this class as the default platform implementation.
static void registerWith() {
ImagePickerPlatform.instance = ImagePickerAndroid();
}

@override
Future<PickedFile?> pickImage({
required ImageSource source,
double? maxWidth,
double? maxHeight,
int? imageQuality,
CameraDevice preferredCameraDevice = CameraDevice.rear,
}) async {
final String? path = await _getImagePath(
source: source,
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: imageQuality,
preferredCameraDevice: preferredCameraDevice,
);
return path != null ? PickedFile(path) : null;
}

@override
Future<List<PickedFile>?> pickMultiImage({
double? maxWidth,
double? maxHeight,
int? imageQuality,
}) async {
final List<dynamic>? paths = await _getMultiImagePath(
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: imageQuality,
);
if (paths == null) {
return null;
}

return paths.map((dynamic path) => PickedFile(path as String)).toList();
}

Future<List<dynamic>?> _getMultiImagePath({
double? maxWidth,
double? maxHeight,
int? imageQuality,
}) {
if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) {
throw ArgumentError.value(
imageQuality, 'imageQuality', 'must be between 0 and 100');
}

if (maxWidth != null && maxWidth < 0) {
throw ArgumentError.value(maxWidth, 'maxWidth', 'cannot be negative');
}

if (maxHeight != null && maxHeight < 0) {
throw ArgumentError.value(maxHeight, 'maxHeight', 'cannot be negative');
}

return _channel.invokeMethod<List<dynamic>?>(
'pickMultiImage',
<String, dynamic>{
'maxWidth': maxWidth,
'maxHeight': maxHeight,
'imageQuality': imageQuality,
},
);
}

Future<String?> _getImagePath({
required ImageSource source,
double? maxWidth,
double? maxHeight,
int? imageQuality,
CameraDevice preferredCameraDevice = CameraDevice.rear,
bool requestFullMetadata = true,
}) {
if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) {
throw ArgumentError.value(
imageQuality, 'imageQuality', 'must be between 0 and 100');
}

if (maxWidth != null && maxWidth < 0) {
throw ArgumentError.value(maxWidth, 'maxWidth', 'cannot be negative');
}

if (maxHeight != null && maxHeight < 0) {
throw ArgumentError.value(maxHeight, 'maxHeight', 'cannot be negative');
}

return _channel.invokeMethod<String>(
'pickImage',
<String, dynamic>{
'source': source.index,
'maxWidth': maxWidth,
'maxHeight': maxHeight,
'imageQuality': imageQuality,
'cameraDevice': preferredCameraDevice.index,
'requestFullMetadata': requestFullMetadata,
},
);
}

@override
Future<PickedFile?> pickVideo({
required ImageSource source,
CameraDevice preferredCameraDevice = CameraDevice.rear,
Duration? maxDuration,
}) async {
final String? path = await _getVideoPath(
source: source,
maxDuration: maxDuration,
preferredCameraDevice: preferredCameraDevice,
);
return path != null ? PickedFile(path) : null;
}

Future<String?> _getVideoPath({
required ImageSource source,
CameraDevice preferredCameraDevice = CameraDevice.rear,
Duration? maxDuration,
}) {
return _channel.invokeMethod<String>(
'pickVideo',
<String, dynamic>{
'source': source.index,
'maxDuration': maxDuration?.inSeconds,
'cameraDevice': preferredCameraDevice.index
},
);
}

@override
Future<XFile?> getImage({
required ImageSource source,
double? maxWidth,
double? maxHeight,
int? imageQuality,
CameraDevice preferredCameraDevice = CameraDevice.rear,
}) async {
final String? path = await _getImagePath(
source: source,
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: imageQuality,
preferredCameraDevice: preferredCameraDevice,
);
return path != null ? XFile(path) : null;
}

@override
Future<XFile?> getImageFromSource({
required ImageSource source,
ImagePickerOptions options = const ImagePickerOptions(),
}) async {
final String? path = await _getImagePath(
source: source,
maxHeight: options.maxHeight,
maxWidth: options.maxWidth,
imageQuality: options.imageQuality,
preferredCameraDevice: options.preferredCameraDevice,
requestFullMetadata: options.requestFullMetadata,
);
return path != null ? XFile(path) : null;
}

@override
Future<List<XFile>?> getMultiImage({
double? maxWidth,
double? maxHeight,
int? imageQuality,
}) async {
final List<dynamic>? paths = await _getMultiImagePath(
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: imageQuality,
);
if (paths == null) {
return null;
}

return paths.map((dynamic path) => XFile(path as String)).toList();
}

@override
Future<XFile?> getVideo({
required ImageSource source,
CameraDevice preferredCameraDevice = CameraDevice.rear,
Duration? maxDuration,
}) async {
final String? path = await _getVideoPath(
source: source,
maxDuration: maxDuration,
preferredCameraDevice: preferredCameraDevice,
);
return path != null ? XFile(path) : null;
}

@override
Future<LostData> retrieveLostData() async {
final LostDataResponse result = await getLostData();

if (result.isEmpty) {
return LostData.empty();
}

return LostData(
file: result.file != null ? PickedFile(result.file!.path) : null,
exception: result.exception,
type: result.type,
);
}

@override
Future<LostDataResponse> getLostData() async {
List<XFile>? pickedFileList;

final Map<String, dynamic>? result =
await _channel.invokeMapMethod<String, dynamic>('retrieve');

if (result == null) {
return LostDataResponse.empty();
}

assert(result.containsKey('path') != result.containsKey('errorCode'));

final String? type = result['type'] as String?;
assert(type == kTypeImage || type == kTypeVideo);

RetrieveType? retrieveType;
if (type == kTypeImage) {
retrieveType = RetrieveType.image;
} else if (type == kTypeVideo) {
retrieveType = RetrieveType.video;
}

PlatformException? exception;
if (result.containsKey('errorCode')) {
exception = PlatformException(
code: result['errorCode']! as String,
message: result['errorMessage'] as String?);
}

final String? path = result['path'] as String?;

final List<String>? pathList =
(result['pathList'] as List<dynamic>?)?.cast<String>();
if (pathList != null) {
pickedFileList = <XFile>[];
for (final String path in pathList) {
pickedFileList.add(XFile(path));
}
}

return LostDataResponse(
file: path != null ? XFile(path) : null,
exception: exception,
type: retrieveType,
files: pickedFileList,
);
}
}
3 changes: 2 additions & 1 deletion packages/image_picker/image_picker_android/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: image_picker_android
description: Android implementation of the image_picker plugin.
repository: https://github.com/flutter/plugins/tree/main/packages/image_picker/image_picker_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
version: 0.8.5
version: 0.8.5+1

environment:
sdk: ">=2.14.0 <3.0.0"
Expand All @@ -15,6 +15,7 @@ flutter:
android:
package: io.flutter.plugins.imagepicker
pluginClass: ImagePickerPlugin
dartPluginClass: ImagePickerAndroid

dependencies:
flutter:
Expand Down
Loading