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

Commit

Permalink
[image_picker] Switch Android to internal method channel (#5958)
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartmorgan authored Jun 15, 2022
1 parent 0b29924 commit 95a1f2c
Show file tree
Hide file tree
Showing 5 changed files with 1,545 additions and 2 deletions.
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

0 comments on commit 95a1f2c

Please sign in to comment.