blob: 8f9e46be017bf8bfb5dda790c1ec04b53007f2c6 [file] [log] [blame]
// 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: public_member_api_docs
import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
import 'package:flutter/cupertino.dart';
import 'file_selector_api.g.dart';
import 'types/native_illegal_argument_exception.dart';
/// An implementation of [FileSelectorPlatform] for Android.
class FileSelectorAndroid extends FileSelectorPlatform {
FileSelectorAndroid({@visibleForTesting FileSelectorApi? api})
: _api = api ?? FileSelectorApi();
final FileSelectorApi _api;
/// Registers this class as the implementation of the file_selector platform interface.
static void registerWith() {
FileSelectorPlatform.instance = FileSelectorAndroid();
}
@override
Future<XFile?> openFile({
List<XTypeGroup>? acceptedTypeGroups,
String? initialDirectory,
String? confirmButtonText,
}) async {
final FileResponse? file = await _api.openFile(
initialDirectory,
_fileTypesFromTypeGroups(acceptedTypeGroups),
);
return file == null ? null : _xFileFromFileResponse(file);
}
@override
Future<List<XFile>> openFiles({
List<XTypeGroup>? acceptedTypeGroups,
String? initialDirectory,
String? confirmButtonText,
}) async {
final List<FileResponse> files = await _api.openFiles(
initialDirectory,
_fileTypesFromTypeGroups(acceptedTypeGroups),
);
return files.map<XFile>(_xFileFromFileResponse).toList();
}
@override
Future<String?> getDirectoryPath({
String? initialDirectory,
String? confirmButtonText,
}) async {
return _api.getDirectoryPath(initialDirectory);
}
XFile _xFileFromFileResponse(FileResponse file) {
if (file.fileSelectorNativeException != null) {
_resolveErrorCodeAndMaybeThrow(file.fileSelectorNativeException!);
}
return XFile.fromData(
file.bytes,
// Note: The name parameter is not used by XFile. The XFile.name returns
// the extracted file name from XFile.path.
name: file.name,
length: file.size,
mimeType: file.mimeType,
path: file.path,
);
}
FileTypes _fileTypesFromTypeGroups(List<XTypeGroup>? typeGroups) {
if (typeGroups == null) {
return FileTypes(extensions: <String>[], mimeTypes: <String>[]);
}
final Set<String> mimeTypes = <String>{};
final Set<String> extensions = <String>{};
for (final XTypeGroup group in typeGroups) {
if (!group.allowsAny &&
group.mimeTypes == null &&
group.extensions == null) {
throw ArgumentError(
'Provided type group $group does not allow all files, but does not '
'set any of the Android supported filter categories. At least one of '
'"extensions" or "mimeTypes" must be non-empty for Android.',
);
}
mimeTypes.addAll(group.mimeTypes ?? <String>{});
extensions.addAll(group.extensions ?? <String>{});
}
return FileTypes(
mimeTypes: mimeTypes.toList(),
extensions: extensions.toList(),
);
}
/// Translates a [FileSelectorExceptionCode] to its corresponding error and
/// handles throwing.
void _resolveErrorCodeAndMaybeThrow(
FileSelectorNativeException fileSelectorNativeException) {
switch (fileSelectorNativeException.fileSelectorExceptionCode) {
case FileSelectorExceptionCode.illegalArgumentException:
throw NativeIllegalArgumentException(
fileSelectorNativeException.message);
case (FileSelectorExceptionCode.illegalStateException ||
FileSelectorExceptionCode.ioException ||
FileSelectorExceptionCode.securityException):
// unused for now
}
}
}