Skip to content

Commit

Permalink
[path_provider] Add getApplicationCachePath() - implementations (#4619)
Browse files Browse the repository at this point in the history
Platform implementations split out from #4483.
  • Loading branch information
jpnurmi authored Aug 3, 2023
1 parent 051d20a commit 9323e33
Show file tree
Hide file tree
Showing 35 changed files with 287 additions and 35 deletions.
3 changes: 2 additions & 1 deletion packages/path_provider/path_provider_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -84,6 +84,9 @@ public interface PathProviderApi {
@Nullable
String getApplicationDocumentsPath();

@Nullable
String getApplicationCachePath();

@Nullable
String getExternalStoragePath();

Expand Down Expand Up @@ -176,6 +179,31 @@ static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable PathProvid
channel.setMessageHandler(null);
}
}
{
BinaryMessenger.TaskQueue taskQueue = binaryMessenger.makeBackgroundTaskQueue();
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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
return getPathProviderApplicationDocumentsDirectory();
}

@Override
public @Nullable String getApplicationCachePath() {
return context.getCacheDir().getPath();
}

@Override
public @Nullable String getExternalStoragePath() {
return getPathProviderStorageDirectory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ void main() {
_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(),
Expand Down
16 changes: 16 additions & 0 deletions packages/path_provider/path_provider_android/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class _MyHomePageState extends State<MyHomePage> {
Future<String?>? _tempDirectory;
Future<String?>? _appSupportDirectory;
Future<String?>? _appDocumentsDirectory;
Future<String?>? _appCacheDirectory;
Future<String?>? _externalDocumentsDirectory;
Future<List<String>?>? _externalStorageDirectories;
Future<List<String>?>? _externalCacheDirectories;
Expand Down Expand Up @@ -92,6 +93,12 @@ class _MyHomePageState extends State<MyHomePage> {
});
}

void _requestAppCacheDirectory() {
setState(() {
_appCacheDirectory = provider.getApplicationCachePath();
});
}

void _requestExternalStorageDirectory() {
setState(() {
_externalDocumentsDirectory = provider.getExternalStoragePath();
Expand Down Expand Up @@ -147,6 +154,15 @@ class _MyHomePageState extends State<MyHomePage> {
),
FutureBuilder<String?>(
future: _appSupportDirectory, builder: _buildDirectory),
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ dependencies:
# 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:
Expand Down
23 changes: 22 additions & 1 deletion packages/path_provider/path_provider_android/lib/messages.g.dart
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -98,6 +98,27 @@ class PathProviderApi {
}
}

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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class PathProviderAndroid extends PathProviderPlatform {
return _api.getApplicationDocumentsPath();
}

@override
Future<String?> getApplicationCachePath() {
return _api.getApplicationCachePath();
}

@override
Future<String?> getExternalStoragePath() {
return _api.getExternalStoragePath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ abstract class PathProviderApi {
@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();
Expand Down
4 changes: 2 additions & 2 deletions packages/path_provider/path_provider_android/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: path_provider_android
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"
Expand All @@ -20,7 +20,7 @@ flutter:
dependencies:
flutter:
sdk: flutter
path_provider_platform_interface: ^2.0.1
path_provider_platform_interface: ^2.1.0

dev_dependencies:
flutter_test:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -24,6 +24,8 @@ abstract class TestPathProviderApi {

String? getApplicationDocumentsPath();

String? getApplicationCachePath();

String? getExternalStoragePath();

List<String?> getExternalCachePaths();
Expand Down Expand Up @@ -84,6 +86,23 @@ abstract class TestPathProviderApi {
});
}
}
{
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const String kTemporaryPath = 'temporaryPath';
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';
Expand All @@ -23,6 +24,9 @@ class _Api implements TestPathProviderApi {
@override
String? getApplicationSupportPath() => kApplicationSupportPath;

@override
String? getApplicationCachePath() => kApplicationCachePath;

@override
List<String?> getExternalCachePaths() => <String>[kExternalCachePaths];

Expand Down Expand Up @@ -58,6 +62,11 @@ void main() {
expect(path, kApplicationSupportPath);
});

test('getApplicationCachePath', () async {
final String? path = await pathProvider.getApplicationCachePath();
expect(path, kApplicationCachePath);
});

test('getLibraryPath fails', () async {
try {
await pathProvider.getLibraryPath();
Expand Down
4 changes: 4 additions & 0 deletions packages/path_provider/path_provider_foundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ public class PathProviderPlugin: NSObject, FlutterPlugin, PathProviderApi {
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
Expand All @@ -49,6 +49,8 @@ public class PathProviderPlugin: NSObject, FlutterPlugin, PathProviderApi {
/// 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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enum DirectoryType: Int {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ void main() {
_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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class _MyAppState extends State<MyApp> {
String? _appSupportDirectory = 'Unknown';
String? _documentsDirectory = 'Unknown';
String? _containerDirectory = 'Unknown';
String? _cacheDirectory = 'Unknown';

@override
void initState() {
Expand All @@ -42,6 +43,7 @@ class _MyAppState extends State<MyApp> {
String? libraryDirectory;
String? documentsDirectory;
String? containerDirectory;
String? cacheDirectory;
final PathProviderPlatform provider = PathProviderPlatform.instance;
final PathProviderFoundation providerFoundation = PathProviderFoundation();

Expand Down Expand Up @@ -82,13 +84,20 @@ class _MyAppState extends State<MyApp> {
'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;
_libraryDirectory = libraryDirectory;
_appSupportDirectory = appSupportDirectory;
_documentsDirectory = documentsDirectory;
_containerDirectory = containerDirectory;
_cacheDirectory = cacheDirectory;
});
}

Expand All @@ -108,6 +117,7 @@ class _MyAppState extends State<MyApp> {
Text('Library Directory: $_libraryDirectory\n'),
Text('Application Support Directory: $_appSupportDirectory\n'),
Text('App Group Container Directory: $_containerDirectory\n'),
Text('Cache Directory: $_cacheDirectory\n'),
],
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ dependencies:
# 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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ enum DirectoryType {
downloads,
library,
temp,
applicationCache,
}

class PathProviderApi {
Expand Down
Loading

0 comments on commit 9323e33

Please sign in to comment.