Mercurial > repos > blastem
diff util.c @ 2681:c4256ce2c45a
Updated Android port using gradle toolchain and with basic Storage Access Framework support for Android 11+ support
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 26 Mar 2025 01:20:55 -0700 |
parents | bebc3589dedf |
children | 143cb5762ec9 |
line wrap: on
line diff
--- a/util.c Wed Mar 26 01:20:09 2025 -0700 +++ b/util.c Wed Mar 26 01:20:55 2025 -0700 @@ -11,6 +11,8 @@ #ifdef __ANDROID__ #include <android/log.h> +#include <SDL_system.h> +#include <jni.h> #define info_puts(msg) __android_log_write(ANDROID_LOG_INFO, "BlastEm", msg) #define warning_puts(msg) __android_log_write(ANDROID_LOG_WARN, "BlastEm", msg) #define fatal_puts(msg) __android_log_write(ANDROID_LOG_FATAL, "BlastEm", msg) @@ -866,6 +868,54 @@ dir_entry *get_dir_list(char *path, size_t *numret) { +#ifdef __ANDROID__ + debug_message("get_dir_list(%s)\n", path); + if (startswith(path, "content://")) { + static const char activity_class_name[] = "com/retrodev/blastem/BlastEmActivity"; + static const char read_uri_dir_name[] = "readUriDir"; + JNIEnv *env = SDL_AndroidGetJNIEnv(); + jclass act_class = (*env)->FindClass(env, activity_class_name); + if (!act_class) { + fatal_error("Failed to find activity class %s\n", activity_class_name); + } + jmethodID meth = (*env)->GetMethodID(env, act_class, read_uri_dir_name, "(Ljava/lang/String;)[Ljava/lang/String;"); + if (!meth) { + fatal_error("Failed to find method %s\n", read_uri_dir_name); + } + debug_message("get_dir_list(%s) using Storage Access Framework\n", path); + jstring jpath = (*env)->NewStringUTF(env, path); + jobject activity = SDL_AndroidGetActivity(); + jobject ret = (*env)->CallObjectMethod(env, activity, meth, jpath); + dir_entry *res = NULL; + if (ret) { + jsize num = (*env)->GetArrayLength(env, ret); + if (numret) { + *numret = num; + } + res = calloc(num, sizeof(dir_entry)); + for (jsize i = 0; i < num; i++) + { + jstring entry = (*env)->GetObjectArrayElement(env, ret, i); + char const *tmp = (*env)->GetStringUTFChars(env, entry, NULL); + jsize len = (*env)->GetStringUTFLength(env, entry); + res[i].name = calloc(len + 1, 1); + res[i].is_dir = tmp[len-1] == '/'; + memcpy(res[i].name, tmp, res[i].is_dir ? len -1 : len); + (*env)->ReleaseStringUTFChars(env, entry, tmp); + } + (*env)->DeleteLocalRef(env, ret); + } + + (*env)->DeleteLocalRef(env, activity); + if (!res) { + if (numret) { + *numret = 0; + } + return NULL; + } + return res; + } +#endif DIR *d = opendir(path); if (!d) { if (numret) { @@ -1004,7 +1054,60 @@ SDL_RWclose(rw); return ret; } + +static int open_uri(const char *path, const char *mode) +{ + static const char activity_class_name[] = "com/retrodev/blastem/BlastEmActivity"; + static const char open_uri_as_fd_name[] = "openUriAsFd"; + JNIEnv *env = SDL_AndroidGetJNIEnv(); + jclass act_class = (*env)->FindClass(env, activity_class_name); + if (!act_class) { + fatal_error("Failed to find activity class %s\n", activity_class_name); + } + jmethodID meth = (*env)->GetMethodID(env, act_class, open_uri_as_fd_name, "(Ljava/lang/String;Ljava/lang/String;)I"); + if (!meth) { + fatal_error("Failed to find method %s\n", open_uri_as_fd_name); + } + jobject activity = SDL_AndroidGetActivity(); + jstring jpath = (*env)->NewStringUTF(env, path); + jstring jmode = (*env)->NewStringUTF(env, mode); + int fd = (*env)->CallIntMethod(env, activity, meth, jpath, jmode); + (*env)->DeleteLocalRef(env, activity); + return fd; +} + +FILE* fopen_wrapper(const char *path, const char *mode) +{ + if (startswith(path, "content://")) { + debug_message("fopen_wrapper(%s, %s) - Using Storage Access Framework\n", path, mode); + int fd = open_uri(path, mode); + if (!fd) { + return NULL; + } + return fdopen(fd, mode); + } else { + debug_message("fopen_wrapper(%s, %s) - Norma fopen\n", path, mode); + return fopen(path, mode); + } +} + +#ifndef DISABLE_ZLIB +gzFile gzopen_wrapper(const char *path, const char *mode) +{ + if (startswith(path, "content://")) { + debug_message("gzopen_wrapper(%s, %s) - Using Storage Access Framework\n", path, mode); + int fd = open_uri(path, mode); + if (!fd) { + return NULL; + } + return gzdopen(fd, mode); + } else { + debug_message("fopen_wrapper(%s, %s) - Norma gzopen\n", path, mode); + return gzopen(path, mode); + } +} #endif +#endif // IS_LIB char const *get_config_dir() {