Flutter: Shared Storage (Storage Access Framework API) Permission for files inside hidden sub-directory not working

438

Finally I Found a package that can solve SAF issue ! Here is a link Visit

Share:
438
jvoltci
Author by

jvoltci

AI Researcher at Vehement Inc.

Updated on January 03, 2023

Comments

  • jvoltci
    jvoltci over 1 year

    How to achieve to listing all files (e.g. Media) inside hidden subdirectory i.e. folder name start with '.' e.g. "(.media)" after using SAF in Flutter/Dart?

    I have used ACTION_OPEN_DOCUMENT_TREE to let the user choose a folder [So to avoid using MANAGE_EXTERNAL_STORAGE] but couldn't view i.e. Read the files inside the hidden subdirectory of the folder.

    Permission Granted folder is media:

    storage/emulated/0/internal storage/Android/media/matrix/.new/

    Issue:

    Not able to list all files inside subfolder .new

    At the same time...

    Able to access files (not folder) inside matrix subfolder

    Also if I rename the subfolder ".new" to new I am able to list all the files inside that folder

    I am using flutter/dart. For Shared Storage Permission, I have used Kotlin custom native code.

    Kotlin Code:

    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 side | Dart Code:

    _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
        }
    }
    

    Tried method:

    1. In the native Kotlin side, fetched child document files using CachingDocumentFile and iterating over all DocumentFile and storing Uri list in string and sending it back to Flutter side. Rendering image File.fromUri() at dart side (Flutter)

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

    2. Used the solution of these folks. Refer > https://github.com/lakscastro/shared-storage/issues/10#issuecomment-1025801272

    I feel I am not getting the read permission for child document files.

    Note:- As of 31-Jan-2022 No flutter package helps to achieve this functionality. Tried given packages :

    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 (discontinued class)

    Any help would be greatly appreciated.

    • jvoltci
      jvoltci about 2 years
      Using Shared Storage API I have asked the user to give permission for the given directory thus consent to use this folder. Hope it clears your doubt!
    • blackapps
      blackapps about 2 years
      You could have told that you used ACTION_OPEN_DOCUMENT_TREE to let the user choose a folder. Which folder to begin with?
    • blackapps
      blackapps about 2 years
      It looks that you use a classic file path to that folder to make listings. That will not go as the obtained permission to read/write the folder and subfolders is only when using SAF to do so.
    • blackapps
      blackapps about 2 years
      And further we can nowhere in your post read what you try to achieve.
    • jvoltci
      jvoltci about 2 years
      @blackapps can you elaborate this That will not go as the obtained permission to read/write the folder and subfolders is only when using SAF to do so.? Because I have access to files as well from adjacent subdirectory after SAF.
    • jvoltci
      jvoltci about 2 years
      @blackapps Edited the Problem statement a bit.
    • blackapps
      blackapps about 2 years
      You did not tell which folder the user choosed.
    • jvoltci
      jvoltci about 2 years
      I have mentioned it there. In this line Permission Granted Directory: .../internal storage/Android/media User has chosen this folder. '/storage/emulated/0/Android/media'
    • blackapps
      blackapps about 2 years
      You mentioned it too late. Instead of a folder you could have mentioned it. You mention a classic file system path. But in onActivityResult() you would get a content scheme uri for the chosen folder. Please tell how that content scheme looks like
    • blackapps
      blackapps about 2 years
      Once you got a content scheme for the chosen folder you should use that content scheme. It does not make sense to use a file system path like you do in // path: '/storage/emulated/0/Android/media/neo/matrix/.new
    • jvoltci
      jvoltci about 2 years
      Again you missed issue - Not able to list all files inside this Directory: .../internal storage/Android/media/neo/matrix/.new At the same time... Able to access files inside following dir: .../internal storage/Android/media/neo/matrix Also if I rename the folder ".new" to new I am able to list all the files inside that directory It is working perfectly using the classic path with the Directory(path: "some/path") class from dart: io I request you to please go through the Problem statement completely.
    • Ankit Parmar
      Ankit Parmar about 2 years
      @Jai I am facing the same problem unable to read Statues from hidden folder for this Path => /storage/emulated/0/Android/Media/com.whatsapp/WhatsApp/Medi‌​a/.Statuses/ but when i Remove (.)dot from Statues folder I can read all the files from the Statues folder using this method. Directory dir = Directory( '/storage/emulated/0/Android/Media/com.whatsapp/WhatsApp/Med‌​ia/Statuses/'); List<FileSystemEntity> allFiles = dir.listSync(); even without using SAF Api just took this permission from user Permission.storage.request() using permission_handler package