Flutter: 存储共享(存储访问框架API)权限在隐藏子目录中的文件上不起作用。

5
如何实现在使用 Flutter/Dart 中的 SAF 后列出所有位于隐藏子目录(即文件夹名以'.'开头,如"(.media)")中的所有文件(例如媒体)?我已经使用了 ACTION_OPEN_DOCUMENT_TREE 来让用户选择一个文件夹(所以避免使用 MANAGE_EXTERNAL_STORAGE),但无法查看即读取文件夹内隐藏子目录中的文件。 授予权限的文件夹为 media: storage/emulated/0/internal storage/Android/media/matrix/.new/ 问题: 无法列出子文件夹.new中的所有文件。
与此同时...
可以访问matrix子文件夹中的文件(非文件夹)。
此外,如果我将子文件夹".new"的名称更改为new,我就能够列出该文件夹中的所有文件。
我正在使用 Flutter/Dart。对于共享存储权限,我已经使用了Kotlin自定义本地代码。 Kotlin 代码:
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {

        GeneratedPluginRegistrant.registerWith(flutterEngine)

        MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)

                .setMethodCallHandler{ call: MethodCall, result: MethodChannel.Result -> run {
                                if (call.method.contentEquals("getSAFPermission")) {
                                    if (VERSION.SDK_INT > 29) {
                                        openDirectory(_initialPickerDirPath) //@String path
                                    } else {
                                        result.success(true)
                                    }
                                }
                            }
                        }
}

private fun openDirectory(pickerInitialUri: String) { 
           val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
            putExtra(DocumentsContract.EXTRA_INITIAL_URI,DocumentsContract.buildDocumentUri(
                "com.android.externalstorage.documents", pickerInitialUri)
                }

            startActivityForResult(intent, SAF_PERMISSION_CODE)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
          if (requestCode == SAF_PERMISSION_CODE && resultCode == Activity.RESULT_OK) {

             val contentResolver = applicationContext.contentResolver

             val takeFlags: Int = (Intent.FLAG_GRANT_READ_URI_PERMISSION or 
                                   Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

             contentResolver.takePersistableUriPermission(treeUri, takeFlags)
          }
}

Flutter端 | Dart代码:

_loadimage() async {
    // path: '/storage/emulated/0/Android/media/neo/matrix/.new'
    if (Directory(_neoDir.path).existsSync()) { // _neoDir: Directory
      imageList += _neodDir
          .listSync()
          .map((item) => item.path)
          .where((item) => item.endsWith(".jpg"))
          .toList(growable: false); // imageList appear empty list
    }
}

尝试的方法:

1. 在本地Kotlin端,使用CachingDocumentFile获取子文档文件,遍历所有DocumentFile,将Uri列表存储在字符串中并将其发送回Flutter端。在dart端(Flutter)渲染图片File.fromUri()。

参考 - > https://github.com/android/storage-samples/tree/main/ActionOpenDocumentTree

2. 使用这些人的解决方案。 参考 > https://github.com/lakscastro/shared-storage/issues/10#issuecomment-1025801272

我感觉我没有获得子文档文件的读取权限。

注意:截至2022年1月31日,没有任何Flutter包可以帮助实现此功能。已尝试给定的包

shared_storage,> https://pub.dev/packages/shared_storage

file_picker,> https://pub.dev/packages/file_picker

filesystem_picker,> https://pub.dev/packages/filesystem_picker

FileManager已停用的类

非常感谢任何帮助。


看起来你使用了经典的文件路径来列出该文件夹中的内容。这样做是不行的,因为只有使用 SAF 才能获得读/写该文件夹及其子文件夹的权限。 - blackapps
@blackapps稍微修改了问题陈述。 - jvoltci
您没有告诉用户选择了哪个文件夹。 - blackapps
我已经在那里提到了它。在这行代码中Permission Granted Directory: .../internal storage/Android/media,用户选择了这个文件夹。'/storage/emulated/0/Android/media' - jvoltci
你提到得太晚了。你本可以提到“一个文件夹”。你提到了一个经典的文件系统路径。但在onActivityResult()中,你会得到所选文件夹的内容方案URI。请告诉我这个内容方案是什么样子的。 - blackapps
显示剩余7条评论
1个回答

1

我终于找到了一个可以解决SAF问题的包!以下是链接访问


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接