![](/img/trans.png)
[英]Nexus 6 Environment.getExternalStorageDirectory() cannot create directory External storage
[英]Flutter : Create directory on external storage path - path provider getExternalStorageDirectory()
我正在创建一个 flutter 应用程序,我想在其中下载图像并将其存储到外部存储(不是文档目录),以便任何照片库应用程序都可以查看它。 我正在使用以下代码创建一个目录
var dir = await getExternalStorageDirectory();
if(!Directory("${dir.path}/myapp").existsSync()){
Directory("${dir.path}/myapp").createSync(recursive: true);
}
它给我以下错误:
FileSystemException: Creation failed, path = '/storage/emulated/0/myapp' (OS Error: Permission denied, errno = 13)
我已经在清单文件中设置了权限,并使用以下代码获得运行时权限
List<Permissions> permissions = await Permission.getPermissionStatus([PermissionName.Storage]);
permissions.forEach((p) async {
if(p.permissionStatus != PermissionStatus.allow){
final res = await Permission.requestSinglePermission(PermissionName.Storage);
print(res);
}
});
我已经在设置中验证了该应用程序已获得许可,也正如此处某些答案所建议的那样,我还尝试手动授予设置应用程序的许可,但没有用。
下面的代码在我的应用程序中运行良好,可以使用 url 将图像下载到外部存储
Future<bool> downloadImage(String url) async {
await new Future.delayed(new Duration(seconds: 1));
bool checkResult =
await SimplePermissions.checkPermission(Permission.WriteExternalStorage);
if (!checkResult) {
var status = await SimplePermissions.requestPermission(
Permission.WriteExternalStorage);
if (status == PermissionStatus.authorized) {
var res = await saveImage(url);
return res != null;
}
} else {
var res = await saveImage(url);
return res != null;
}
return false;
}
Future<Io.File> saveImage(String url) async {
try {
final file = await getImageFromNetwork(url);
var dir = await getExternalStorageDirectory();
var testdir =
await new Io.Directory('${dir.path}/iLearn').create(recursive: true);
IM.Image image = IM.decodeImage(file.readAsBytesSync());
return new Io.File(
'${testdir.path}/${DateTime.now().toUtc().toIso8601String()}.png')
..writeAsBytesSync(IM.encodePng(image));
} catch (e) {
print(e);
return null;
}
}
Future<Io.File> getImageFromNetwork(String url) async {
var cacheManager = await CacheManager.getInstance();
Io.File file = await cacheManager.getFile(url);
return file;
}
命名空间
import 'dart:io' as Io;
import 'package:image/image.dart' as IM;
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:path_provider/path_provider.dart';
import 'package:simple_permissions/simple_permissions.dart';
希望能帮助到你
您需要在使用 getExternalStorageDirectory 保存文件之前请求权限。
将此添加到 Androidmanifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
然后使用permission_handler包获取Storage权限:
https://pub.dev/packages/permission_handler
如果您在模拟器中运行,则 getExternalStorageDirectory 返回:
/storage/emulated/0/Android/data/com.example.myapp/files/
如果您只需要外部目录在其下创建目录,则只需使用:
/storage/emulated/0/
您可以在此文件夹下创建一个目录,以便他们的用户可以打开文件。
对于 Android 11 及更高版本,android 更改其策略,以便您在 AndroidManifest.. 中添加权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
并且还在 <application ......
android:requestLegacyExternalStorage="true"
android:preserveLegacyExternalStorage="true"
这是一个可操作的 100% Dart 代码,使事情变得更容易:
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:path/path.dart' as Path;
import 'package:path_provider/path_provider.dart';
///getExternalStoragePublicDirectory
enum extPublicDir {
Music,
PodCasts,
Ringtones,
Alarms,
Notifications,
Pictures,
Movies,
Download,
DCIM,
Documents,
Screenshots,
Audiobooks,
}
/// use in loop or without:
/// generation loop of a creation of the same directory in a list
/// public or shared folders by the Android system
/*
for (var ext in extPublicDir.values) {
ExtStorage.createFolderInPublicDir(
type: ext, //or without loop : extPublicDir.Download,
folderName: "folderName", // folder or folder/subFolder/... to create
);
}
*/
/// provided the ability to create folders and files within folders
/// public or shared from the Android system
///
/// /storage/emulated/0/Audiobooks
/// /storage/emulated/0/PodCasts
/// /storage/emulated/0/Ringtones
/// /storage/emulated/0/Alarms
/// /storage/emulated/0/Notifications
/// /storage/emulated/0/Pictures
/// /storage/emulated/0/Movies
/// storage/emulated/0/Download
/// /storage/emulated/0/DCIM
/// /storage/emulated/0/Documents
/// /storage/emulated/0/Screenshots //Screenshots dropping ?
/// /storage/emulated/0/Music/
class ExtStorage {
//According to path_provider
static Future<String> get _directoryPathESD async {
var directory = await getExternalStorageDirectory();
if (directory != null) {
log('directory:${directory.path}');
return directory.path;
}
log('_directoryPathESD==null');
return '';
}
/// create or not, but above all returns the created folder in a public folder
/// official, folderName = '', only return the public folder: useful for
/// manage a file at its root
static Future<String> createFolderInPublicDir({
required extPublicDir type,
required String folderName,
}) async {
var _appDocDir = await _directoryPathESD;
log("createFolderInPublicDir:_appDocDir:${_appDocDir.toString()}");
var values = _appDocDir.split("${Platform.pathSeparator}");
values.forEach(print);
var dim = values.length - 4; // Android/Data/package.name/files
_appDocDir = "";
for (var i = 0; i < dim; i++) {
_appDocDir += values[i];
_appDocDir += "${Platform.pathSeparator}";
}
_appDocDir += "${type.toString().split('.').last}${Platform.pathSeparator}";
_appDocDir += folderName;
log("createFolderInPublicDir:_appDocDir:$_appDocDir");
if (await Directory(_appDocDir).exists()) {
log("createFolderInPublicDir:reTaken:$_appDocDir");
return _appDocDir;
} else {
log("createFolderInPublicDir:toCreate:$_appDocDir");
//if folder not exists create folder and then return its path
final _appDocDirNewFolder =
await Directory(_appDocDir).create(recursive: true);
final pathNorma = Path.normalize(_appDocDirNewFolder.path);
log("createFolderInPublicDir:ToCreate:pathNorma:$pathNorma");
return pathNorma;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.