簡體   English   中英

Flutter:在外部存儲路徑上創建目錄 - 路徑提供程序 getExternalStorageDirectory()

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM