[file_selector]Improve API docs and examples (#4824)

diff --git a/packages/file_selector/file_selector/AUTHORS b/packages/file_selector/file_selector/AUTHORS
index dbf9d19..94743a9 100644
--- a/packages/file_selector/file_selector/AUTHORS
+++ b/packages/file_selector/file_selector/AUTHORS
@@ -63,3 +63,4 @@
 Anton Borries <mail@antonborri.es>
 Alex Li <google@alexv525.com>
 Rahul Raj <64.rahulraj@gmail.com>
+TowaYamashita <confirm.apps.develop@gmail.com>
diff --git a/packages/file_selector/file_selector/CHANGELOG.md b/packages/file_selector/file_selector/CHANGELOG.md
index 6397833..ed7b213 100644
--- a/packages/file_selector/file_selector/CHANGELOG.md
+++ b/packages/file_selector/file_selector/CHANGELOG.md
@@ -1,5 +1,6 @@
-## NEXT
+## 0.8.4+3
 
+* Improves API docs and examples.
 * Minor fixes for new analysis options.
 
 ## 0.8.4+2
diff --git a/packages/file_selector/file_selector/README.md b/packages/file_selector/file_selector/README.md
index 89cac1e..f5c1de8 100644
--- a/packages/file_selector/file_selector/README.md
+++ b/packages/file_selector/file_selector/README.md
@@ -1,5 +1,7 @@
 # file_selector
 
+<?code-excerpt path-base="excerpts/packages/file_selector_example"?>
+
 [![pub package](https://img.shields.io/pub/v/file_selector.svg)](https://pub.dartlang.org/packages/file_selector)
 
 A Flutter plugin that manages files and interactions with file dialogs.
@@ -30,25 +32,48 @@
 Please also take a look at our [example][example] app.
 
 #### Open a single file
+<?code-excerpt "open_image_page.dart (SingleOpen)"?>
 ``` dart
-final typeGroup = XTypeGroup(label: 'images', extensions: ['jpg', 'png']);
-final file = await openFile(acceptedTypeGroups: [typeGroup]);
+final XTypeGroup typeGroup = XTypeGroup(
+  label: 'images',
+  extensions: <String>['jpg', 'png'],
+);
+final XFile? file =
+    await openFile(acceptedTypeGroups: <XTypeGroup>[typeGroup]);
 ```
 
 #### Open multiple files at once
+<?code-excerpt "open_multiple_images_page.dart (MultiOpen)"?>
 ``` dart
-final typeGroup = XTypeGroup(label: 'images', extensions: ['jpg', 'png']);
-final files = await openFiles(acceptedTypeGroups: [typeGroup]);
+final XTypeGroup jpgsTypeGroup = XTypeGroup(
+  label: 'JPEGs',
+  extensions: <String>['jpg', 'jpeg'],
+);
+final XTypeGroup pngTypeGroup = XTypeGroup(
+  label: 'PNGs',
+  extensions: <String>['png'],
+);
+final List<XFile> files = await openFiles(acceptedTypeGroups: <XTypeGroup>[
+  jpgsTypeGroup,
+  pngTypeGroup,
+]);
 ```
 
 #### Saving a file
+<?code-excerpt "readme_standalone_excerpts.dart (Save)"?>
 ```dart
-final path = await getSavePath();
-final name = "hello_file_selector.txt";
-final data = Uint8List.fromList("Hello World!".codeUnits);
-final mimeType = "text/plain";
-final file = XFile.fromData(data, name: name, mimeType: mimeType);
-await file.saveTo(path);
+const String fileName = 'suggested_name.txt';
+final String? path = await getSavePath(suggestedName: fileName);
+if (path == null) {
+  // Operation was canceled by the user.
+  return;
+}
+
+final Uint8List fileData = Uint8List.fromList('Hello World!'.codeUnits);
+const String mimeType = 'text/plain';
+final XFile textFile =
+    XFile.fromData(fileData, mimeType: mimeType, name: fileName);
+await textFile.saveTo(path);
 ```
 
 [example]:./example
diff --git a/packages/file_selector/file_selector/example/build.excerpt.yaml b/packages/file_selector/file_selector/example/build.excerpt.yaml
new file mode 100644
index 0000000..e317efa
--- /dev/null
+++ b/packages/file_selector/file_selector/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/file_selector/file_selector/example/lib/main.dart b/packages/file_selector/file_selector/example/lib/main.dart
index 34f5857..d05e80f 100644
--- a/packages/file_selector/file_selector/example/lib/main.dart
+++ b/packages/file_selector/file_selector/example/lib/main.dart
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:example/get_directory_page.dart';
-import 'package:example/home_page.dart';
-import 'package:example/open_image_page.dart';
-import 'package:example/open_multiple_images_page.dart';
-import 'package:example/open_text_page.dart';
-import 'package:example/save_text_page.dart';
 import 'package:flutter/material.dart';
 
+import 'get_directory_page.dart';
+import 'home_page.dart';
+import 'open_image_page.dart';
+import 'open_multiple_images_page.dart';
+import 'open_text_page.dart';
+import 'save_text_page.dart';
+
 void main() {
   runApp(const MyApp());
 }
diff --git a/packages/file_selector/file_selector/example/lib/open_image_page.dart b/packages/file_selector/file_selector/example/lib/open_image_page.dart
index e520ffb..4fb0686 100644
--- a/packages/file_selector/file_selector/example/lib/open_image_page.dart
+++ b/packages/file_selector/file_selector/example/lib/open_image_page.dart
@@ -14,17 +14,18 @@
   const OpenImagePage({Key? key}) : super(key: key);
 
   Future<void> _openImageFile(BuildContext context) async {
+    // #docregion SingleOpen
     final XTypeGroup typeGroup = XTypeGroup(
       label: 'images',
       extensions: <String>['jpg', 'png'],
     );
-    final List<XFile> files =
-        await openFiles(acceptedTypeGroups: <XTypeGroup>[typeGroup]);
-    if (files.isEmpty) {
+    final XFile? file =
+        await openFile(acceptedTypeGroups: <XTypeGroup>[typeGroup]);
+    // #enddocregion SingleOpen
+    if (file == null) {
       // Operation was canceled by the user.
       return;
     }
-    final XFile file = files[0];
     final String fileName = file.name;
     final String filePath = file.path;
 
diff --git a/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart b/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart
index e2d21c7..ac3d66f 100644
--- a/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart
+++ b/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart
@@ -14,6 +14,7 @@
   const OpenMultipleImagesPage({Key? key}) : super(key: key);
 
   Future<void> _openImageFile(BuildContext context) async {
+    // #docregion MultiOpen
     final XTypeGroup jpgsTypeGroup = XTypeGroup(
       label: 'JPEGs',
       extensions: <String>['jpg', 'jpeg'],
@@ -26,6 +27,7 @@
       jpgsTypeGroup,
       pngTypeGroup,
     ]);
+    // #enddocregion MultiOpen
     if (files.isEmpty) {
       // Operation was canceled by the user.
       return;
diff --git a/packages/file_selector/file_selector/example/lib/open_text_page.dart b/packages/file_selector/file_selector/example/lib/open_text_page.dart
index be48a43..057925e 100644
--- a/packages/file_selector/file_selector/example/lib/open_text_page.dart
+++ b/packages/file_selector/file_selector/example/lib/open_text_page.dart
@@ -4,6 +4,7 @@
 
 import 'package:file_selector/file_selector.dart';
 import 'package:flutter/material.dart';
+import 'package:path_provider/path_provider.dart';
 
 /// Screen that shows an example of openFile
 class OpenTextPage extends StatelessWidget {
@@ -15,8 +16,15 @@
       label: 'text',
       extensions: <String>['txt', 'json'],
     );
-    final XFile? file =
-        await openFile(acceptedTypeGroups: <XTypeGroup>[typeGroup]);
+    // This demonstrates using an initial directory for the prompt, which should
+    // only be done in cases where the application can likely predict where the
+    // file would be. In most cases, this parameter should not be provided.
+    final String initialDirectory =
+        (await getApplicationDocumentsDirectory()).path;
+    final XFile? file = await openFile(
+      acceptedTypeGroups: <XTypeGroup>[typeGroup],
+      initialDirectory: initialDirectory,
+    );
     if (file == null) {
       // Operation was canceled by the user.
       return;
diff --git a/packages/file_selector/file_selector/example/lib/readme_standalone_excerpts.dart b/packages/file_selector/file_selector/example/lib/readme_standalone_excerpts.dart
new file mode 100644
index 0000000..c67c93f
--- /dev/null
+++ b/packages/file_selector/file_selector/example/lib/readme_standalone_excerpts.dart
@@ -0,0 +1,57 @@
+// 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.
+
+// This file exists solely to host compiled excerpts for README.md, and is not
+// intended for use as an actual example application.
+
+// ignore_for_file: public_member_api_docs
+
+// TODO(a14n): remove this import once Flutter 3.1 or later reaches stable (including flutter/flutter#104231)
+// ignore: unnecessary_import
+import 'dart:typed_data';
+
+import 'package:file_selector/file_selector.dart';
+import 'package:flutter/material.dart';
+
+void main() {
+  runApp(const MyApp());
+}
+
+class MyApp extends StatefulWidget {
+  const MyApp({Key? key}) : super(key: key);
+
+  @override
+  State<MyApp> createState() => _MyAppState();
+}
+
+class _MyAppState extends State<MyApp> {
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      home: Scaffold(
+        appBar: AppBar(
+          title: const Text('README snippet app'),
+        ),
+        body: const Text('See example in main.dart'),
+      ),
+    );
+  }
+
+  Future<void> saveFile() async {
+    // #docregion Save
+    const String fileName = 'suggested_name.txt';
+    final String? path = await getSavePath(suggestedName: fileName);
+    if (path == null) {
+      // Operation was canceled by the user.
+      return;
+    }
+
+    final Uint8List fileData = Uint8List.fromList('Hello World!'.codeUnits);
+    const String mimeType = 'text/plain';
+    final XFile textFile =
+        XFile.fromData(fileData, mimeType: mimeType, name: fileName);
+    await textFile.saveTo(path);
+    // #enddocregion Save
+  }
+}
diff --git a/packages/file_selector/file_selector/example/lib/save_text_page.dart b/packages/file_selector/file_selector/example/lib/save_text_page.dart
index b031784..257add5 100644
--- a/packages/file_selector/file_selector/example/lib/save_text_page.dart
+++ b/packages/file_selector/file_selector/example/lib/save_text_page.dart
@@ -5,6 +5,7 @@
 import 'dart:typed_data';
 import 'package:file_selector/file_selector.dart';
 import 'package:flutter/material.dart';
+import 'package:path_provider/path_provider.dart';
 
 /// Page for showing an example of saving with file_selector
 class SaveTextPage extends StatelessWidget {
@@ -15,17 +16,27 @@
   final TextEditingController _contentController = TextEditingController();
 
   Future<void> _saveFile() async {
-    final String? path = await getSavePath();
+    final String fileName = _nameController.text;
+    // This demonstrates using an initial directory for the prompt, which should
+    // only be done in cases where the application can likely predict where the
+    // file will be saved. In most cases, this parameter should not be provided.
+    final String initialDirectory =
+        (await getApplicationDocumentsDirectory()).path;
+    final String? path = await getSavePath(
+      initialDirectory: initialDirectory,
+      suggestedName: fileName,
+    );
     if (path == null) {
       // Operation was canceled by the user.
       return;
     }
+
     final String text = _contentController.text;
-    final String fileName = _nameController.text;
     final Uint8List fileData = Uint8List.fromList(text.codeUnits);
     const String fileMimeType = 'text/plain';
     final XFile textFile =
         XFile.fromData(fileData, mimeType: fileMimeType, name: fileName);
+
     await textFile.saveTo(path);
   }
 
diff --git a/packages/file_selector/file_selector/example/pubspec.yaml b/packages/file_selector/file_selector/example/pubspec.yaml
index 531f479..011d958 100644
--- a/packages/file_selector/file_selector/example/pubspec.yaml
+++ b/packages/file_selector/file_selector/example/pubspec.yaml
@@ -1,4 +1,4 @@
-name: example
+name: file_selector_example
 description: A new Flutter project.
 publish_to: none
 
@@ -17,8 +17,10 @@
     path: ../
   flutter:
     sdk: flutter
+  path_provider: ^2.0.9
 
 dev_dependencies:
+  build_runner: ^2.1.10
   flutter_test:
     sdk: flutter
 
diff --git a/packages/file_selector/file_selector/example/windows/flutter/generated_plugins.cmake b/packages/file_selector/file_selector/example/windows/flutter/generated_plugins.cmake
index 63eda9b..a423a02 100644
--- a/packages/file_selector/file_selector/example/windows/flutter/generated_plugins.cmake
+++ b/packages/file_selector/file_selector/example/windows/flutter/generated_plugins.cmake
@@ -6,6 +6,9 @@
   file_selector_windows
 )
 
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+)
+
 set(PLUGIN_BUNDLED_LIBRARIES)
 
 foreach(plugin ${FLUTTER_PLUGIN_LIST})
@@ -14,3 +17,8 @@
   list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
 endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/packages/file_selector/file_selector/lib/file_selector.dart b/packages/file_selector/file_selector/lib/file_selector.dart
index c2803d6..322ae6c 100644
--- a/packages/file_selector/file_selector/lib/file_selector.dart
+++ b/packages/file_selector/file_selector/lib/file_selector.dart
@@ -9,7 +9,24 @@
 export 'package:file_selector_platform_interface/file_selector_platform_interface.dart'
     show XFile, XTypeGroup;
 
-/// Open file dialog for loading files and return a file path
+/// Opens a file selection dialog and returns the path chosen by the user.
+///
+/// [acceptedTypeGroups] is a list of file type groups that can be selected in
+/// the dialog. How this is displayed depends on the pltaform, for example:
+/// - On Windows and Linux, each group will be an entry in a list of filter
+///   options.
+/// - On macOS, the union of all types allowed by all of the groups will be
+///   allowed.
+///
+/// [initialDirectory] is the full path to the directory that will be displayed
+/// when the dialog is opened. When not provided, the platform will pick an
+/// initial location. This is ignored on the Web platform.
+///
+/// [confirmButtonText] is the text in the confirmation button of the dialog.
+/// When not provided, the default OS label is used (for example, "Open").
+/// This is ignored on the Web platform.
+///
+/// Returns `null` if the user cancels the operation.
 Future<XFile?> openFile({
   List<XTypeGroup> acceptedTypeGroups = const <XTypeGroup>[],
   String? initialDirectory,
@@ -21,7 +38,24 @@
       confirmButtonText: confirmButtonText);
 }
 
-/// Open file dialog for loading files and return a list of file paths
+/// Opens a file selection dialog and returns the list of paths chosen by the
+/// user.
+///
+/// [acceptedTypeGroups] is a list of file type groups that can be selected in
+/// the dialog. How this is displayed depends on the pltaform, for example:
+/// - On Windows and Linux, each group will be an entry in a list of filter
+///   options.
+/// - On macOS, the union of all types allowed by all of the groups will be
+///   allowed.
+///
+/// [initialDirectory] is the full path to the directory that will be displayed
+/// when the dialog is opened. When not provided, the platform will pick an
+/// initial location.
+///
+/// [confirmButtonText] is the text in the confirmation button of the dialog.
+/// When not provided, the default OS label is used (for example, "Open").
+///
+/// Returns an empty list if the user cancels the operation.
 Future<List<XFile>> openFiles({
   List<XTypeGroup> acceptedTypeGroups = const <XTypeGroup>[],
   String? initialDirectory,
@@ -33,7 +67,25 @@
       confirmButtonText: confirmButtonText);
 }
 
-/// Saves File to user's file system
+/// Opens a save dialog and returns the target path chosen by the user.
+///
+/// [acceptedTypeGroups] is a list of file type groups that can be selected in
+/// the dialog. How this is displayed depends on the pltaform, for example:
+/// - On Windows and Linux, each group will be an entry in a list of filter
+///   options.
+/// - On macOS, the union of all types allowed by all of the groups will be
+///   allowed.
+///
+/// [initialDirectory] is the full path to the directory that will be displayed
+/// when the dialog is opened. When not provided, the platform will pick an
+/// initial location.
+///
+/// [suggestedName] is initial value of file name.
+///
+/// [confirmButtonText] is the text in the confirmation button of the dialog.
+/// When not provided, the default OS label is used (for example, "Save").
+///
+/// Returns `null` if the user cancels the operation.
 Future<String?> getSavePath({
   List<XTypeGroup> acceptedTypeGroups = const <XTypeGroup>[],
   String? initialDirectory,
@@ -47,7 +99,17 @@
       confirmButtonText: confirmButtonText);
 }
 
-/// Gets a directory path from a user's file system
+/// Opens a directory selection dialog and returns the path chosen by the user.
+/// This always returns `null` on the web.
+///
+/// [initialDirectory] is the full path to the directory that will be displayed
+/// when the dialog is opened. When not provided, the platform will pick an
+/// initial location.
+///
+/// [confirmButtonText] is the text in the confirmation button of the dialog.
+/// When not provided, the default OS label is used (for example, "Open").
+///
+/// Returns `null` if the user cancels the operation.
 Future<String?> getDirectoryPath({
   String? initialDirectory,
   String? confirmButtonText,
diff --git a/packages/file_selector/file_selector/pubspec.yaml b/packages/file_selector/file_selector/pubspec.yaml
index 1c502c0..12a1fbc 100644
--- a/packages/file_selector/file_selector/pubspec.yaml
+++ b/packages/file_selector/file_selector/pubspec.yaml
@@ -3,7 +3,7 @@
   directories, using native file selection UI.
 repository: https://github.com/flutter/plugins/tree/main/packages/file_selector/file_selector
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22
-version: 0.8.4+2
+version: 0.8.4+3
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
diff --git a/script/configs/temp_exclude_excerpt.yaml b/script/configs/temp_exclude_excerpt.yaml
index bd73880..dec99ee 100644
--- a/script/configs/temp_exclude_excerpt.yaml
+++ b/script/configs/temp_exclude_excerpt.yaml
@@ -7,7 +7,6 @@
 # https://github.com/flutter/flutter/issues/102679
 - camera_web
 - espresso
-- file_selector/file_selector
 - google_maps_flutter/google_maps_flutter
 - google_sign_in/google_sign_in
 - google_sign_in_web