• Godot Help
  • Reading an external user supplied file in user directory on Android

I am trying to get my exported project to read a file from the user:// folder.

My plan is to allow the user to change a configfile and to allow the user to change a background image by copying it to the user folder.

If I create a config file from withing the game, it can create the file, save data to it and read it back. But I can't see the file in the explorer externally from the game.

I can see the folder externally, and I can copy a file to it, but my game can't see the file I copied there.
No matter how I do I can't get it to work, have tried dozens of different things,

The permissions currently set in the export options are:

Clear app user data
Internet
Read external storage
Read user dictionary
Write external storage
Write profile
Write user dictionary

version of Godot is 3.5

I am now considering letting the app download a configfile and background image with http and then saving that file to user:// from within the app. It just seems like a really long winded and weird work around. I have seen other games have the ability to use custom data in it's user directory so it is certainly possible, just don't know if it's possible in Godot.

Since the documentation specifically forbids other software from accessing user:// on mobile, the engine might not be coded to see changes, even if you make them. If that's the case, you'll have to tinker with the engine to get it to work.

No, I don't think that would work for security reasons, and is a poor user experience. You can save files like this.

https://docs.godotengine.org/en/stable/tutorials/io/saving_games.html

Then just have an options screen in your game, where the user can configure things. That said, you can access all data from a computer (like with your Android phone connected to a PC via USB cable). I've done this, but I forget the full path off hand. Doing this on the phone would be difficult, due to security, as apps are not supposed to access the data of other apps (otherwise your Godot game could be reading data from the user's Chase bank account or whatever).

Yes, but you should do it through the provided OS methods. When you get access to media, I assume you should be able to load/save an image from the user's photo reel into your Godot game. But this would not be done manually in a file browser. I mean, I can think of some hack ways to do it, but this seems like a horrible user experience, and I'm not even going to go down that road.

See if this plug-in helps. You may have to do a custom build.

https://github.com/Lamelynx/GodotGetImagePlugin-Android

5 months later

I solved this problem actually. So, the way to have a possibility of copying in custom data, for instance to be able to mod a game or something like that. I used the folder /storage/emulated/0/Android/data/com.madeupcompany.gamename/images/ and so on. You can copy your custom images into that folder and the game can then access them.
I still use user: for config files that the game saves itself, but in order to have an config file modifiable externally I have to have it in /storage/emulated/0/Android/data/com.madeupcompany.gamename/config/

So that's how I solved it anyway.
As it goes for security or user experience, we sell custom hardware using android, so it's not going to be downloadable on playstore or anything like that. It's not on a phone.

I hope this will help someone.

    a month later
    16 days later

    Beatrix

    Sure.

    I use a function:

    load_external_img("/storage/emulated/0/Android/data/com.madeupcompany.gamename/images/myimage.png")

    Which is defined as the following:

    func load_external_img(path):
    	var img_file = File.new()
    	img_file.open(path, File.READ)
    	var bytes = img_file.get_buffer(img_file.get_len())
    	var img = Image.new()
    	match path.get_extension():
    		"png":
    			var _data = img.load_png_from_buffer(bytes)
    		"jpg":
    			var _data = img.load_jpg_from_buffer(bytes)
    		"jpeg":
    			var _data = img.load_jpg_from_buffer(bytes)
    		"bmp":
    			var _data = img.load_bmp_from_buffer(bytes)
    			
    	img_file.close()
    	return img

    This works fine for loading images you can copy to a local folder on the device using a filwbrowser on it.
    In the filebrowser the path is "Internal Memory/Android/data/com.madeupcompany.gamename/images/myimage.png"

    So this way you can allow a user to mod his installed game with custom graphics for instance.

    You can also write to this folder using for instance:

    func printlog(s:String,path:String = "/storage/emulated/0/Android/data/com.madeupcompany.gamename/log.txt"):
    	var logfile = File.new()
    	logfile.open(path, File.WRITE)
    	logfile.store_string(s)
    	logfile.close()