[path_provider] Add getApplicationCachePath() - implementations (#4619)

Platform implementations split out from #4483.
diff --git a/packages/path_provider/path_provider_android/CHANGELOG.md b/packages/path_provider/path_provider_android/CHANGELOG.md
index 8164575..f829dcc 100644
--- a/packages/path_provider/path_provider_android/CHANGELOG.md
+++ b/packages/path_provider/path_provider_android/CHANGELOG.md
@@ -1,5 +1,6 @@
-## NEXT
+## 2.1.0
 
+* Adds getApplicationCachePath() for storing app-specific cache files.
 * Updates minimum supported SDK version to Flutter 3.3/Dart 2.18.
 
 ## 2.0.27
diff --git a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java
index 11cda6b..1bfa729 100644
--- a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java
+++ b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java
@@ -1,7 +1,7 @@
 // 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.
-// Autogenerated from Pigeon (v9.2.4), do not edit directly.
+// Autogenerated from Pigeon (v9.2.5), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 package io.flutter.plugins.pathprovider;
@@ -85,6 +85,9 @@
     String getApplicationDocumentsPath();
 
     @Nullable
+    String getApplicationCachePath();
+
+    @Nullable
     String getExternalStoragePath();
 
     @NonNull
@@ -181,6 +184,31 @@
         BasicMessageChannel<Object> channel =
             new BasicMessageChannel<>(
                 binaryMessenger,
+                "dev.flutter.pigeon.PathProviderApi.getApplicationCachePath",
+                getCodec(),
+                taskQueue);
+        if (api != null) {
+          channel.setMessageHandler(
+              (message, reply) -> {
+                ArrayList<Object> wrapped = new ArrayList<Object>();
+                try {
+                  String output = api.getApplicationCachePath();
+                  wrapped.add(0, output);
+                } catch (Throwable exception) {
+                  ArrayList<Object> wrappedError = wrapError(exception);
+                  wrapped = wrappedError;
+                }
+                reply.reply(wrapped);
+              });
+        } else {
+          channel.setMessageHandler(null);
+        }
+      }
+      {
+        BinaryMessenger.TaskQueue taskQueue = binaryMessenger.makeBackgroundTaskQueue();
+        BasicMessageChannel<Object> channel =
+            new BasicMessageChannel<>(
+                binaryMessenger,
                 "dev.flutter.pigeon.PathProviderApi.getExternalStoragePath",
                 getCodec(),
                 taskQueue);
diff --git a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java
index 6e259cf..4ce1ba0 100644
--- a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java
+++ b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java
@@ -67,6 +67,11 @@
   }
 
   @Override
+  public @Nullable String getApplicationCachePath() {
+    return context.getCacheDir().getPath();
+  }
+
+  @Override
   public @Nullable String getExternalStoragePath() {
     return getPathProviderStorageDirectory();
   }
diff --git a/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart
index ecd0b97..1403d93 100644
--- a/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart
+++ b/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart
@@ -28,6 +28,12 @@
     _verifySampleFile(result, 'applicationSupport');
   });
 
+  testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async {
+    final PathProviderPlatform provider = PathProviderPlatform.instance;
+    final String? result = await provider.getApplicationCachePath();
+    _verifySampleFile(result, 'applicationCache');
+  });
+
   testWidgets('getLibraryDirectory', (WidgetTester tester) async {
     final PathProviderPlatform provider = PathProviderPlatform.instance;
     expect(() => provider.getLibraryPath(),
diff --git a/packages/path_provider/path_provider_android/example/lib/main.dart b/packages/path_provider/path_provider_android/example/lib/main.dart
index d0bc13b..79293e1 100644
--- a/packages/path_provider/path_provider_android/example/lib/main.dart
+++ b/packages/path_provider/path_provider_android/example/lib/main.dart
@@ -39,6 +39,7 @@
   Future<String?>? _tempDirectory;
   Future<String?>? _appSupportDirectory;
   Future<String?>? _appDocumentsDirectory;
+  Future<String?>? _appCacheDirectory;
   Future<String?>? _externalDocumentsDirectory;
   Future<List<String>?>? _externalStorageDirectories;
   Future<List<String>?>? _externalCacheDirectories;
@@ -92,6 +93,12 @@
     });
   }
 
+  void _requestAppCacheDirectory() {
+    setState(() {
+      _appCacheDirectory = provider.getApplicationCachePath();
+    });
+  }
+
   void _requestExternalStorageDirectory() {
     setState(() {
       _externalDocumentsDirectory = provider.getExternalStoragePath();
@@ -150,6 +157,15 @@
             Padding(
               padding: const EdgeInsets.all(16.0),
               child: ElevatedButton(
+                onPressed: _requestAppCacheDirectory,
+                child: const Text('Get Application Cache Directory'),
+              ),
+            ),
+            FutureBuilder<String?>(
+                future: _appCacheDirectory, builder: _buildDirectory),
+            Padding(
+              padding: const EdgeInsets.all(16.0),
+              child: ElevatedButton(
                 onPressed: _requestExternalStorageDirectory,
                 child: const Text('Get External Storage Directory'),
               ),
diff --git a/packages/path_provider/path_provider_android/example/pubspec.yaml b/packages/path_provider/path_provider_android/example/pubspec.yaml
index 852d1cd..df9d0e3 100644
--- a/packages/path_provider/path_provider_android/example/pubspec.yaml
+++ b/packages/path_provider/path_provider_android/example/pubspec.yaml
@@ -16,7 +16,7 @@
     # 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: ../
-  path_provider_platform_interface: ^2.0.0
+  path_provider_platform_interface: ^2.1.0
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/path_provider/path_provider_android/lib/messages.g.dart b/packages/path_provider/path_provider_android/lib/messages.g.dart
index ec5c1f9..20d4368 100644
--- a/packages/path_provider/path_provider_android/lib/messages.g.dart
+++ b/packages/path_provider/path_provider_android/lib/messages.g.dart
@@ -1,7 +1,7 @@
 // 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.
-// Autogenerated from Pigeon (v9.2.4), do not edit directly.
+// Autogenerated from Pigeon (v9.2.5), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
 
@@ -98,6 +98,27 @@
     }
   }
 
+  Future<String?> getApplicationCachePath() async {
+    final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.PathProviderApi.getApplicationCachePath', codec,
+        binaryMessenger: _binaryMessenger);
+    final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
+    if (replyList == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+      );
+    } else if (replyList.length > 1) {
+      throw PlatformException(
+        code: replyList[0]! as String,
+        message: replyList[1] as String?,
+        details: replyList[2],
+      );
+    } else {
+      return (replyList[0] as String?);
+    }
+  }
+
   Future<String?> getExternalStoragePath() async {
     final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
         'dev.flutter.pigeon.PathProviderApi.getExternalStoragePath', codec,
diff --git a/packages/path_provider/path_provider_android/lib/path_provider_android.dart b/packages/path_provider/path_provider_android/lib/path_provider_android.dart
index f5c74f5..c65b0ab 100644
--- a/packages/path_provider/path_provider_android/lib/path_provider_android.dart
+++ b/packages/path_provider/path_provider_android/lib/path_provider_android.dart
@@ -63,6 +63,11 @@
   }
 
   @override
+  Future<String?> getApplicationCachePath() {
+    return _api.getApplicationCachePath();
+  }
+
+  @override
   Future<String?> getExternalStoragePath() {
     return _api.getExternalStoragePath();
   }
diff --git a/packages/path_provider/path_provider_android/pigeons/messages.dart b/packages/path_provider/path_provider_android/pigeons/messages.dart
index 96ad634..6e4eb8f 100644
--- a/packages/path_provider/path_provider_android/pigeons/messages.dart
+++ b/packages/path_provider/path_provider_android/pigeons/messages.dart
@@ -36,6 +36,8 @@
   @TaskQueue(type: TaskQueueType.serialBackgroundThread)
   String? getApplicationDocumentsPath();
   @TaskQueue(type: TaskQueueType.serialBackgroundThread)
+  String? getApplicationCachePath();
+  @TaskQueue(type: TaskQueueType.serialBackgroundThread)
   String? getExternalStoragePath();
   @TaskQueue(type: TaskQueueType.serialBackgroundThread)
   List<String?> getExternalCachePaths();
diff --git a/packages/path_provider/path_provider_android/pubspec.yaml b/packages/path_provider/path_provider_android/pubspec.yaml
index ee83173..42c4ba1 100644
--- a/packages/path_provider/path_provider_android/pubspec.yaml
+++ b/packages/path_provider/path_provider_android/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Android implementation of the path_provider plugin.
 repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_android
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22
-version: 2.0.27
+version: 2.1.0
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
@@ -20,7 +20,7 @@
 dependencies:
   flutter:
     sdk: flutter
-  path_provider_platform_interface: ^2.0.1
+  path_provider_platform_interface: ^2.1.0
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/path_provider/path_provider_android/test/messages_test.g.dart b/packages/path_provider/path_provider_android/test/messages_test.g.dart
index 515f6b5..e18fc96 100644
--- a/packages/path_provider/path_provider_android/test/messages_test.g.dart
+++ b/packages/path_provider/path_provider_android/test/messages_test.g.dart
@@ -1,7 +1,7 @@
 // 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.
-// Autogenerated from Pigeon (v9.2.4), do not edit directly.
+// Autogenerated from Pigeon (v9.2.5), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import
 // ignore_for_file: avoid_relative_lib_imports
@@ -24,6 +24,8 @@
 
   String? getApplicationDocumentsPath();
 
+  String? getApplicationCachePath();
+
   String? getExternalStoragePath();
 
   List<String?> getExternalCachePaths();
@@ -86,6 +88,23 @@
     }
     {
       final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+          'dev.flutter.pigeon.PathProviderApi.getApplicationCachePath', codec,
+          binaryMessenger: binaryMessenger);
+      if (api == null) {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel, null);
+      } else {
+        _testBinaryMessengerBinding!.defaultBinaryMessenger
+            .setMockDecodedMessageHandler<Object?>(channel,
+                (Object? message) async {
+          // ignore message
+          final String? output = api.getApplicationCachePath();
+          return <Object?>[output];
+        });
+      }
+    }
+    {
+      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
           'dev.flutter.pigeon.PathProviderApi.getExternalStoragePath', codec,
           binaryMessenger: binaryMessenger);
       if (api == null) {
diff --git a/packages/path_provider/path_provider_android/test/path_provider_android_test.dart b/packages/path_provider/path_provider_android/test/path_provider_android_test.dart
index e301147..5f94da6 100644
--- a/packages/path_provider/path_provider_android/test/path_provider_android_test.dart
+++ b/packages/path_provider/path_provider_android/test/path_provider_android_test.dart
@@ -12,6 +12,7 @@
 const String kApplicationSupportPath = 'applicationSupportPath';
 const String kLibraryPath = 'libraryPath';
 const String kApplicationDocumentsPath = 'applicationDocumentsPath';
+const String kApplicationCachePath = 'applicationCachePath';
 const String kExternalCachePaths = 'externalCachePaths';
 const String kExternalStoragePaths = 'externalStoragePaths';
 const String kDownloadsPath = 'downloadsPath';
@@ -24,6 +25,9 @@
   String? getApplicationSupportPath() => kApplicationSupportPath;
 
   @override
+  String? getApplicationCachePath() => kApplicationCachePath;
+
+  @override
   List<String?> getExternalCachePaths() => <String>[kExternalCachePaths];
 
   @override
@@ -58,6 +62,11 @@
       expect(path, kApplicationSupportPath);
     });
 
+    test('getApplicationCachePath', () async {
+      final String? path = await pathProvider.getApplicationCachePath();
+      expect(path, kApplicationCachePath);
+    });
+
     test('getLibraryPath fails', () async {
       try {
         await pathProvider.getLibraryPath();
diff --git a/packages/path_provider/path_provider_foundation/CHANGELOG.md b/packages/path_provider/path_provider_foundation/CHANGELOG.md
index 1bbba4d..0142c04 100644
--- a/packages/path_provider/path_provider_foundation/CHANGELOG.md
+++ b/packages/path_provider/path_provider_foundation/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.3.0
+
+* Adds getApplicationCachePath() for storing app-specific cache files.
+
 ## 2.2.4
 
 * Updates to the latest version of `pigeon`.
diff --git a/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift b/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift
index e2346b0..5530b8b 100644
--- a/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift
+++ b/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift
@@ -25,12 +25,12 @@
   func getDirectoryPath(type: DirectoryType) -> String? {
     var path = getDirectory(ofType: fileManagerDirectoryForType(type))
   #if os(macOS)
-    // In a non-sandboxed app, this is a shared directory where applications are
+    // In a non-sandboxed app, these are shared directories where applications are
     // expected to use its bundle ID as a subdirectory. (For non-sandboxed apps,
     // adding the extra path is harmless).
     // This is not done for iOS, for compatibility with older versions of the
     // plugin.
-    if type == .applicationSupport {
+    if type == .applicationSupport || type == .applicationCache {
       if let basePath = path {
         let basePathURL = URL.init(fileURLWithPath: basePath)
         path = basePathURL.appendingPathComponent(Bundle.main.bundleIdentifier!).path
@@ -49,6 +49,8 @@
 /// Returns the FileManager constant corresponding to the given type.
 private func fileManagerDirectoryForType(_ type: DirectoryType) -> FileManager.SearchPathDirectory {
   switch type {
+    case .applicationCache:
+      return FileManager.SearchPathDirectory.cachesDirectory
     case .applicationDocuments:
       return FileManager.SearchPathDirectory.documentDirectory
     case .applicationSupport:
diff --git a/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift b/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift
index 402e14f..4af5ac3 100644
--- a/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift
+++ b/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift
@@ -44,6 +44,7 @@
   case downloads = 2
   case library = 3
   case temp = 4
+  case applicationCache = 5
 }
 /// Generated protocol from Pigeon that represents a handler of messages from Flutter.
 protocol PathProviderApi {
diff --git a/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart
index b67730a..0d05745 100644
--- a/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart
+++ b/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart
@@ -29,6 +29,12 @@
     _verifySampleFile(result, 'applicationSupport');
   });
 
+  testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async {
+    final PathProviderPlatform provider = PathProviderPlatform.instance;
+    final String? result = await provider.getApplicationCachePath();
+    _verifySampleFile(result, 'applicationCache');
+  });
+
   testWidgets('getLibraryDirectory', (WidgetTester tester) async {
     final PathProviderPlatform provider = PathProviderPlatform.instance;
     final String? result = await provider.getLibraryPath();
diff --git a/packages/path_provider/path_provider_foundation/example/lib/main.dart b/packages/path_provider/path_provider_foundation/example/lib/main.dart
index 3e3a599..c766ccf 100644
--- a/packages/path_provider/path_provider_foundation/example/lib/main.dart
+++ b/packages/path_provider/path_provider_foundation/example/lib/main.dart
@@ -27,6 +27,7 @@
   String? _appSupportDirectory = 'Unknown';
   String? _documentsDirectory = 'Unknown';
   String? _containerDirectory = 'Unknown';
+  String? _cacheDirectory = 'Unknown';
 
   @override
   void initState() {
@@ -42,6 +43,7 @@
     String? libraryDirectory;
     String? documentsDirectory;
     String? containerDirectory;
+    String? cacheDirectory;
     final PathProviderPlatform provider = PathProviderPlatform.instance;
     final PathProviderFoundation providerFoundation = PathProviderFoundation();
 
@@ -82,6 +84,12 @@
           'Failed to get app group container directory: $exception';
     }
 
+    try {
+      cacheDirectory = await provider.getApplicationCachePath();
+    } catch (exception) {
+      cacheDirectory = 'Failed to get cache directory: $exception';
+    }
+
     setState(() {
       _tempDirectory = tempDirectory;
       _downloadsDirectory = downloadsDirectory;
@@ -89,6 +97,7 @@
       _appSupportDirectory = appSupportDirectory;
       _documentsDirectory = documentsDirectory;
       _containerDirectory = containerDirectory;
+      _cacheDirectory = cacheDirectory;
     });
   }
 
@@ -108,6 +117,7 @@
               Text('Library Directory: $_libraryDirectory\n'),
               Text('Application Support Directory: $_appSupportDirectory\n'),
               Text('App Group Container Directory: $_containerDirectory\n'),
+              Text('Cache Directory: $_cacheDirectory\n'),
             ],
           ),
         ),
diff --git a/packages/path_provider/path_provider_foundation/example/pubspec.yaml b/packages/path_provider/path_provider_foundation/example/pubspec.yaml
index 65feace..51bc61d 100644
--- a/packages/path_provider/path_provider_foundation/example/pubspec.yaml
+++ b/packages/path_provider/path_provider_foundation/example/pubspec.yaml
@@ -16,7 +16,7 @@
     # 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: ../
-  path_provider_platform_interface: ^2.0.0
+  path_provider_platform_interface: ^2.1.0
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/path_provider/path_provider_foundation/lib/messages.g.dart b/packages/path_provider/path_provider_foundation/lib/messages.g.dart
index 7893dbd..3fdbadd 100644
--- a/packages/path_provider/path_provider_foundation/lib/messages.g.dart
+++ b/packages/path_provider/path_provider_foundation/lib/messages.g.dart
@@ -17,6 +17,7 @@
   downloads,
   library,
   temp,
+  applicationCache,
 }
 
 class PathProviderApi {
diff --git a/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart b/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart
index 32bbf02..55e24c4 100644
--- a/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart
+++ b/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart
@@ -52,6 +52,18 @@
   }
 
   @override
+  Future<String?> getApplicationCachePath() async {
+    final String? path =
+        await _pathProvider.getDirectoryPath(DirectoryType.applicationCache);
+    if (path != null) {
+      // Ensure the directory exists before returning it, for consistency with
+      // other platforms.
+      await Directory(path).create(recursive: true);
+    }
+    return path;
+  }
+
+  @override
   Future<String?> getExternalStoragePath() async {
     throw UnsupportedError(
         'getExternalStoragePath is not supported on this platform');
diff --git a/packages/path_provider/path_provider_foundation/pigeons/messages.dart b/packages/path_provider/path_provider_foundation/pigeons/messages.dart
index e3d9d0d..ae4e7c1 100644
--- a/packages/path_provider/path_provider_foundation/pigeons/messages.dart
+++ b/packages/path_provider/path_provider_foundation/pigeons/messages.dart
@@ -16,6 +16,7 @@
   downloads,
   library,
   temp,
+  applicationCache,
 }
 
 @HostApi(dartHostTestHandler: 'TestPathProviderApi')
diff --git a/packages/path_provider/path_provider_foundation/pubspec.yaml b/packages/path_provider/path_provider_foundation/pubspec.yaml
index 936e182..6117963 100644
--- a/packages/path_provider/path_provider_foundation/pubspec.yaml
+++ b/packages/path_provider/path_provider_foundation/pubspec.yaml
@@ -2,7 +2,7 @@
 description: iOS and macOS implementation of the path_provider plugin
 repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_foundation
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22
-version: 2.2.4
+version: 2.3.0
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
@@ -24,7 +24,7 @@
 dependencies:
   flutter:
     sdk: flutter
-  path_provider_platform_interface: ^2.0.1
+  path_provider_platform_interface: ^2.1.0
 
 dev_dependencies:
   build_runner: ^2.3.2
diff --git a/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart b/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart
index e8337a7..e13e182 100644
--- a/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart
+++ b/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart
@@ -98,6 +98,32 @@
       expect(path, applicationDocumentsPath);
     });
 
+    test('getApplicationCachePath', () async {
+      final PathProviderFoundation pathProvider = PathProviderFoundation();
+      final String applicationCachePath =
+          p.join(testRoot.path, 'application', 'cache', 'path');
+      when(mockApi.getDirectoryPath(DirectoryType.applicationCache))
+          .thenReturn(applicationCachePath);
+
+      final String? path = await pathProvider.getApplicationCachePath();
+
+      verify(mockApi.getDirectoryPath(DirectoryType.applicationCache));
+      expect(path, applicationCachePath);
+    });
+
+    test('getApplicationCachePath creates the directory if necessary',
+        () async {
+      final PathProviderFoundation pathProvider = PathProviderFoundation();
+      final String applicationCachePath =
+          p.join(testRoot.path, 'application', 'cache', 'path');
+      when(mockApi.getDirectoryPath(DirectoryType.applicationCache))
+          .thenReturn(applicationCachePath);
+
+      final String? path = await pathProvider.getApplicationCachePath();
+
+      expect(Directory(path!).existsSync(), isTrue);
+    });
+
     test('getDownloadsPath', () async {
       final PathProviderFoundation pathProvider = PathProviderFoundation();
       final String downloadsPath = p.join(testRoot.path, 'downloads', 'path');
diff --git a/packages/path_provider/path_provider_linux/CHANGELOG.md b/packages/path_provider/path_provider_linux/CHANGELOG.md
index 7b4f83d..09a9d94 100644
--- a/packages/path_provider/path_provider_linux/CHANGELOG.md
+++ b/packages/path_provider/path_provider_linux/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.2.0
+
+* Adds getApplicationCachePath() for storing app-specific cache files.
+
 ## 2.1.11
 
 * Removes obsolete null checks on non-nullable values.
diff --git a/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart
index 3bd644f..3353f56 100644
--- a/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart
+++ b/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart
@@ -36,6 +36,12 @@
     final String? result = await provider.getApplicationSupportPath();
     _verifySampleFile(result, 'applicationSupport');
   });
+
+  testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async {
+    final PathProviderLinux provider = PathProviderLinux();
+    final String? result = await provider.getApplicationCachePath();
+    _verifySampleFile(result, 'applicationCache');
+  });
 }
 
 /// Verify a file called [name] in [directoryPath] by recreating it with test
diff --git a/packages/path_provider/path_provider_linux/example/lib/main.dart b/packages/path_provider/path_provider_linux/example/lib/main.dart
index 254360c..3cbb691 100644
--- a/packages/path_provider/path_provider_linux/example/lib/main.dart
+++ b/packages/path_provider/path_provider_linux/example/lib/main.dart
@@ -23,6 +23,7 @@
   String? _tempDirectory = 'Unknown';
   String? _downloadsDirectory = 'Unknown';
   String? _appSupportDirectory = 'Unknown';
+  String? _appCacheDirectory = 'Unknown';
   String? _documentsDirectory = 'Unknown';
   final PathProviderLinux _provider = PathProviderLinux();
 
@@ -37,6 +38,7 @@
     String? tempDirectory;
     String? downloadsDirectory;
     String? appSupportDirectory;
+    String? appCacheDirectory;
     String? documentsDirectory;
     // Platform messages may fail, so we use a try/catch PlatformException.
     try {
@@ -61,6 +63,12 @@
     } on PlatformException {
       appSupportDirectory = 'Failed to get documents directory.';
     }
+
+    try {
+      appCacheDirectory = await _provider.getApplicationCachePath();
+    } on PlatformException {
+      appCacheDirectory = 'Failed to get cache directory.';
+    }
     // If the widget was removed from the tree while the asynchronous platform
     // message was in flight, we want to discard the reply rather than calling
     // setState to update our non-existent appearance.
@@ -72,6 +80,7 @@
       _tempDirectory = tempDirectory;
       _downloadsDirectory = downloadsDirectory;
       _appSupportDirectory = appSupportDirectory;
+      _appCacheDirectory = appCacheDirectory;
       _documentsDirectory = documentsDirectory;
     });
   }
@@ -90,6 +99,7 @@
               Text('Documents Directory: $_documentsDirectory\n'),
               Text('Downloads Directory: $_downloadsDirectory\n'),
               Text('Application Support Directory: $_appSupportDirectory\n'),
+              Text('Application Cache Directory: $_appCacheDirectory\n'),
             ],
           ),
         ),
diff --git a/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart b/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart
index 1544dce..5909711 100644
--- a/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart
+++ b/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart
@@ -72,6 +72,16 @@
   }
 
   @override
+  Future<String?> getApplicationCachePath() async {
+    final Directory directory =
+        Directory(path.join(xdg.cacheHome.path, await _getId()));
+    if (!directory.existsSync()) {
+      await directory.create(recursive: true);
+    }
+    return directory.path;
+  }
+
+  @override
   Future<String?> getDownloadsPath() {
     return Future<String?>.value(xdg.getUserDirectory('DOWNLOAD')?.path);
   }
diff --git a/packages/path_provider/path_provider_linux/pubspec.yaml b/packages/path_provider/path_provider_linux/pubspec.yaml
index a72228f..b1c3e7f 100644
--- a/packages/path_provider/path_provider_linux/pubspec.yaml
+++ b/packages/path_provider/path_provider_linux/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Linux implementation of the path_provider plugin
 repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_linux
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22
-version: 2.1.11
+version: 2.2.0
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
@@ -20,7 +20,7 @@
   flutter:
     sdk: flutter
   path: ^1.8.0
-  path_provider_platform_interface: ^2.0.0
+  path_provider_platform_interface: ^2.1.0
   xdg_directories: ">=0.2.0 <2.0.0"
 
 dev_dependencies:
diff --git a/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart b/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart
index 1f567c0..b5dfcce 100644
--- a/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart
+++ b/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart
@@ -57,6 +57,13 @@
     expect(await plugin.getApplicationDocumentsPath(), startsWith('/'));
   });
 
+  test('getApplicationCachePath', () async {
+    final PathProviderPlatform plugin = PathProviderLinux.private(
+        executableName: 'path_provider_linux_test_binary');
+    expect(await plugin.getApplicationCachePath(),
+        '${xdg.cacheHome.path}/path_provider_linux_test_binary');
+  });
+
   test('getDownloadsPath', () async {
     final PathProviderPlatform plugin = PathProviderPlatform.instance;
     expect(await plugin.getDownloadsPath(), startsWith('/'));
diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md
index 6011789..04a201f 100644
--- a/packages/path_provider/path_provider_windows/CHANGELOG.md
+++ b/packages/path_provider/path_provider_windows/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.2.0
+
+* Adds getApplicationCachePath() for storing app-specific cache files.
+
 ## 2.1.7
 
 * Adds compatibility with `win32` 5.x.
diff --git a/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart
index a828596..0e90022 100644
--- a/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart
+++ b/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart
@@ -28,6 +28,12 @@
     _verifySampleFile(result, 'applicationSupport');
   });
 
+  testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async {
+    final PathProviderWindows provider = PathProviderWindows();
+    final String? result = await provider.getApplicationCachePath();
+    _verifySampleFile(result, 'applicationCache');
+  });
+
   testWidgets('getDownloadsDirectory', (WidgetTester tester) async {
     final PathProviderWindows provider = PathProviderWindows();
     final String? result = await provider.getDownloadsPath();
diff --git a/packages/path_provider/path_provider_windows/example/lib/main.dart b/packages/path_provider/path_provider_windows/example/lib/main.dart
index e910732..53e46e5 100644
--- a/packages/path_provider/path_provider_windows/example/lib/main.dart
+++ b/packages/path_provider/path_provider_windows/example/lib/main.dart
@@ -24,6 +24,7 @@
   String? _downloadsDirectory = 'Unknown';
   String? _appSupportDirectory = 'Unknown';
   String? _documentsDirectory = 'Unknown';
+  String? _cacheDirectory = 'Unknown';
 
   @override
   void initState() {
@@ -37,6 +38,7 @@
     String? downloadsDirectory;
     String? appSupportDirectory;
     String? documentsDirectory;
+    String? cacheDirectory;
     final PathProviderWindows provider = PathProviderWindows();
 
     try {
@@ -62,11 +64,18 @@
       appSupportDirectory = 'Failed to get app support directory: $exception';
     }
 
+    try {
+      cacheDirectory = await provider.getApplicationCachePath();
+    } catch (exception) {
+      cacheDirectory = 'Failed to get cache directory: $exception';
+    }
+
     setState(() {
       _tempDirectory = tempDirectory;
       _downloadsDirectory = downloadsDirectory;
       _appSupportDirectory = appSupportDirectory;
       _documentsDirectory = documentsDirectory;
+      _cacheDirectory = cacheDirectory;
     });
   }
 
@@ -84,6 +93,7 @@
               Text('Documents Directory: $_documentsDirectory\n'),
               Text('Downloads Directory: $_downloadsDirectory\n'),
               Text('Application Support Directory: $_appSupportDirectory\n'),
+              Text('Cache Directory: $_cacheDirectory\n'),
             ],
           ),
         ),
diff --git a/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart b/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart
index 691d7a2..2faa599 100644
--- a/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart
+++ b/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart
@@ -114,31 +114,18 @@
   }
 
   @override
-  Future<String?> getApplicationSupportPath() async {
-    final String? appDataRoot =
-        await getPath(WindowsKnownFolder.RoamingAppData);
-    if (appDataRoot == null) {
-      return null;
-    }
-    final Directory directory = Directory(
-        path.join(appDataRoot, _getApplicationSpecificSubdirectory()));
-    // Ensure that the directory exists if possible, since it will on other
-    // platforms. If the name is longer than MAXPATH, creating will fail, so
-    // skip that step; it's up to the client to decide what to do with the path
-    // in that case (e.g., using a short path).
-    if (directory.path.length <= MAX_PATH) {
-      if (!directory.existsSync()) {
-        await directory.create(recursive: true);
-      }
-    }
-    return directory.path;
-  }
+  Future<String?> getApplicationSupportPath() =>
+      _createApplicationSubdirectory(WindowsKnownFolder.RoamingAppData);
 
   @override
   Future<String?> getApplicationDocumentsPath() =>
       getPath(WindowsKnownFolder.Documents);
 
   @override
+  Future<String?> getApplicationCachePath() =>
+      _createApplicationSubdirectory(WindowsKnownFolder.LocalAppData);
+
+  @override
   Future<String?> getDownloadsPath() => getPath(WindowsKnownFolder.Downloads);
 
   /// Retrieve any known folder from Windows.
@@ -256,4 +243,23 @@
     }
     return sanitized.isEmpty ? null : sanitized;
   }
+
+  Future<String?> _createApplicationSubdirectory(String folderId) async {
+    final String? baseDir = await getPath(folderId);
+    if (baseDir == null) {
+      return null;
+    }
+    final Directory directory =
+        Directory(path.join(baseDir, _getApplicationSpecificSubdirectory()));
+    // Ensure that the directory exists if possible, since it will on other
+    // platforms. If the name is longer than MAXPATH, creating will fail, so
+    // skip that step; it's up to the client to decide what to do with the path
+    // in that case (e.g., using a short path).
+    if (directory.path.length <= MAX_PATH) {
+      if (!directory.existsSync()) {
+        await directory.create(recursive: true);
+      }
+    }
+    return directory.path;
+  }
 }
diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml
index 4e00b93..8062aa5 100644
--- a/packages/path_provider/path_provider_windows/pubspec.yaml
+++ b/packages/path_provider/path_provider_windows/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Windows implementation of the path_provider plugin
 repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_windows
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22
-version: 2.1.7
+version: 2.2.0
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
@@ -20,7 +20,7 @@
   flutter:
     sdk: flutter
   path: ^1.8.0
-  path_provider_platform_interface: ^2.0.0
+  path_provider_platform_interface: ^2.1.0
   win32: ">=2.1.0 <6.0.0"
 
 dev_dependencies:
diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart
index 48e5640..dd8fead 100644
--- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart
+++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart
@@ -165,6 +165,20 @@
     expect(path, contains(r'Documents'));
   }, skip: !Platform.isWindows);
 
+  test('getApplicationCachePath', () async {
+    final PathProviderWindows pathProvider = PathProviderWindows();
+    pathProvider.versionInfoQuerier = FakeVersionInfoQuerier(<String, String>{
+      'CompanyName': 'A Company',
+      'ProductName': 'Amazing App',
+    }, encoding: encodingCP1252);
+    final String? path = await pathProvider.getApplicationCachePath();
+    expect(path, isNotNull);
+    if (path != null) {
+      expect(path, endsWith(r'AppData\Local\A Company\Amazing App'));
+      expect(Directory(path).existsSync(), isTrue);
+    }
+  }, skip: !Platform.isWindows);
+
   test('getDownloadsPath', () async {
     final PathProviderWindows pathProvider = PathProviderWindows();
     final String? path = await pathProvider.getDownloadsPath();