Search Unity

Simple File Browser [Open Source]

Discussion in 'Assets and Asset Store' started by yasirkula, Nov 19, 2016.

  1. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You can handle files inside Application.persistentDataPath programmatically with File and Directory APIs, you don't need to use file browser in this case.
     
  2. chgeorgiadis

    chgeorgiadis

    Joined:
    Jan 30, 2018
    Posts:
    51
    I would like to save to another file from peristant path. Like the example before. What i mean : is that possible to change the path (i.e. to /Download/) to previous example without using the dialog and save the file there? Can you please make this function as an example?
     
  3. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Handling files without using file browser isn't related to my asset so I'd recommend you to ask these questions in the Scripting section of this forum the next time. If you have the path of a file in persistentDataPath and you want to copy it to "/Download/", then you can call:

    string downloadsFilePath = Path.Combine("/Download/", Path.GetFileName(filePath));
    File.Copy(filePath, downloadsFilePath, true);
     
  4. chgeorgiadis

    chgeorgiadis

    Joined:
    Jan 30, 2018
    Posts:
    51
    Thank you very much! I will search the corresponding call for Android.
     
  5. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    On Android, copying a file to a hardcoded path like /storage/mnt/0/SomeFolder isn't recommended because the path might be different on other devices and also, Android 11 and later forces you to use Storage Access Framework which limits File/Directory API access to most folders on the device (you can access persistentDataPath and temporaryCachePath just fine, though).

    SimpleFileBrowser and its FileBrowserHelpers functions are compatible with Storage Access Framework so I'd recommend you to use it if Android is a target platform. At least, you can ask the user for a directory once and then cache the returned path to reuse it later (without displaying file dialog) (until the directory no longer exists).
     
  6. chgeorgiadis

    chgeorgiadis

    Joined:
    Jan 30, 2018
    Posts:
    51
    So actually SimpleFileBrowser is compatible with Android11! :) Thank you! I am searching how to find the right functions for copy/paste files. Thank you again!! Sorry for having so many questions.
     
    yasirkula likes this.
  7. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You're welcome! You can use
    FileBrowserHelpers.CopyFile
    but you can't pass "/storage/mnt/0/SomeFolder" to it, the path must come from SimpleFileBrowser or a FileBrowserHelpers function like
    FileBrowserHelpers.CreateFileInDirectory
    .
     
  8. chgeorgiadis

    chgeorgiadis

    Joined:
    Jan 30, 2018
    Posts:
    51
    So.. is there a possible "combination" from (passing and) copying from persistentDataPath to another /Download folder?

    Something like that?
    string downloadsFilePath = Path.Combine(FileBrowserHelpers.CreateFileInDirectory("/Download/", filePath));
    Debug.Log("is almost copied");
    FileBrowserHelpers.CopyFile(Application.persistentDataPath, downloadsFilePath);
     
  9. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Your logic is correct, you first need to call CreateFileInDirectory and then pass it to CopyFile. However, "/Download/" must be the path of the directory returned by SimpleFileBrowser, you mustn't use a hardcoded path here. On Android 11+, such file paths are no longer supported, so you have to use SimpleFileBrowser's returned path. Also Path.Combine should be omitted since CreateFileInDirectory does the same thing. You can't pass persistentDataPath itself to CopyFile because it's not a file, it's a directory. You need to pass the path of a file in persistentDataPath or temporaryCachePath.
     
  10. chgeorgiadis

    chgeorgiadis

    Joined:
    Jan 30, 2018
    Posts:
    51
    So the first line is wrong?

    string destinationFilePath = FileBrowserHelpers.CreateFileInDirectory("/Download/something/", filePath);
    string savedFilePath = Path.Combine(Application.persistentDataPath, filePath)
    FileBrowserHelpers.CopyFile(savedFilePath, destinationFilePath);

    But how can i take a specific path without using showdialog?
     
  11. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Quoting myself:
     
  12. mawejjenikolas

    mawejjenikolas

    Joined:
    Nov 11, 2020
    Posts:
    4
    Hello, Thank you for this useful asset, I have been using to load songs path from phone storage, keep the path and when the user clicked the path the music plays. This was working well when I was building with android Target API 29. But when I build with API 30+, it doesn't work. The file browser opens in app folder and can't even load files from other folders(Downloads...etc). however when a new folder is created and I put music in it, it loads the files path with weird strings and when clicked nothing plays.
    I put the screen shots taken on the same phone and app but with different target APIs. API 29 show internal and external drives and can pick and play the music , API 30+ opens in app folder and can't play the music.
    script:
     

    Attached Files:

  13. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Hi, API 30+ uses Storage Access Framework which is why you're seeing weird strings. If the music player expects a raw filepath, you can copy the selected file to Application.temporaryCachePath via
    FileBrowserHelpers.CopyFile(pathReturnedByFileBrowser, rawFilepathInCachePath);
     
    mawejjenikolas likes this.
  14. ChloeGue

    ChloeGue

    Joined:
    May 11, 2019
    Posts:
    11
    Hello!
    I am using your plugin for upload GLB into our application. However, for certain Android Device I have this error :

    DirectoryNotFoundException
    Could not find a part of the path "/content:/com.android.externalstorage.documents/tree/primary%3ADocuments%2FGLB/document/primary%3ADocuments%2FGLB%2FTheJenningsDog.glb".

    Indeed, if you look at the URL, the encoding is not correct and transformed the "/" into "%3A" => Have you already get this issue?

    I don't really know how to fix this issue since I am getting this URL error directly from
    FileBrowser.ShowLoadDialog(OnSuccessLoad, OnCancel, FileBrowser.PickMode.Files);
    getting the path from OnSuccessLoad.
    I could fix manually the path then, but maybe you have a better way to solve this issue?

    Thanks a lot for your reply ^^
    Have a nice day,
    C.
     
  15. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    "%3A" is expected but the weird thing is, "/content:/" should've been "content://". Are you modifying the returned path in any way (string modification, Path.Combine, etc.) in OnSuccessLoad?
     
    Last edited: May 2, 2022
  16. ChloeGue

    ChloeGue

    Joined:
    May 11, 2019
    Posts:
    11
    Hi, thanks for quick reply!
    Nope, I don't do anything particular:

    Code (CSharp):
    1.     public void OnSuccessLoad(string[] paths)
    2.     {
    3.         Debug.Log("File Browser Success ! " + paths[0]);
    4.  
    5.         foreach (string str in paths)
    6.             Debug.Log("file = " + str);
    7.  
    8.         MoveImage(paths[0]);
    9.     }
    That's definitly strange, no?

    Another question : using it on iOS, it opened the file browser, but obviously I have an UnathorizedEx:

    [B]UnauthorizedAccessException[/B]
    Access to the path '/private/var/mobile/Containers/Data/Application/7CD819C5-9FEA-4E81-954A-C8BC85BAE80B/SystemData' is denied.


    I know that iOS is blocking access by default, but I guess there is a way to ask for permission and then be granted to explore files, no? Do you have an idea about that?

    Thanks a lot!
    C.
     
  17. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Can I see MoveImage's implementation?
     
  18. ChloeGue

    ChloeGue

    Joined:
    May 11, 2019
    Posts:
    11
    Sure ! Here you go:

    Code (CSharp):
    1.     virtual public void MoveImage(string imagePath)
    2.     {
    3.         if (imagePath == "")
    4.             return;
    5.  
    6.         string destinationPath = GetDestinationPath(imagePath);
    7.  
    8.         Debug.Log("Moving " + imagePath + " to " + destinationPath);
    9.         File.Copy(imagePath, destinationPath, true);
    10.         Debug.Log("Image downloaded at : " + destinationPath);
    11.         OnFileDownloaded(destinationPath);
    12.     }
     
  19. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Can I see GetDestinationPath's implementation? And what does the "
    Debug.Log("file = " + str);
    " log output?
     
  20. ChloeGue

    ChloeGue

    Joined:
    May 11, 2019
    Posts:
    11
    Thanks, here is the implementation:
    Code (CSharp):
    1.         public string GetDestinationPath(string originalPath)
    2.         {
    3.             string fileName = Path.GetFileNameWithoutExtension(originalPath);
    4.             string result = Application.temporaryCachePath + "/" + fileName + "_" + ArtDataToSubmit.art.art_type + m_currentArtPictureID + Path.GetExtension(originalPath);
    5.             return result;
    6.         }
    However, the path already contains "content://" BEFORE calling MoveImage, so I don't think it is gonna help.

    Here is my log:

    unity.logger Opening File Browser Info 18:54:59
    unity.logger File Browser Success ! content://com.android.externalstorage.documents/tree/primary%3ADocuments%2FGLB/document/primary%3ADocuments%2FGLB%2FTheJenningsDog.glb Info 18:55:02
    unity.logger file = content://com.android.externalstorage.documents/tree/primary%3ADocuments%2FGLB/document/primary%3ADocuments%2FGLB%2FTheJenningsDog.glb Info 18:55:02
    unity.logger Moving content://com.android.externalstorage.documents/tree/primary%3ADocuments%2FGLB/document/primary%3ADocuments%2FGLB%2FTheJenningsDog.glb to /storage/emulated/0/Android/data/com.ARtStudio.BavARt/cache/primary%3ADocuments%2FGLB%2FTheJenningsDog_3dcreation0.glb Info 18:55:02
    exception
    DirectoryNotFoundException: Could not find a part of the path "/content:/com.android.externalstorage.documents/tree/primary%3ADocuments%2FGLB/document/primary%3ADocuments%2FGLB%2FTheJenningsDog.glb". Error 18:55:02


    As you can see, the
    Debug.Log("file = " + str);
    output a path already containing "content://". However the error did mention "/content:/" different from "content://" if the first log.

    Here are my Android device info, if that can help:
    upload_2022-5-2_19-22-2.png
    Thanks again for your assistance!
     
  21. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    That's a Storage Access Framework path, on Android 10 and later, unfortunately we must work with them, there is no other way, OS simply restricts our access. To work with these paths, you must use FileBrowserHelpers functions, standard System.IO functions won't work (e.g.
    FileBrowserHelpers.GetFilename, FileBrowserHelpers.CopyFile).
     
  22. ChloeGue

    ChloeGue

    Joined:
    May 11, 2019
    Posts:
    11
    Hey!
    Thanks a lot for your help. It works like a charm now :)
    Thanks for this very useful plugin.

    Have a nice day!
    Chloé.
     
    yasirkula likes this.
  23. OHronek

    OHronek

    Joined:
    Apr 20, 2022
    Posts:
    2
    Hi!

    I wanted to impement your plugin but wasn't able to test it because of errors. The error occurs if i want to do something with the Filebrowser.

    Error:
    AndroidJavaException: java.lang.ClassNotFoundException: com.yasirkula.unity.FileBrowser
    java.lang.ClassNotFoundException: com.yasirkula.unity.FileBrowser

    I already tried to add the line -keep class com.yasirkula.unity.* { *; } in the progurad file but this didn't solve my problem.

    If I execute my unity project in the unity editior, it works well. After creating the apk and upload it to the device, I get this error message from logcat.

    Thank you in advance!
     
    Last edited: May 4, 2022
  24. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Does
    SimpleFileBrowser/Android/SimpleFileBrowser.aar
    exist in the project? Does its import settings say that it's included in Android builds? Have you imported the plugin via GitHub, Asset Store or another medium? What is the value of Minification in Player Settings (e.g. Proguard, Gradle)? Are you exporting Android Studio project or building APK directly? Does deleting the plugin and then reimporting it from GitHub have any effect?
     
  25. OHronek

    OHronek

    Joined:
    Apr 20, 2022
    Posts:
    2
    This is currently the structure from my Project. The android in the plugins folder contains the androidmanifest.xml and some other data. The android folder in SimpleFileBrowser folder contains your data. SimpleFileBrowser.aar is existing in this folder. At the section "Select platforms for plugin" is the android checkbox checked.

    I imported the asset with the unitypackage.

    The second picture is displaying the player settings -> publishing settings -> build section

    The APK was builded directly to my android device.

    Reimporting the plugin didn't solve the problem.
    upload_2022-5-5_8-31-45.png

    upload_2022-5-5_8-16-10.png
     
  26. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    mawejjenikolas likes this.
  27. IanCole

    IanCole

    Joined:
    Feb 21, 2017
    Posts:
    3
    Apologies if this has already been covered but I was trying to use your package with an OpenXR project, which uses the new Input System, and by default Unity set my project to the new system only, not both. I was therefore getting the following namespace compiler errors:
    • Assets\Plugins\SimpleFileBrowser\Scripts\FileBrowser.cs(13,19): error CS0234: The type or namespace name 'InputSystem' does not exist in the namespace 'UnityEngine' (are you missing an assembly reference?)
    • Assets\Plugins\SimpleFileBrowser\Scripts\FileBrowserDeleteConfirmationPanel.cs(5,19): error CS0234: The type or namespace name 'InputSystem' does not exist in the namespace 'UnityEngine' (are you missing an assembly reference?)
    • Assets\Plugins\SimpleFileBrowser\Scripts\FileBrowserRenamedItem.cs(5,19): error CS0234: The type or namespace name 'InputSystem' does not exist in the namespace 'UnityEngine' (are you missing an assembly reference?)
    If anyone else runs into this problem, it's quite an easy fix - you just need to set Edit > Project Settings > Player > Active Input Handling to 'Both'. This will prompt a restart of Unity, after which the namespace errors should disappear.

    upload_2022-7-11_12-6-38.png

    Thanks for the free asset @yasirkula :)

    #Edit 1 - I possibly jumped the gun on this - I see you have a section for 'NEW INPUT SYSTEM SUPPORT' in your readme file, which is very helpful thank you, especially the bit about adding Unity.InputSystem assembly to SimpleFileBrowser.Runtime Assembly Definition File's Assembly Definition References list. Doing this seems to fix the namespace compiler errors without the need to switch 'Active Input Handling' to 'Both'. I think you could clarify this part slightly though @yasirkula, as I was unsure what this meant to start with. Thanks again for the asset though - I'm hoping it will prove to be very helpful. :D

    I'll leave my original post up for now in case it helps some peeps.

    # Edit 2 - I'm unsure if this is only an issue in OpenXR but I've noticed in the SimpleFileBrowserCanvas prefab, the following object has additional Canvas and Graphic Raycaster components on it, which in my case prevented any interaction. Just removing these made it work:

    SimpleFileBrowserWindow/Padding/MidView/Padding/Files
     
    Last edited: Jul 12, 2022
    yasirkula likes this.
  28. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @IanCole Thank you for sharing your findings! I haven't tried the plugin in XR myself but it's sad to hear that nested canvases (Padding > Files) aren't supported by OpenXR framework. Nevertheless, happy to hear that you've resolved the issue!
     
  29. Andefob

    Andefob

    Joined:
    Sep 17, 2018
    Posts:
    99
    Hi! Just for your information, I am using an old and modified version of SFB in my game. I just upgraded from Unity 2021.3.0 to 2021.3.6 and the result was that SFB stopped working. It seemed that the canvas of "Padding/MidView/Padding/Files" was behind the canvas of the top level SimpleFileBrowserCanvas (with sort order 2016). I fixed this by changing the sort order of Files canvas to 2020.

    I have no idea why this happened and if it this was a Unity bug or something that was indirectly caused by my modifications, or something that would have been fixed in newer versions of FSB already. But, I just thought it would be nice to report this here since I spent some time on debugging it and someone else might have the same issue :).
     
    yasirkula likes this.
  30. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @Andefob Thank you for reporting this. "Padding/MidView/Padding/Files"s "Override Sorting" property is set to False by default so it might be a Unity bug on 2021.3.6f1.
     
  31. krokadile

    krokadile

    Joined:
    Oct 28, 2016
    Posts:
    5
    On Windows 10, it does not list any files nor folders - just drives regardless of file filter.
     
  32. IanCole

    IanCole

    Joined:
    Feb 21, 2017
    Posts:
    3
    @Andefob, I'm using Unity 2021.3.3f1 and can confirm that the Override Sorting setting for the canvas on "Padding/MidView/Padding/Files" is off in the prefab. I just tried your suggestion of enabling it and changing it to something higher than 2016 but alas in my OpenXR scene I still can't interact with that part of the UI using an XR Ray Interactor. Only removing the Canvas and Graphic Raycaster on that nested object seems to work, which doesn’t appear to have any detrimental effect, making me wonder if there's a need to have it there in the first place. I've noticed there is also a nested Canvas and Graphic Raycaster on the DeleteConfirmationPanel but I haven't been able to test if this is a problem in VR yet - although I suspect it would be.
     
  33. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @krokadile Are there any errors in Console? Can I see your code and if possible a screenshot from the file browser?

    @IanCole Nested canvases are among Unity's recommended best practices which is why I'm using them when applicable.
     
    IanCole likes this.
  34. Andefob

    Andefob

    Joined:
    Sep 17, 2018
    Posts:
    99
    Yes it was false for me, too, but the top level canvas had it enabled with value 2016 (wherever that comes from).

    For some reason, when not overriding the sorting of the Files canvas with a higher value, it is now behind the top level canvas. Might be a Unity bug, yes, or then it is undefined behavior that has worked before by luck in the previous Unity versions.

    @IanCole thanks for mentioning DeleteConfirmationPanel - it seems there are similar other issues, too, also when just opening the popup by right-clicking a file. Similar fix is probably needed (I will test that later when I have time).
     
  35. Andefob

    Andefob

    Joined:
    Sep 17, 2018
    Posts:
    99
    This might be the same issue I am reporting about, at least if you can see that the files are actually there in the scene but hidden in a canvas behind the top-level canvas.
     
  36. krokadile

    krokadile

    Joined:
    Oct 28, 2016
    Posts:
    5
    @yasirkula Thanks - the code is just what's on Github page in a mono behavior attached to an otherwise empty game object in an empty scene. The view is as below:

    upload_2022-7-13_9-33-56.png

    AFAIK there are no error messages - does it have a diagnostic logging switch?
     
  37. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @krokadile I see. Please apply this solution to resolve this issue. I don't know why it started happening on Unity 2021.3.2+ but it's very likely a Unity bug because it doesn't occur on any of the previous Unity versions.
     
  38. Andefob

    Andefob

    Joined:
    Sep 17, 2018
    Posts:
    99
    Revised fix to the bug:

    At least in my FSB version, there were 4 canvases inside SimpleFileBrowserCanvas. So, the root now has the old sort order of 2016, Files was changed to overridden value of 2017, Context menu remains at 2020 (I guess it already had that so nothing changed) and DeleteConfirmationPanel was set overridden value of 2021.
     
    JHIMMY_777 likes this.
  39. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    I've realized that enabling and then disabling the nested canvases' Override Sorting property at runtime fixes the rendering issue (but touch input will still not go through correctly), so this is surely some sort of annoying Unity bug introduced in a version no earlier than 2021.3.1f1. I've filed a bug report and hope that they'll resolve it soon.
     
    JHIMMY_777 likes this.
  40. Kethlak

    Kethlak

    Joined:
    Jul 5, 2020
    Posts:
    1
    Andefob and yasirkula like this.
  41. sw_unity02

    sw_unity02

    Joined:
    May 4, 2017
    Posts:
    1
    I am on 2021.3.8f1, it does not list any files nor folders, fix for me is- "Padding/MidView/Padding/Files" Override Sorting ON and sort order to 2020.
     
    yasirkula likes this.
  42. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  43. HellSharkGames

    HellSharkGames

    Joined:
    Apr 4, 2022
    Posts:
    2
    yasirkula likes this.
  44. jjaros

    jjaros

    Joined:
    Jun 18, 2015
    Posts:
    7
    Hi,
    I found an issue when some folders aren't visible on Windows in SimpleFileBrowser. Software called DragonFrame 5 will create project folder, which is probably in some custom settings and it's not visible in SimpleFileBrowser. I figure out that if you open folder's properties and click Customize -> Restore Default and Apply, then it will be visible in SimpleFileBrowser. Is it possible to make it visible in SimpleFileBrowser without Restoring the folder?

    Unity 2021.2.19f1

    Here is the article which helped me to make it visible:
    https://appuals.com/hidden-attribute-greyed-out-windows-7-8-and-10/

    Thank you
     

    Attached Files:

    Last edited: Sep 15, 2022
  45. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @jjaros Hi! If you call Directory.GetDirectories or Directory.GetFileSystemEntries inside the DragonFrameTest folder, do any/both of these return the hidden folder?
     
  46. jjaros

    jjaros

    Joined:
    Jun 18, 2015
    Posts:
    7
    if I call:
    var dirs = Directory.GetDirectories("R:/Downloads/DragonFrameTest");
    var dirs2 = Directory.GetFileSystemEntries("R:/Downloads/DragonFrameTest");

    both returned arrays has path to all folders (also the one which is not visible in SimpleFileBrowser)
     
    Last edited: Sep 15, 2022
  47. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  48. jjaros

    jjaros

    Joined:
    Jun 18, 2015
    Posts:
    7
    setting ignoredFileAttributes = 0; helped :D thx, is it possible to set that filter from code? because it is in the package and I can't push the change to git. Thx
     
  49. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Currently, the only way is to use reflection :D BTW you can move a package from Library/PackageCache to Packages and now it's both editable and pushable.
     
  50. jjaros

    jjaros

    Joined:
    Jun 18, 2015
    Posts:
    7
    I figure it out by downloading the SimpleFileBrowser as project and move it to plugin folder and removed it as a package.
    Thank you so much for your help.
     
    yasirkula likes this.