Page 1 of 1

Image not found in ANDROID_PUBLIC path

Posted: Tue May 26, 2020 6:27 pm
by srksrk 68

OK, this is a longer post for a problem that buggs me right now. I try to explain in detail, and I hope you gurus have the patience to read ;)

I have this game which works perfectly on Android and on Windows. I have an archive (a directory structure) "alt" containing alternate images for character "xyz" (i.e. alternate images are in alt/xyz/images and the original ones that are in game/images). Let's this archive call a mod.

The mod works because in an early init state, I enhance config.searchpath like this:


where <game>/ is the path to the game's installation directory. So whenever an alternate image is found in <game>/alt/xyz/images it is loaded instead of what would be found in <game>/game/images later during automatic image loading in _scan_images_directory. As I said, this works well in Android and in Windows.

What does not work is when I try to load an image out of the mod's archive like this:

Code: Select all

screen mod_sample(path):
        if and ("ANDROID_PUBLIC" in os.environ):
            sample = os.path.join(os.environ["ANDROID_PUBLIC"], "alt")
            sample = config.basedir.replace('\\', '/') + '/alt'
        sample += '/' + path
    if os.path.isfile(sample): # Does not seem to work on Android for some reason...
        add Image(sample) at center
In this screen, a path to the sample image in the mod's archive is passed as screen parameter, and this image is displayed. Works fine on Windows, but not on Android, and I can't figure out why. Apparently the constructed path to the image is not working when the image is located in ANDROID_PUBLIC. Strange is that the test for file existance is working ("if os.path.isfile(sample)") but loading the very same image is not. Error is:

File "renpy/common/000statements.rpy", line 531, in execute_call_screen
IOError: Couldn't find file 'storage/emulated/150/Android/data/<game>/alt/xyz/sample.png'.

As written before, the existence check before the image is attempted to load is successful. The path to the <game> directory is what the coding before that constructs from the environment variable, and the appended part to the image file is what is passed as argument to the screen.

What I noticed is that the error message is lacking the leading slash, i.e. 'storage/emulated...' instead of '/storage/emulated' which is the complete path to the image. I cannot work with the config.basedir variable because mods on Android have to be placed in the public storage.

Does anybody have a clue why displaying the image like that does not work on Android, but everything else (the modded app with the images loaded via _scan_images_directory) works?

Re: Image not found in ANDROID_PUBLIC path

Posted: Tue May 26, 2020 7:31 pm
by Imperf3kt
I won't pretend to understand most of this as it's all new to me, but when does the image get defined, at what stage of init?
Does placing your code in a higher (lower?) init help?

Re: Image not found in ANDROID_PUBLIC path

Posted: Tue May 26, 2020 7:41 pm
by srksrk 68
Well, that's the issue. Init is not a problem since using the images works as expected. They are all found by the _scan_images_directory function, which walks the config.searchpath and looks for images.

What does not work is addressing the image directly via the complete path name. This does work on Windows only but not on Android.

The idea behind this is: I want to give the user the option to switch the mod on/off, presenting the sample image to him. If he does his selection, the change is stored and -- this is important -- he has to close and restart the game, this time with the config.searchpath set up in accordance to what he selected earlier. But this means that the sample image is not available at init time if the mod is switched off. It can only be loaded (on Windows) using the complete path/name like in the sample screen above.

Re: Image not found in ANDROID_PUBLIC path

Posted: Tue May 26, 2020 9:46 pm
by Imperf3kt
What does your mod change, exactly?
You can change the user interface without restarting the app and sprites / backgrounds can be adjusted also.
I recently updated my Android GUI (link in signature) to do exactly this.
The next planned update should extend the functionality to styles.

Would this be more suitable, or have I misunderstood?

Re: Image not found in ANDROID_PUBLIC path

Posted: Wed May 27, 2020 3:16 am
by srksrk 68
As I wrote, the user can basically throw the mod (i.e. a directory structure similar to the unmodded structure found under game/images) into the <game> folder, and the Ren'py _scan_images_directory function walks everything in config.searchpath in a sequence so that the modded images will overrrule the game's images. This works well and I do not want to discuss this here.

What does not work and what this posting is about is why Ren'py on Android apparently cannot load an image (error: not found) of which the existence is checked just one line above, when addressed using the complete path name. Under Windows, I can just give a path to an image file and display that image. Under Android this does not work. The file exists, os.path.isfile confirms it exists, but it cannot be loaded.

Re: Image not found in ANDROID_PUBLIC path

Posted: Wed May 27, 2020 4:40 am
by Imperf3kt
Oh, you didn't mention allowing the user/player to put the mod in the game.

As far as I'm aware, it's a permissions thing - Renpy doesn't have the required permissions to read outside its own directory.

Re: Image not found in ANDROID_PUBLIC path

Posted: Wed May 27, 2020 4:45 am
by srksrk 68
This would explain the issue. But why does it work in Windows, and why does os.path.isfile not give an error on Android? And to my understanding, this image *is* inside the game's directory, it is just not included in config.searchpath. Which, again, works well on Windows.

Re: Image not found in ANDROID_PUBLIC path

Posted: Wed May 27, 2020 4:49 am
by Imperf3kt

Re: Image not found in ANDROID_PUBLIC path

Posted: Wed May 27, 2020 5:06 am
by srksrk 68
Well, the first link does not apply because it is about making the APK. I already have an APK, I want to put in a mod.

The second link seems to be the same topic.

The third one is interesting, but there PyTom mentions that the issue that Android can walk the external memory will be put onto the ToDo list for a future release (the posting is from 2018). The github item he created "transfn should search the external android files directory" has been closed January 2019. So I would expect that my problem should be covered by this...

Re: Image not found in ANDROID_PUBLIC path

Posted: Wed May 27, 2020 11:56 am
by srksrk 68

I guess I found a solution, or workaround. Or rather an exploit.

Seems that on Android, the image in fact must be stored inside the <game>/game directory, and absolute paths do not work even if the image is existing and os.path.isfile confirms it. So the solution (which in my case is no solution) would be to have the sample images present in e.g. a folder <game>/_samples. This would contradict the purpose of installing the mod *parallel* to the <game>/game directory, e.g. to <game>/alt as intended in my initial post.

The workaround would be to check, create and copy the image files in the init phase physically from the <game>/alt directory structure to the <game>/game structure, which would work but is very ugly.

The "exploit" I am now going with is:

Install the mod as intended to <game>/alt, and during init phase, create images like this:

Code: Select all

renpy.image(<name of sample image>, "../alt/" + <relative path to sample image>)
The pretty thing is that this now works on Android and on Windows. The ugly thing is that Renpy on Android forces me to become a hacker...