[image_picker] Adopt readme excerpts (#3507)

[image_picker] Adopt readme excerpts
diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index fe845b3..140efae 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.8.7+1
+
+* Updates README to use code excerpts.
+
 ## 0.8.7
 
 * Adds `usePhotoPickerAndroid` options.
diff --git a/packages/image_picker/image_picker/README.md b/packages/image_picker/image_picker/README.md
index 3d5a11a..2dfb107 100755
--- a/packages/image_picker/image_picker/README.md
+++ b/packages/image_picker/image_picker/README.md
@@ -1,4 +1,5 @@
 # Image Picker plugin for Flutter
+<?code-excerpt path-base="excerpts/packages/image_picker_example"?>
 
 [![pub package](https://img.shields.io/pub/v/image_picker.svg)](https://pub.dev/packages/image_picker)
 
@@ -42,22 +43,20 @@
 
 ### Example
 
+<?code-excerpt "readme_excerpts.dart (Pick)"?>
 ``` dart
-import 'package:image_picker/image_picker.dart';
-
-    ...
-    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? video = await _picker.pickVideo(source: ImageSource.camera);
-    // Pick multiple images
-    final List<XFile>? images = await _picker.pickMultiImage();
-    ...
+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? galleryVideo =
+    await picker.pickVideo(source: ImageSource.gallery);
+// Capture a video.
+final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
+// Pick multiple images.
+final List<XFile> images = await picker.pickMultiImage();
 ```
 
 ### Handling MainActivity destruction on Android
@@ -71,17 +70,17 @@
 application. Since the data is never returned to the original call use the
 `ImagePicker.retrieveLostData()` method to retrieve the lost data. For example:
 
+<?code-excerpt "readme_excerpts.dart (LostData)"?>
 ```dart
 Future<void> getLostData() async {
-  final LostDataResponse response =
-      await picker.retrieveLostData();
+  final ImagePicker picker = ImagePicker();
+  final LostDataResponse response = await picker.retrieveLostData();
   if (response.isEmpty) {
     return;
   }
-  if (response.files != null) {
-    for (final XFile file in response.files) {
-      _handleFile(file);
-    }
+  final List<XFile>? files = response.files;
+  if (files != null) {
+    _handleLostFiles(files);
   } else {
     _handleError(response.exception);
   }
@@ -95,7 +94,7 @@
 
 ### Android Photo Picker
 
-This package has optional [Android Photo Picker](https://developer.android.com/training/data-storage/shared/photopicker) functionality. 
+This package has optional [Android Photo Picker](https://developer.android.com/training/data-storage/shared/photopicker) functionality.
 [Learn how to use it](https://pub.dev/packages/image_picker_android).
 
 ## Migrating to 0.8.2+
diff --git a/packages/image_picker/image_picker/example/build.excerpt.yaml b/packages/image_picker/image_picker/example/build.excerpt.yaml
new file mode 100644
index 0000000..e317efa
--- /dev/null
+++ b/packages/image_picker/image_picker/example/build.excerpt.yaml
@@ -0,0 +1,15 @@
+targets:
+  $default:
+    sources:
+      include:
+        - lib/**
+        # Some default includes that aren't really used here but will prevent
+        # false-negative warnings:
+        - $package$
+        - lib/$lib$
+      exclude:
+        - '**/.*/**'
+        - '**/build/**'
+    builders:
+      code_excerpter|code_excerpter:
+        enabled: true
diff --git a/packages/image_picker/image_picker/example/lib/readme_excerpts.dart b/packages/image_picker/image_picker/example/lib/readme_excerpts.dart
new file mode 100644
index 0000000..3f0f078
--- /dev/null
+++ b/packages/image_picker/image_picker/example/lib/readme_excerpts.dart
@@ -0,0 +1,54 @@
+// 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 'package:flutter/services.dart';
+import 'package:image_picker/image_picker.dart';
+
+/// Example function for README demonstration of various pick* calls.
+Future<List<XFile?>> readmePickExample() async {
+  // #docregion Pick
+  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? galleryVideo =
+      await picker.pickVideo(source: ImageSource.gallery);
+  // Capture a video.
+  final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
+  // Pick multiple images.
+  final List<XFile> images = await picker.pickMultiImage();
+  // #enddocregion Pick
+
+  // Return everything for the sanity check test.
+  return <XFile?>[
+    image,
+    photo,
+    galleryVideo,
+    cameraVideo,
+    if (images.isEmpty) null else images.first
+  ];
+}
+
+/// Example function for README demonstration of getting lost data.
+// #docregion LostData
+Future<void> getLostData() async {
+  final ImagePicker picker = ImagePicker();
+  final LostDataResponse response = await picker.retrieveLostData();
+  if (response.isEmpty) {
+    return;
+  }
+  final List<XFile>? files = response.files;
+  if (files != null) {
+    _handleLostFiles(files);
+  } else {
+    _handleError(response.exception);
+  }
+}
+// #enddocregion LostData
+
+// Stubs for the getLostData function.
+void _handleLostFiles(List<XFile> file) {}
+void _handleError(PlatformException? exception) {}
diff --git a/packages/image_picker/image_picker/example/pubspec.yaml b/packages/image_picker/image_picker/example/pubspec.yaml
old mode 100755
new mode 100644
index 81c7861..462e582
--- a/packages/image_picker/image_picker/example/pubspec.yaml
+++ b/packages/image_picker/image_picker/example/pubspec.yaml
@@ -17,9 +17,11 @@
     # The example app is bundled with the plugin so we use a path dependency on
     # the parent directory to use the current plugin's version.
     path: ../
+  image_picker_platform_interface: ^2.6.1
   video_player: ^2.1.4
 
 dev_dependencies:
+  build_runner: ^2.1.10
   espresso: ^0.2.0
   flutter_driver:
     sdk: flutter
diff --git a/packages/image_picker/image_picker/example/test/readme_excerpts_test.dart b/packages/image_picker/image_picker/example/test/readme_excerpts_test.dart
new file mode 100644
index 0000000..771d5d4
--- /dev/null
+++ b/packages/image_picker/image_picker/example/test/readme_excerpts_test.dart
@@ -0,0 +1,60 @@
+// 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 'package:flutter_test/flutter_test.dart';
+import 'package:image_picker_example/readme_excerpts.dart';
+import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
+
+void main() {
+  TestWidgetsFlutterBinding.ensureInitialized();
+
+  setUpAll(() async {
+    ImagePickerPlatform.instance = FakeImagePicker();
+  });
+
+  test('sanity check readmePickExample', () async {
+    // Ensure that the snippet code runs successfully.
+    final List<XFile?> results = await readmePickExample();
+    // It should demonstrate a variety of calls.
+    expect(results.length, greaterThan(4));
+    // And the calls should all be different. This works since each fake call
+    // returns a different result.
+    expect(results.map((XFile? file) => file?.path).toSet().length,
+        results.length);
+  });
+
+  test('sanity check getLostData', () async {
+    // Ensure that the snippet code runs successfully.
+    await getLostData();
+  });
+}
+
+class FakeImagePicker extends ImagePickerPlatform {
+  @override
+  Future<XFile?> getImageFromSource(
+      {required ImageSource source,
+      ImagePickerOptions options = const ImagePickerOptions()}) async {
+    return XFile(source == ImageSource.camera ? 'cameraImage' : 'galleryImage');
+  }
+
+  @override
+  Future<LostDataResponse> getLostData() async {
+    return LostDataResponse.empty();
+  }
+
+  @override
+  Future<List<XFile>> getMultiImageWithOptions(
+      {MultiImagePickerOptions options =
+          const MultiImagePickerOptions()}) async {
+    return <XFile>[XFile('multiImage')];
+  }
+
+  @override
+  Future<XFile?> getVideo(
+      {required ImageSource source,
+      CameraDevice preferredCameraDevice = CameraDevice.rear,
+      Duration? maxDuration}) async {
+    return XFile(source == ImageSource.camera ? 'cameraVideo' : 'galleryVideo');
+  }
+}
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index 68f9936..800738b 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/packages/tree/main/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.7
+version: 0.8.7+1
 
 environment:
   sdk: ">=2.17.0 <4.0.0"
diff --git a/script/configs/temp_exclude_excerpt.yaml b/script/configs/temp_exclude_excerpt.yaml
index 5c3a632..a2f7438 100644
--- a/script/configs/temp_exclude_excerpt.yaml
+++ b/script/configs/temp_exclude_excerpt.yaml
@@ -17,7 +17,6 @@
 - google_maps_flutter/google_maps_flutter
 - google_sign_in/google_sign_in
 - google_sign_in_web
-- image_picker/image_picker
 - image_picker_for_web
 - in_app_purchase/in_app_purchase
 - ios_platform_images