SDL icon indicating copy to clipboard operation
SDL copied to clipboard

Android: `SDL_GetPathInfo` doesn't default to "assets" like other file functions.

Open AntTheAlchemist opened this issue 6 months ago • 3 comments

The following line will return false, to suggest the file doesn't exist:

SDL_GetPathInfo("example.text", 0);

However, the following line will work, because the file does exist:

SDL_LoadFile("example.text", 0);

The file is in \app\src\main\assets, which seems to be the default for many file operations, but not SDL_GetPathInfo, maybe? Is it unreasonable to assume it should default to assets without a full path specified?

AntTheAlchemist avatar May 15 '25 23:05 AntTheAlchemist

Yeah, that seems like a bug.

icculus avatar May 19 '25 20:05 icculus

Okay, so this happens because SDL_LoadFile is backed by SDL_IOFromFile, which has a ton of Android-specific code.

But SDL_GetPathInfo() is just calling POSIX functions on Android.

So fixing this probably means rolling a bunch of Android code to use AAssetManager in some cases, and POSIX in others.

It's doable, but it's not gonna make it for 3.2.16.

icculus avatar Jun 01 '25 06:06 icculus

That's fair. It's not a deal breaker because there are plenty of ways around it.

Should we put a note in so it doesn't trip anyone up?

Or, how easy would it be to just insert the current path if a relative path is detected?

AntTheAlchemist avatar Jun 01 '25 06:06 AntTheAlchemist

SDL_GetPathInfo returns with false and error "Can't stat: No such file or directory" for files selected using SDL_ShowOpenFileDialog as well (and can be loaded successfully using SDL_LoadFile), so it seems that is not working in general.

ManuBlack avatar Jun 27 '25 09:06 ManuBlack

Okay, this is pushed to main: 515433aa8a8fdeb0be4d0e2e1ee733ad16fc7d6e

It works like SDL_IOStream: it'll try real filesystem accesses, and if that doesn't work out, it'll try the AssetManager. Assets don't have file times, so they always come back as zero in SDL_GetPathInfo() in this case, but I assume most things just want file size and type anyhow.

If it's possible, can you make sure this works for your app before I cherry-pick it over to release-3.2.x?

icculus avatar Jul 11 '25 18:07 icculus

Only now looking at this, apologise for delay. This still isn't behaving as expected. SDL_GetPathInfo("anything", null) is returning true for everything.

Stepping through the code in SDL_android.c's Android_JNI_GetAssetPathInfo. In the following code, AAssetManager_openDir returns a valid AAssetDir object (not null) even if path isn't a path:

    // this is sort of messy, but there isn't a stat()-like interface to the Assets.
    AAssetDir *adir = AAssetManager_openDir(asset_manager, path);
    if (adir) {  // it's a directory!
        AAssetDir_close(adir);
        info->type = SDL_PATHTYPE_DIRECTORY;
        info->size = 0;
        return true;
    }

AntTheAlchemist avatar Jul 29 '25 12:07 AntTheAlchemist

Ugh, okay.

icculus avatar Jul 29 '25 15:07 icculus

Sure enough, it never returns NULL:

https://android.googlesource.com/platform/frameworks/base/+/master/native/android/asset_manager.cpp#94

icculus avatar Jul 29 '25 15:07 icculus

Okay, so it looks like AAssetManager_open() will return NULL, so we can flip this to look for files first, and directories second, and then check if the directory is empty (AAssetDir_getNextFileName returns NULL)...if empty, we assume the directory doesn't exist.

This isn't perfect, but it's probably good enough...?

icculus avatar Jul 29 '25 15:07 icculus

(Notably: this never returns NULL because asset dirs are a union of multiple .zip files that might each have the same directory.)

icculus avatar Jul 29 '25 16:07 icculus

Okay, try the latest in main and see if it works for you!

icculus avatar Jul 29 '25 16:07 icculus

Sorry, you seem to get all the nice bug-fixes 🤣. Yes, that's done the trick, thank you. Tested exists functionality in assets, and full paths. Shame about empty directories, but looks like the best it's going to be.

AntTheAlchemist avatar Jul 29 '25 19:07 AntTheAlchemist