即使在授予存储权限后,在 Samsung phone 上创建目录仍被拒绝

Create directory denied on Samsung phone even after Storage Permissions are granted

在启动我的应用程序时,我在存储中创建了一个文件夹。为此,我请求 initState() 内的权限。只有当它完成时,目录检查才会继续。

@override
  void initState(){
    super.initState();
    easyDir = Directory(widget.folderPath);
    getPermissionStatus().whenComplete(() {
      setState(() {
        //never call async operations in setState, do it in a function call.
        directoryCheck();
      });
    });
  }

folderPathpermission_handler 包生成。我的 phone 是 /storage/emulated/0/Documents/easyFolder

  //check if directory exists, create if not.
  Future<void> directoryCheck() async {
    // using awaits fixed my problem of setstate being called before
    // directory was created.. and calling setState at end
    exists = await easyDir.exists();
    if (!exists){
      await new Directory(widget.folderPath).create(recursive: true);
      exists = true;
    }
    setState(() {

    });

  }

Future<void> getPermissionStatus() async {
    _status = await Permission.storage.status;
    // if permission is not granted yet, request it and update _status
    if (_status != PermissionStatus.granted){
      await Permission.storage.request();
      _status = await Permission.storage.status;
    }
  }

这在模拟器上按预期工作。该应用程序在启动时请求权限,等待它完成,并在允许时创建目录。

但是当安装在我的三星 phone 甚至朋友 phone(三星)上时,由于权限被拒绝,即使在授予权限后也无法创建文件夹。

这是我在三星 phone 上收到的错误消息:

E/flutter (23275): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: FileSystemException: Creation failed, path = '/storage/emulated/0/Documents' (OS Error: Permission denied, errno = 13)

我在应用程序启动时明确授予了权限。更重要的是,当我进入我的应用程序的 appinfo 时,它显示已授予 Storage 权限。

我尝试在华为和小米 phones 上安装它,两者都按预期工作。

我做错了什么?

这是我的 AndroindManifest

中的许可行
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>

如果有帮助,这里是错误堆栈:

E/flutter (23275): #0      _Directory.create.<anonymous closure> (dart:io/directory_impl.dart:124:11)
E/flutter (23275): #1      _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter (23275): #2      _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter (23275): #3      _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
E/flutter (23275): #4      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
E/flutter (23275): #5      Future._propagateToListeners (dart:async/future_impl.dart:711:32)
E/flutter (23275): #6      Future._completeWithValue (dart:async/future_impl.dart:526:5)
E/flutter (23275): #7      Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:556:7)
E/flutter (23275): #8      _rootRun (dart:async/zone.dart:1184:13)
E/flutter (23275): #9      _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (23275): #10     _CustomZone.runGuarded (dart:async/zone.dart:979:7)
E/flutter (23275): #11     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1019:23)
E/flutter (23275): #12     _microtaskLoop (dart:async/schedule_microtask.dart:43:21)
E/flutter (23275): #13     _startMicrotaskLoop (dart:async/schedule_microtask.dart:52:5)
E/flutter (23275): 

我发现代码在 Android 11 中运行良好但在 10 中运行良好很奇怪,因为新的范围存储,写入权限在 Android 10 (Q) 及更高版本

中应该会失败

现在在您的清单中尝试此操作,以选择退出 Android 10 中的范围存储(这在 Android 11 中不会执行任何操作),

<manifest ... >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<!-- This attribute is "false" by default on apps targeting
     Android 10 or higher. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Caution: After you update your app to target Android 11 (API level 30), the system ignores the requestLegacyExternalStorage attribute when your app is running on Android 11 devices, so your app must be ready to support scoped storage and to migrate app data for users on those devices.

More info about Scoped Storage here

现在有一些问题可以帮助您解决这个问题:

the folderPath is produced by the permission_handler

我不记得请求权限时 permission_handler 到 return 的路径,你能详细说明你是如何获得 widget.folderPath 的吗?

The Emulator is running Android version 11. While my Samsung phone is on Android version 10

华为和小米设备怎么样,也是运行Android10吗?

gradle 中的 compileSdkVersion/targetSdkVersion 或 AndroidManifest 中的 targetSdk 是什么?