android: If various POSIX fsops functions fail, try using AAssetManager.
This specifically affects SDL_EnumerateDirectory and SDL_GetPathInfo. Android assets are read-only, so no need to do this for things like SDL_CreateDirectory, etc, and the POSIX SDL_CopyFile() uses SDL_IOStream behind the scenes, which already supports Android assets. Fixes #13050.
This commit is contained in:
@@ -1853,6 +1853,62 @@ bool Android_JNI_FileClose(void *userdata)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Android_JNI_EnumerateAssetDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
|
||||||
|
{
|
||||||
|
SDL_assert((*path == '\0') || (path[SDL_strlen(path) - 1] == '/')); // SDL_SYS_EnumerateDirectory() should have verified this.
|
||||||
|
|
||||||
|
if (!asset_manager) {
|
||||||
|
Internal_Android_Create_AssetManager();
|
||||||
|
if (!asset_manager) {
|
||||||
|
return SDL_SetError("Couldn't create asset manager");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AAssetDir *adir = AAssetManager_openDir(asset_manager, path);
|
||||||
|
if (!adir) {
|
||||||
|
return SDL_SetError("AAssetManager_openDir failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_EnumerationResult result = SDL_ENUM_CONTINUE;
|
||||||
|
const char *ent;
|
||||||
|
while ((result == SDL_ENUM_CONTINUE) && ((ent = AAssetDir_getNextFileName(adir)) != NULL)) {
|
||||||
|
result = cb(userdata, path, ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
AAssetDir_close(adir);
|
||||||
|
|
||||||
|
return (result != SDL_ENUM_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Android_JNI_GetAssetPathInfo(const char *path, SDL_PathInfo *info)
|
||||||
|
{
|
||||||
|
if (!asset_manager) {
|
||||||
|
Internal_Android_Create_AssetManager();
|
||||||
|
if (!asset_manager) {
|
||||||
|
return SDL_SetError("Couldn't create asset manager");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
AAsset *aasset = AAssetManager_open(asset_manager, path, AASSET_MODE_UNKNOWN);
|
||||||
|
if (aasset) { // it's a file!
|
||||||
|
info->type = SDL_PATHTYPE_FILE;
|
||||||
|
info->size = (Uint64) AAsset_getLength64(aasset);
|
||||||
|
AAsset_close(aasset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_SetError("Couldn't open asset '%s'", path);
|
||||||
|
}
|
||||||
|
|
||||||
bool Android_JNI_SetClipboardText(const char *text)
|
bool Android_JNI_SetClipboardText(const char *text)
|
||||||
{
|
{
|
||||||
JNIEnv *env = Android_JNI_GetEnv();
|
JNIEnv *env = Android_JNI_GetEnv();
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, SDL_IOWhence whence);
|
|||||||
size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOStatus *status);
|
size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOStatus *status);
|
||||||
size_t Android_JNI_FileWrite(void *userdata, const void *buffer, size_t size, SDL_IOStatus *status);
|
size_t Android_JNI_FileWrite(void *userdata, const void *buffer, size_t size, SDL_IOStatus *status);
|
||||||
bool Android_JNI_FileClose(void *userdata);
|
bool Android_JNI_FileClose(void *userdata);
|
||||||
|
bool Android_JNI_EnumerateAssetDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata);
|
||||||
|
bool Android_JNI_GetAssetPathInfo(const char *path, SDL_PathInfo *info);
|
||||||
|
|
||||||
// Environment support
|
// Environment support
|
||||||
void Android_JNI_GetManifestEnvironmentVariables(void);
|
void Android_JNI_GetManifestEnvironmentVariables(void);
|
||||||
|
|||||||
@@ -35,6 +35,10 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID
|
||||||
|
#include "../../core/android/SDL_android.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
|
bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
|
||||||
{
|
{
|
||||||
char *pathwithsep = NULL;
|
char *pathwithsep = NULL;
|
||||||
@@ -51,8 +55,14 @@ bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback
|
|||||||
|
|
||||||
DIR *dir = opendir(pathwithsep);
|
DIR *dir = opendir(pathwithsep);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID // Maybe it's an asset...?
|
||||||
|
const bool retval = Android_JNI_EnumerateAssetDirectory(pathwithsep, cb, userdata);
|
||||||
|
SDL_free(pathwithsep);
|
||||||
|
return retval;
|
||||||
|
#else
|
||||||
SDL_free(pathwithsep);
|
SDL_free(pathwithsep);
|
||||||
return SDL_SetError("Can't open directory: %s", strerror(errno));
|
return SDL_SetError("Can't open directory: %s", strerror(errno));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure there's a path separator at the end now for the actual callback.
|
// make sure there's a path separator at the end now for the actual callback.
|
||||||
@@ -173,7 +183,11 @@ bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
|
|||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
const int rc = stat(path, &statbuf);
|
const int rc = stat(path, &statbuf);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
#ifdef SDL_PLATFORM_ANDROID // Maybe it's an asset...?
|
||||||
|
return Android_JNI_GetAssetPathInfo(path, info);
|
||||||
|
#else
|
||||||
return SDL_SetError("Can't stat: %s", strerror(errno));
|
return SDL_SetError("Can't stat: %s", strerror(errno));
|
||||||
|
#endif
|
||||||
} else if (S_ISREG(statbuf.st_mode)) {
|
} else if (S_ISREG(statbuf.st_mode)) {
|
||||||
info->type = SDL_PATHTYPE_FILE;
|
info->type = SDL_PATHTYPE_FILE;
|
||||||
info->size = (Uint64) statbuf.st_size;
|
info->size = (Uint64) statbuf.st_size;
|
||||||
@@ -203,7 +217,7 @@ bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that this isn't actually part of filesystem, not fsops, but everything that uses posix fsops uses this implementation, even with separate filesystem code.
|
// Note that this is actually part of filesystem, not fsops, but everything that uses posix fsops uses this implementation, even with separate filesystem code.
|
||||||
char *SDL_SYS_GetCurrentDirectory(void)
|
char *SDL_SYS_GetCurrentDirectory(void)
|
||||||
{
|
{
|
||||||
size_t buflen = 64;
|
size_t buflen = 64;
|
||||||
|
|||||||
Reference in New Issue
Block a user