[image_picker] Migrate image_picker to package:cross_file (#4073)

diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index 33178de..fef3e47 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,3 +1,12 @@
+## 0.8.2
+
+* Added new methods that return `package:cross_file` `XFile` instances. [Docs](https://pub.dev/documentation/cross_file/latest/index.html).
+* Deprecate methods that return `PickedFile` instances:
+  * `getImage`: use **`pickImage`** instead.
+  * `getVideo`: use **`pickVideo`** instead.
+  * `getMultiImage`: use **`pickMultiImage`** instead.
+  * `getLostData`: use **`retrieveLostData`** instead.
+
 ## 0.8.1+4
 
 * Fixes an issue where `preferredCameraDevice` option is not working for `getVideo` method.
diff --git a/packages/image_picker/image_picker/README.md b/packages/image_picker/image_picker/README.md
index 3b3746d..18fd96d 100755
--- a/packages/image_picker/image_picker/README.md
+++ b/packages/image_picker/image_picker/README.md
@@ -12,7 +12,7 @@
 ### iOS
 
 Starting with version **0.8.1** the iOS implementation uses PHPicker to pick (multiple) images on iOS 14 or higher.
-As a result of implementing PHPicker it becomes impossible to pick HEIC images on the iOS simulator in iOS 14+. This is a known issue. Please test this on a real device, or test with non-HEIC images until Apple solves this issue.[63426347 - Apple known issue](https://www.google.com/search?q=63426347+apple&sxsrf=ALeKk01YnTMid5S0PYvhL8GbgXJ40ZS[…]t=gws-wiz&ved=0ahUKEwjKh8XH_5HwAhWL_rsIHUmHDN8Q4dUDCA8&uact=5) 
+As a result of implementing PHPicker it becomes impossible to pick HEIC images on the iOS simulator in iOS 14+. This is a known issue. Please test this on a real device, or test with non-HEIC images until Apple solves this issue.[63426347 - Apple known issue](https://www.google.com/search?q=63426347+apple&sxsrf=ALeKk01YnTMid5S0PYvhL8GbgXJ40ZS[…]t=gws-wiz&ved=0ahUKEwjKh8XH_5HwAhWL_rsIHUmHDN8Q4dUDCA8&uact=5)
 
 Add the following keys to your _Info.plist_ file, located in `<project root>/ios/Runner/Info.plist`:
 
@@ -37,7 +37,19 @@
 import 'package:image_picker/image_picker.dart';
 
     ...
-    final PickedFile? pickedFile = await picker.getImage(source: ImageSource.camera);
+    final ImagePicker _picker = ImagePicker();
+    // Pick an image
+    final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
+    // Capture a photo
+    final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
+    // Pick a video
+    final XFile? image = await _picker.pickVideo(source: ImageSource.gallery);
+    // Capture a video
+    final XFile? photo = await _picker.pickVideo(source: ImageSource.camera);
+    // Pick multiple images
+    final List<XFile>? images = await _picker.pickMultiImage(source: ImageSource.gallery);
+    // Pick multiple photos
+    final List<XFile>? photos = await _picker.pickMultiImage(source: ImageSource.camera);
     ...
 ```
 
@@ -46,9 +58,9 @@
 Android system -- although very rarely -- sometimes kills the MainActivity after the image_picker finishes. When this happens, we lost the data selected from the image_picker. You can use `retrieveLostData` to retrieve the lost data in this situation. For example:
 
 ```dart
-Future<void> retrieveLostData() async {
-  final LostData response =
-      await picker.getLostData();
+Future<void> getLostData() async {
+  final LostDataResponse response =
+      await picker.retrieveLostData();
   if (response.isEmpty) {
     return;
   }
@@ -68,65 +80,17 @@
 
 There's no way to detect when this happens, so calling this method at the right place is essential. We recommend to wire this into some kind of start up check. Please refer to the example app to see how we used it.
 
-On Android, `getLostData` will only get the last picked image when picking multiple images, see: [#84634](https://github.com/flutter/flutter/issues/84634).
+On Android, `retrieveLostData` will only get the last picked image when picking multiple images, see: [#84634](https://github.com/flutter/flutter/issues/84634).
 
-## Deprecation warnings in `pickImage`, `pickVideo` and `LostDataResponse`
+## Migrating to 0.8.2+
 
-Starting with version **0.6.7** of the image_picker plugin, the API of the plugin changed slightly to allow for web implementations to exist.
-
-The **old methods that returned `dart:io` File objects were marked as deprecated**, and a new set of methods that return [`PickedFile` objects](https://pub.dev/documentation/image_picker_platform_interface/latest/image_picker_platform_interface/PickedFile-class.html) were introduced.
-
-### How to migrate from to ^0.6.7
-
-#### Instantiate the `ImagePicker`
-
-The new ImagePicker API does not rely in static methods anymore, so the first thing you'll need to do is to create a new instance of the plugin where you need it:
-
-```dart
-final _picker = ImagePicker();
-```
+Starting with version **0.8.2** of the image_picker plugin, new methods have been added for picking files that return `XFile` instances (from the [cross_file](https://pub.dev/packages/cross_file) package) rather than the plugin's own `PickedFile` instances. While the previous methods still exist, it is already recommended to start migrating over to their new equivalents. Eventually, `PickedFile` and the methods that return instances of it will be deprecated and removed.
 
 #### Call the new methods
 
-The new methods **receive the same parameters as before**, but they **return a `PickedFile`, instead of a `File`**. The `LostDataResponse` class has been replaced by the [`LostData` class](https://pub.dev/documentation/image_picker_platform_interface/latest/image_picker_platform_interface/LostData-class.html).
-
 | Old API | New API |
 |---------|---------|
-| `File image = await ImagePicker.pickImage(...)` | `PickedFile image = await _picker.getImage(...)` |
-| `File video = await ImagePicker.pickVideo(...)` | `PickedFile video = await _picker.getVideo(...)` |
-| `LostDataResponse response = await ImagePicker.retrieveLostData()` | `LostData response = await _picker.getLostData()` |
-
-#### `PickedFile` to `File`
-
-If your app needs dart:io `File` objects to operate, you may transform `PickedFile` to `File` like so:
-
-```dart
-final pickedFile = await _picker.getImage(...);
-final File file = File(pickedFile.path);
-```
-
-You may also retrieve the bytes from the pickedFile directly if needed:
-
-```dart
-final bytes = await pickedFile.readAsBytes();
-```
-
-#### Getting ready for the web platform
-
-Note that on the web platform (`kIsWeb == true`), `File` is not available, so the `path` of the `PickedFile` will point to a network resource instead:
-
-```dart
-if (kIsWeb) {
-  image = Image.network(pickedFile.path);
-} else {
-  image = Image.file(File(pickedFile.path));
-}
-```
-
-Alternatively, the code may be unified at the expense of memory utilization:
-
-```dart
-image = Image.memory(await pickedFile.readAsBytes())
-```
-
-Take a look at the changes to the `example` app introduced in version 0.6.7 to see the migration steps applied there.
+| `PickedFile image = await _picker.getImage(...)` | `XFile image = await _picker.pickImage(...)` |
+| `List<PickedFile> images = await _picker.getMultiImage(...)` | `List<XFile> images = await _picker.pickMultiImage(...)` |
+| `PickedFile video = await _picker.getVideo(...)` | `XFile video = await _picker.pickVideo(...)` |
+| `LostData response = await _picker.getLostData()` | `LostDataResponse response = await _picker.retrieveLostData()` |
\ No newline at end of file
diff --git a/packages/image_picker/image_picker/example/lib/main.dart b/packages/image_picker/image_picker/example/lib/main.dart
index 71388ef..2d5fd9a 100755
--- a/packages/image_picker/image_picker/example/lib/main.dart
+++ b/packages/image_picker/image_picker/example/lib/main.dart
@@ -36,9 +36,9 @@
 }
 
 class _MyHomePageState extends State<MyHomePage> {
-  List<PickedFile>? _imageFileList;
+  List<XFile>? _imageFileList;
 
-  set _imageFile(PickedFile? value) {
+  set _imageFile(XFile? value) {
     _imageFileList = value == null ? null : [value];
   }
 
@@ -54,7 +54,7 @@
   final TextEditingController maxHeightController = TextEditingController();
   final TextEditingController qualityController = TextEditingController();
 
-  Future<void> _playVideo(PickedFile? file) async {
+  Future<void> _playVideo(XFile? file) async {
     if (file != null && mounted) {
       await _disposeVideoController();
       late VideoPlayerController controller;
@@ -84,14 +84,14 @@
       await _controller!.setVolume(0.0);
     }
     if (isVideo) {
-      final PickedFile? file = await _picker.getVideo(
+      final XFile? file = await _picker.pickVideo(
           source: source, maxDuration: const Duration(seconds: 10));
       await _playVideo(file);
     } else if (isMultiImage) {
       await _displayPickImageDialog(context!,
           (double? maxWidth, double? maxHeight, int? quality) async {
         try {
-          final pickedFileList = await _picker.getMultiImage(
+          final pickedFileList = await _picker.pickMultiImage(
             maxWidth: maxWidth,
             maxHeight: maxHeight,
             imageQuality: quality,
@@ -109,7 +109,7 @@
       await _displayPickImageDialog(context!,
           (double? maxWidth, double? maxHeight, int? quality) async {
         try {
-          final pickedFile = await _picker.getImage(
+          final pickedFile = await _picker.pickImage(
             source: source,
             maxWidth: maxWidth,
             maxHeight: maxHeight,
@@ -214,7 +214,7 @@
   }
 
   Future<void> retrieveLostData() async {
-    final LostData response = await _picker.getLostData();
+    final LostDataResponse response = await _picker.retrieveLostData();
     if (response.isEmpty) {
       return;
     }
diff --git a/packages/image_picker/image_picker/lib/image_picker.dart b/packages/image_picker/image_picker/lib/image_picker.dart
index 3d08a38..5bc99d7 100755
--- a/packages/image_picker/image_picker/lib/image_picker.dart
+++ b/packages/image_picker/image_picker/lib/image_picker.dart
@@ -2,12 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// ignore_for_file: deprecated_member_use, deprecated_member_use_from_same_package
-
 import 'dart:async';
-
 import 'package:flutter/foundation.dart';
-
 import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
 
 export 'package:image_picker_platform_interface/image_picker_platform_interface.dart'
@@ -17,7 +13,9 @@
         ImageSource,
         CameraDevice,
         LostData,
+        LostDataResponse,
         PickedFile,
+        XFile,
         RetrieveType;
 
 /// Provides an easy way to pick an image/video from the image library,
@@ -61,6 +59,7 @@
   /// the camera or photos gallery, no camera is available, plugin is already in use,
   /// temporary file could not be created (iOS only), plugin activity could not
   /// be allocated (Android only) or due to an unknown error.
+  @Deprecated('Switch to using pickImage instead')
   Future<PickedFile?> getImage({
     required ImageSource source,
     double? maxWidth,
@@ -101,6 +100,7 @@
   /// be allocated (Android only) or due to an unknown error.
   ///
   /// See also [getImage] to allow users to only pick a single image.
+  @Deprecated('Switch to using pickMultiImage instead')
   Future<List<PickedFile>?> getMultiImage({
     double? maxWidth,
     double? maxHeight,
@@ -135,6 +135,7 @@
   /// temporary file could not be created and video could not be cached (iOS only),
   /// plugin activity could not be allocated (Android only) or due to an unknown error.
   ///
+  @Deprecated('Switch to using pickVideo instead')
   Future<PickedFile?> getVideo({
     required ImageSource source,
     CameraDevice preferredCameraDevice = CameraDevice.rear,
@@ -160,7 +161,146 @@
   /// See also:
   /// * [LostData], for what's included in the response.
   /// * [Android Activity Lifecycle](https://developer.android.com/reference/android/app/Activity.html), for more information on MainActivity destruction.
+  @Deprecated('Switch to using retrieveLostData instead')
   Future<LostData> getLostData() {
     return platform.retrieveLostData();
   }
+
+  /// Returns an [XFile] object wrapping the image that was picked.
+  ///
+  /// The returned [XFile] is intended to be used within a single APP session. Do not save the file path and use it across sessions.
+  ///
+  /// The `source` argument controls where the image comes from. This can
+  /// be either [ImageSource.camera] or [ImageSource.gallery].
+  ///
+  /// Where iOS supports HEIC images, Android 8 and below doesn't. Android 9 and above only support HEIC images if used
+  /// in addition to a size modification, of which the usage is explained below.
+  ///
+  /// If specified, the image will be at most `maxWidth` wide and
+  /// `maxHeight` tall. Otherwise the image will be returned at it's
+  /// original width and height.
+  /// The `imageQuality` argument modifies the quality of the image, ranging from 0-100
+  /// where 100 is the original/max quality. If `imageQuality` is null, the image with
+  /// the original quality will be returned. Compression is only supported for certain
+  /// image types such as JPEG and on Android PNG and WebP, too. If compression is not supported for the image that is picked,
+  /// a warning message will be logged.
+  ///
+  /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera].
+  /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device.
+  /// Defaults to [CameraDevice.rear]. Note that Android has no documented parameter for an intent to specify if
+  /// the front or rear camera should be opened, this function is not guaranteed
+  /// to work on an Android device.
+  ///
+  /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost
+  /// in this call. You can then call [retrieveLostData] when your app relaunches to retrieve the lost data.
+  ///
+  /// See also [pickMultiImage] to allow users to select multiple images at once.
+  ///
+  /// The method could throw [PlatformException] if the app does not have permission to access
+  /// the camera or photos gallery, no camera is available, plugin is already in use,
+  /// temporary file could not be created (iOS only), plugin activity could not
+  /// be allocated (Android only) or due to an unknown error.
+  Future<XFile?> pickImage({
+    required ImageSource source,
+    double? maxWidth,
+    double? maxHeight,
+    int? imageQuality,
+    CameraDevice preferredCameraDevice = CameraDevice.rear,
+  }) {
+    return platform.getImage(
+      source: source,
+      maxWidth: maxWidth,
+      maxHeight: maxHeight,
+      imageQuality: imageQuality,
+      preferredCameraDevice: preferredCameraDevice,
+    );
+  }
+
+  /// Returns a [List<XFile>] object wrapping the images that were picked.
+  ///
+  /// The returned [List<XFile>] is intended to be used within a single APP session. Do not save the file path and use it across sessions.
+  ///
+  /// Where iOS supports HEIC images, Android 8 and below doesn't. Android 9 and above only support HEIC images if used
+  /// in addition to a size modification, of which the usage is explained below.
+  ///
+  /// This method is not supported in iOS versions lower than 14.
+  ///
+  /// If specified, the images will be at most `maxWidth` wide and
+  /// `maxHeight` tall. Otherwise the images will be returned at it's
+  /// original width and height.
+  /// The `imageQuality` argument modifies the quality of the images, ranging from 0-100
+  /// where 100 is the original/max quality. If `imageQuality` is null, the images with
+  /// the original quality will be returned. Compression is only supported for certain
+  /// image types such as JPEG and on Android PNG and WebP, too. If compression is not supported for the image that is picked,
+  /// a warning message will be logged.
+  ///
+  /// The method could throw [PlatformException] if the app does not have permission to access
+  /// the camera or photos gallery, no camera is available, plugin is already in use,
+  /// temporary file could not be created (iOS only), plugin activity could not
+  /// be allocated (Android only) or due to an unknown error.
+  ///
+  /// See also [pickImage] to allow users to only pick a single image.
+  Future<List<XFile>?> pickMultiImage({
+    double? maxWidth,
+    double? maxHeight,
+    int? imageQuality,
+  }) {
+    return platform.getMultiImage(
+      maxWidth: maxWidth,
+      maxHeight: maxHeight,
+      imageQuality: imageQuality,
+    );
+  }
+
+  /// Returns an [XFile] object wrapping the video that was picked.
+  ///
+  /// The returned [XFile] is intended to be used within a single APP session. Do not save the file path and use it across sessions.
+  ///
+  /// The [source] argument controls where the video comes from. This can
+  /// be either [ImageSource.camera] or [ImageSource.gallery].
+  ///
+  /// The [maxDuration] argument specifies the maximum duration of the captured video. If no [maxDuration] is specified,
+  /// the maximum duration will be infinite.
+  ///
+  /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera].
+  /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device.
+  /// Defaults to [CameraDevice.rear].
+  ///
+  /// In Android, the MainActivity can be destroyed for various fo reasons. If that happens, the result will be lost
+  /// in this call. You can then call [retrieveLostData] when your app relaunches to retrieve the lost data.
+  ///
+  /// The method could throw [PlatformException] if the app does not have permission to access
+  /// the camera or photos gallery, no camera is available, plugin is already in use,
+  /// temporary file could not be created and video could not be cached (iOS only),
+  /// plugin activity could not be allocated (Android only) or due to an unknown error.
+  ///
+  Future<XFile?> pickVideo({
+    required ImageSource source,
+    CameraDevice preferredCameraDevice = CameraDevice.rear,
+    Duration? maxDuration,
+  }) {
+    return platform.getVideo(
+      source: source,
+      preferredCameraDevice: preferredCameraDevice,
+      maxDuration: maxDuration,
+    );
+  }
+
+  /// Retrieve the lost [XFile] when [pickImage], [pickMultiImage] or [pickVideo] failed because the MainActivity
+  /// is destroyed. (Android only)
+  ///
+  /// Image or video can be lost if the MainActivity is destroyed. And there is no guarantee that the MainActivity is always alive.
+  /// Call this method to retrieve the lost data and process the data according to your APP's business logic.
+  ///
+  /// Returns a [LostDataResponse] object if successfully retrieved the lost data. The [LostDataResponse] object can \
+  /// represent either a successful image/video selection, or a failure.
+  ///
+  /// Calling this on a non-Android platform will throw [UnimplementedError] exception.
+  ///
+  /// See also:
+  /// * [LostDataResponse], for what's included in the response.
+  /// * [Android Activity Lifecycle](https://developer.android.com/reference/android/app/Activity.html), for more information on MainActivity destruction.
+  Future<LostDataResponse> retrieveLostData() {
+    return platform.getLostData();
+  }
 }
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index c9866db..e5ecfeb 100755
--- a/packages/image_picker/image_picker/pubspec.yaml
+++ b/packages/image_picker/image_picker/pubspec.yaml
@@ -3,7 +3,7 @@
   library, and taking new pictures with the camera.
 repository: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
-version: 0.8.1+4
+version: 0.8.2
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
@@ -24,8 +24,8 @@
   flutter:
     sdk: flutter
   flutter_plugin_android_lifecycle: ^2.0.1
-  image_picker_for_web: ^2.0.0
-  image_picker_platform_interface: ^2.1.0
+  image_picker_for_web: ^2.1.0
+  image_picker_platform_interface: ^2.2.0
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart
new file mode 100644
index 0000000..f295e3d
--- /dev/null
+++ b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart
@@ -0,0 +1,458 @@
+// 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.
+
+// ignore_for_file: deprecated_member_use_from_same_package
+
+// This file preserves the tests for the deprecated methods as they were before
+// the migration. See image_picker_test.dart for the current tests.
+
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
+import 'package:mockito/mockito.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
+
+void main() {
+  TestWidgetsFlutterBinding.ensureInitialized();
+
+  group('$ImagePicker', () {
+    const MethodChannel channel =
+        MethodChannel('plugins.flutter.io/image_picker');
+
+    final List<MethodCall> log = <MethodCall>[];
+
+    final picker = ImagePicker();
+
+    test('ImagePicker platform instance overrides the actual platform used',
+        () {
+      final ImagePickerPlatform savedPlatform = ImagePickerPlatform.instance;
+      final MockPlatform mockPlatform = MockPlatform();
+      ImagePickerPlatform.instance = mockPlatform;
+      expect(ImagePicker.platform, mockPlatform);
+      ImagePickerPlatform.instance = savedPlatform;
+    });
+
+    group('#Single image/video', () {
+      setUp(() {
+        channel.setMockMethodCallHandler((MethodCall methodCall) async {
+          log.add(methodCall);
+          return '';
+        });
+
+        log.clear();
+      });
+
+      group('#pickImage', () {
+        test('passes the image source argument correctly', () async {
+          await picker.getImage(source: ImageSource.camera);
+          await picker.getImage(source: ImageSource.gallery);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': null,
+                'maxHeight': null,
+                'imageQuality': null,
+                'cameraDevice': 0
+              }),
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 1,
+                'maxWidth': null,
+                'maxHeight': null,
+                'imageQuality': null,
+                'cameraDevice': 0
+              }),
+            ],
+          );
+        });
+
+        test('passes the width and height arguments correctly', () async {
+          await picker.getImage(source: ImageSource.camera);
+          await picker.getImage(
+            source: ImageSource.camera,
+            maxWidth: 10.0,
+          );
+          await picker.getImage(
+            source: ImageSource.camera,
+            maxHeight: 10.0,
+          );
+          await picker.getImage(
+            source: ImageSource.camera,
+            maxWidth: 10.0,
+            maxHeight: 20.0,
+          );
+          await picker.getImage(
+              source: ImageSource.camera, maxWidth: 10.0, imageQuality: 70);
+          await picker.getImage(
+              source: ImageSource.camera, maxHeight: 10.0, imageQuality: 70);
+          await picker.getImage(
+              source: ImageSource.camera,
+              maxWidth: 10.0,
+              maxHeight: 20.0,
+              imageQuality: 70);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': null,
+                'maxHeight': null,
+                'imageQuality': null,
+                'cameraDevice': 0
+              }),
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': 10.0,
+                'maxHeight': null,
+                'imageQuality': null,
+                'cameraDevice': 0
+              }),
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': null,
+                'maxHeight': 10.0,
+                'imageQuality': null,
+                'cameraDevice': 0
+              }),
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': 10.0,
+                'maxHeight': 20.0,
+                'imageQuality': null,
+                'cameraDevice': 0
+              }),
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': 10.0,
+                'maxHeight': null,
+                'imageQuality': 70,
+                'cameraDevice': 0
+              }),
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': null,
+                'maxHeight': 10.0,
+                'imageQuality': 70,
+                'cameraDevice': 0
+              }),
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': 10.0,
+                'maxHeight': 20.0,
+                'imageQuality': 70,
+                'cameraDevice': 0
+              }),
+            ],
+          );
+        });
+
+        test('does not accept a negative width or height argument', () {
+          expect(
+            picker.getImage(source: ImageSource.camera, maxWidth: -1.0),
+            throwsArgumentError,
+          );
+
+          expect(
+            picker.getImage(source: ImageSource.camera, maxHeight: -1.0),
+            throwsArgumentError,
+          );
+        });
+
+        test('handles a null image path response gracefully', () async {
+          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+
+          expect(await picker.getImage(source: ImageSource.gallery), isNull);
+          expect(await picker.getImage(source: ImageSource.camera), isNull);
+        });
+
+        test('camera position defaults to back', () async {
+          await picker.getImage(source: ImageSource.camera);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': null,
+                'maxHeight': null,
+                'imageQuality': null,
+                'cameraDevice': 0,
+              }),
+            ],
+          );
+        });
+
+        test('camera position can set to front', () async {
+          await picker.getImage(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.front);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickImage', arguments: <String, dynamic>{
+                'source': 0,
+                'maxWidth': null,
+                'maxHeight': null,
+                'imageQuality': null,
+                'cameraDevice': 1,
+              }),
+            ],
+          );
+        });
+      });
+
+      group('#pickVideo', () {
+        test('passes the image source argument correctly', () async {
+          await picker.getVideo(source: ImageSource.camera);
+          await picker.getVideo(source: ImageSource.gallery);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 0,
+                'cameraDevice': 0,
+                'maxDuration': null,
+              }),
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 1,
+                'cameraDevice': 0,
+                'maxDuration': null,
+              }),
+            ],
+          );
+        });
+
+        test('passes the duration argument correctly', () async {
+          await picker.getVideo(source: ImageSource.camera);
+          await picker.getVideo(
+              source: ImageSource.camera,
+              maxDuration: const Duration(seconds: 10));
+          await picker.getVideo(
+              source: ImageSource.camera,
+              maxDuration: const Duration(minutes: 1));
+          await picker.getVideo(
+              source: ImageSource.camera,
+              maxDuration: const Duration(hours: 1));
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 0,
+                'maxDuration': null,
+                'cameraDevice': 0,
+              }),
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 0,
+                'maxDuration': 10,
+                'cameraDevice': 0,
+              }),
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 0,
+                'maxDuration': 60,
+                'cameraDevice': 0,
+              }),
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 0,
+                'maxDuration': 3600,
+                'cameraDevice': 0,
+              }),
+            ],
+          );
+        });
+
+        test('handles a null video path response gracefully', () async {
+          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+
+          expect(await picker.getVideo(source: ImageSource.gallery), isNull);
+          expect(await picker.getVideo(source: ImageSource.camera), isNull);
+        });
+
+        test('camera position defaults to back', () async {
+          await picker.getVideo(source: ImageSource.camera);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 0,
+                'cameraDevice': 0,
+                'maxDuration': null,
+              }),
+            ],
+          );
+        });
+
+        test('camera position can set to front', () async {
+          await picker.getVideo(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.front);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickVideo', arguments: <String, dynamic>{
+                'source': 0,
+                'maxDuration': null,
+                'cameraDevice': 1,
+              }),
+            ],
+          );
+        });
+      });
+
+      group('#retrieveLostData', () {
+        test('retrieveLostData get success response', () async {
+          channel.setMockMethodCallHandler((MethodCall methodCall) async {
+            return <String, String>{
+              'type': 'image',
+              'path': '/example/path',
+            };
+          });
+          final LostData response = await picker.getLostData();
+          expect(response.type, RetrieveType.image);
+          expect(response.file!.path, '/example/path');
+        });
+
+        test('retrieveLostData get error response', () async {
+          channel.setMockMethodCallHandler((MethodCall methodCall) async {
+            return <String, String>{
+              'type': 'video',
+              'errorCode': 'test_error_code',
+              'errorMessage': 'test_error_message',
+            };
+          });
+          final LostData response = await picker.getLostData();
+          expect(response.type, RetrieveType.video);
+          expect(response.exception!.code, 'test_error_code');
+          expect(response.exception!.message, 'test_error_message');
+        });
+
+        test('retrieveLostData get null response', () async {
+          channel.setMockMethodCallHandler((MethodCall methodCall) async {
+            return null;
+          });
+          expect((await picker.getLostData()).isEmpty, true);
+        });
+
+        test('retrieveLostData get both path and error should throw', () async {
+          channel.setMockMethodCallHandler((MethodCall methodCall) async {
+            return <String, String>{
+              'type': 'video',
+              'errorCode': 'test_error_code',
+              'errorMessage': 'test_error_message',
+              'path': '/example/path',
+            };
+          });
+          expect(picker.getLostData(), throwsAssertionError);
+        });
+      });
+    });
+
+    group('Multi images', () {
+      setUp(() {
+        channel.setMockMethodCallHandler((MethodCall methodCall) async {
+          log.add(methodCall);
+          return [];
+        });
+        log.clear();
+      });
+
+      group('#pickMultiImage', () {
+        test('passes the width and height arguments correctly', () async {
+          await picker.getMultiImage();
+          await picker.getMultiImage(
+            maxWidth: 10.0,
+          );
+          await picker.getMultiImage(
+            maxHeight: 10.0,
+          );
+          await picker.getMultiImage(
+            maxWidth: 10.0,
+            maxHeight: 20.0,
+          );
+          await picker.getMultiImage(
+            maxWidth: 10.0,
+            imageQuality: 70,
+          );
+          await picker.getMultiImage(
+            maxHeight: 10.0,
+            imageQuality: 70,
+          );
+          await picker.getMultiImage(
+              maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70);
+
+          expect(
+            log,
+            <Matcher>[
+              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
+                'maxWidth': null,
+                'maxHeight': null,
+                'imageQuality': null,
+              }),
+              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
+                'maxWidth': 10.0,
+                'maxHeight': null,
+                'imageQuality': null,
+              }),
+              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
+                'maxWidth': null,
+                'maxHeight': 10.0,
+                'imageQuality': null,
+              }),
+              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
+                'maxWidth': 10.0,
+                'maxHeight': 20.0,
+                'imageQuality': null,
+              }),
+              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
+                'maxWidth': 10.0,
+                'maxHeight': null,
+                'imageQuality': 70,
+              }),
+              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
+                'maxWidth': null,
+                'maxHeight': 10.0,
+                'imageQuality': 70,
+              }),
+              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
+                'maxWidth': 10.0,
+                'maxHeight': 20.0,
+                'imageQuality': 70,
+              }),
+            ],
+          );
+        });
+
+        test('does not accept a negative width or height argument', () {
+          expect(
+            picker.getMultiImage(maxWidth: -1.0),
+            throwsArgumentError,
+          );
+
+          expect(
+            picker.getMultiImage(maxHeight: -1.0),
+            throwsArgumentError,
+          );
+        });
+
+        test('handles a null image path response gracefully', () async {
+          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+
+          expect(await picker.getMultiImage(), isNull);
+          expect(await picker.getMultiImage(), isNull);
+        });
+      });
+    });
+  });
+}
+
+class MockPlatform extends Mock
+    with MockPlatformInterfaceMixin
+    implements ImagePickerPlatform {}
diff --git a/packages/image_picker/image_picker/test/image_picker_test.dart b/packages/image_picker/image_picker/test/image_picker_test.dart
index d83b403..960dfe6 100644
--- a/packages/image_picker/image_picker/test/image_picker_test.dart
+++ b/packages/image_picker/image_picker/test/image_picker_test.dart
@@ -41,8 +41,8 @@
 
       group('#pickImage', () {
         test('passes the image source argument correctly', () async {
-          await picker.getImage(source: ImageSource.camera);
-          await picker.getImage(source: ImageSource.gallery);
+          await picker.pickImage(source: ImageSource.camera);
+          await picker.pickImage(source: ImageSource.gallery);
 
           expect(
             log,
@@ -66,25 +66,25 @@
         });
 
         test('passes the width and height arguments correctly', () async {
-          await picker.getImage(source: ImageSource.camera);
-          await picker.getImage(
+          await picker.pickImage(source: ImageSource.camera);
+          await picker.pickImage(
             source: ImageSource.camera,
             maxWidth: 10.0,
           );
-          await picker.getImage(
+          await picker.pickImage(
             source: ImageSource.camera,
             maxHeight: 10.0,
           );
-          await picker.getImage(
+          await picker.pickImage(
             source: ImageSource.camera,
             maxWidth: 10.0,
             maxHeight: 20.0,
           );
-          await picker.getImage(
+          await picker.pickImage(
               source: ImageSource.camera, maxWidth: 10.0, imageQuality: 70);
-          await picker.getImage(
+          await picker.pickImage(
               source: ImageSource.camera, maxHeight: 10.0, imageQuality: 70);
-          await picker.getImage(
+          await picker.pickImage(
               source: ImageSource.camera,
               maxWidth: 10.0,
               maxHeight: 20.0,
@@ -148,12 +148,12 @@
 
         test('does not accept a negative width or height argument', () {
           expect(
-            picker.getImage(source: ImageSource.camera, maxWidth: -1.0),
+            picker.pickImage(source: ImageSource.camera, maxWidth: -1.0),
             throwsArgumentError,
           );
 
           expect(
-            picker.getImage(source: ImageSource.camera, maxHeight: -1.0),
+            picker.pickImage(source: ImageSource.camera, maxHeight: -1.0),
             throwsArgumentError,
           );
         });
@@ -161,12 +161,12 @@
         test('handles a null image path response gracefully', () async {
           channel.setMockMethodCallHandler((MethodCall methodCall) => null);
 
-          expect(await picker.getImage(source: ImageSource.gallery), isNull);
-          expect(await picker.getImage(source: ImageSource.camera), isNull);
+          expect(await picker.pickImage(source: ImageSource.gallery), isNull);
+          expect(await picker.pickImage(source: ImageSource.camera), isNull);
         });
 
         test('camera position defaults to back', () async {
-          await picker.getImage(source: ImageSource.camera);
+          await picker.pickImage(source: ImageSource.camera);
 
           expect(
             log,
@@ -183,7 +183,7 @@
         });
 
         test('camera position can set to front', () async {
-          await picker.getImage(
+          await picker.pickImage(
               source: ImageSource.camera,
               preferredCameraDevice: CameraDevice.front);
 
@@ -204,8 +204,8 @@
 
       group('#pickVideo', () {
         test('passes the image source argument correctly', () async {
-          await picker.getVideo(source: ImageSource.camera);
-          await picker.getVideo(source: ImageSource.gallery);
+          await picker.pickVideo(source: ImageSource.camera);
+          await picker.pickVideo(source: ImageSource.gallery);
 
           expect(
             log,
@@ -225,14 +225,14 @@
         });
 
         test('passes the duration argument correctly', () async {
-          await picker.getVideo(source: ImageSource.camera);
-          await picker.getVideo(
+          await picker.pickVideo(source: ImageSource.camera);
+          await picker.pickVideo(
               source: ImageSource.camera,
               maxDuration: const Duration(seconds: 10));
-          await picker.getVideo(
+          await picker.pickVideo(
               source: ImageSource.camera,
               maxDuration: const Duration(minutes: 1));
-          await picker.getVideo(
+          await picker.pickVideo(
               source: ImageSource.camera,
               maxDuration: const Duration(hours: 1));
           expect(
@@ -265,12 +265,12 @@
         test('handles a null video path response gracefully', () async {
           channel.setMockMethodCallHandler((MethodCall methodCall) => null);
 
-          expect(await picker.getVideo(source: ImageSource.gallery), isNull);
-          expect(await picker.getVideo(source: ImageSource.camera), isNull);
+          expect(await picker.pickVideo(source: ImageSource.gallery), isNull);
+          expect(await picker.pickVideo(source: ImageSource.camera), isNull);
         });
 
         test('camera position defaults to back', () async {
-          await picker.getVideo(source: ImageSource.camera);
+          await picker.pickVideo(source: ImageSource.camera);
 
           expect(
             log,
@@ -285,7 +285,7 @@
         });
 
         test('camera position can set to front', () async {
-          await picker.getVideo(
+          await picker.pickVideo(
               source: ImageSource.camera,
               preferredCameraDevice: CameraDevice.front);
 
@@ -310,7 +310,7 @@
               'path': '/example/path',
             };
           });
-          final LostData response = await picker.getLostData();
+          final LostDataResponse response = await picker.retrieveLostData();
           expect(response.type, RetrieveType.image);
           expect(response.file!.path, '/example/path');
         });
@@ -323,7 +323,7 @@
               'errorMessage': 'test_error_message',
             };
           });
-          final LostData response = await picker.getLostData();
+          final LostDataResponse response = await picker.retrieveLostData();
           expect(response.type, RetrieveType.video);
           expect(response.exception!.code, 'test_error_code');
           expect(response.exception!.message, 'test_error_message');
@@ -333,7 +333,7 @@
           channel.setMockMethodCallHandler((MethodCall methodCall) async {
             return null;
           });
-          expect((await picker.getLostData()).isEmpty, true);
+          expect((await picker.retrieveLostData()).isEmpty, true);
         });
 
         test('retrieveLostData get both path and error should throw', () async {
@@ -345,12 +345,12 @@
               'path': '/example/path',
             };
           });
-          expect(picker.getLostData(), throwsAssertionError);
+          expect(picker.retrieveLostData(), throwsAssertionError);
         });
       });
     });
 
-    group('Multi images', () {
+    group('#Multi images', () {
       setUp(() {
         channel.setMockMethodCallHandler((MethodCall methodCall) async {
           log.add(methodCall);
@@ -361,26 +361,26 @@
 
       group('#pickMultiImage', () {
         test('passes the width and height arguments correctly', () async {
-          await picker.getMultiImage();
-          await picker.getMultiImage(
+          await picker.pickMultiImage();
+          await picker.pickMultiImage(
             maxWidth: 10.0,
           );
-          await picker.getMultiImage(
+          await picker.pickMultiImage(
             maxHeight: 10.0,
           );
-          await picker.getMultiImage(
+          await picker.pickMultiImage(
             maxWidth: 10.0,
             maxHeight: 20.0,
           );
-          await picker.getMultiImage(
+          await picker.pickMultiImage(
             maxWidth: 10.0,
             imageQuality: 70,
           );
-          await picker.getMultiImage(
+          await picker.pickMultiImage(
             maxHeight: 10.0,
             imageQuality: 70,
           );
-          await picker.getMultiImage(
+          await picker.pickMultiImage(
               maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70);
 
           expect(
@@ -427,12 +427,12 @@
 
         test('does not accept a negative width or height argument', () {
           expect(
-            picker.getMultiImage(maxWidth: -1.0),
+            picker.pickMultiImage(maxWidth: -1.0),
             throwsArgumentError,
           );
 
           expect(
-            picker.getMultiImage(maxHeight: -1.0),
+            picker.pickMultiImage(maxHeight: -1.0),
             throwsArgumentError,
           );
         });
@@ -440,8 +440,8 @@
         test('handles a null image path response gracefully', () async {
           channel.setMockMethodCallHandler((MethodCall methodCall) => null);
 
-          expect(await picker.getMultiImage(), isNull);
-          expect(await picker.getMultiImage(), isNull);
+          expect(await picker.pickMultiImage(), isNull);
+          expect(await picker.pickMultiImage(), isNull);
         });
       });
     });