From 6cf1d1f98553e74b4912d6b07927bebd742c9baa Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 2 Nov 2012 02:22:32 -0700 Subject: [PATCH] Added some platform specific API functions for Android: SDL_AndroidGetJNIEnv() SDL_AndroidGetActivity() SDL_AndroidGetInternalStoragePath() SDL_AndroidGetExternalStorageState() SDL_AndroidGetExternalStoragePath() --- include/SDL_system.h | 47 +++++++++- src/core/android/SDL_android.cpp | 152 ++++++++++++++++++++++++++++++- 2 files changed, 196 insertions(+), 3 deletions(-) diff --git a/include/SDL_system.h b/include/SDL_system.h index 08dde6c40..2fd12c291 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -43,6 +43,11 @@ extern "C" { /* *INDENT-ON* */ #endif +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* +/* Platform specific functions for iOS +/* +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #if __IPHONEOS__ extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam); @@ -53,7 +58,47 @@ extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); #define SDL_iPhoneKeyboardToggle SDL_ToggleScreenKeyboard #define SDL_iPhoneKeyboardIsShown SDL_IsScreenKeyboardShown -#endif +#endif /* __IPHONEOS__ */ + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* +/* Platform specific functions for Android +/* +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#if __ANDROID__ + +/* Get the JNI environment for the current thread + This returns JNIEnv*, but the prototype is void* so we don't need jni.h + */ +extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(); + +/* Get the SDL Activity object for the application + This returns jobject, but the prototype is void* so we don't need jni.h + */ +extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(); + +/* See the official Android developer guide for more information: + http://developer.android.com/guide/topics/data/data-storage.html +*/ +#define SDL_ANDROID_EXTERNAL_STORAGE_READ 0x01 +#define SDL_ANDROID_EXTERNAL_STORAGE_WRITE 0x02 + +/* Get the path used for internal storage for this application */ +extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(); + +/* Get the current state of external storage, a bitmask of these values: + SDL_ANDROID_EXTERNAL_STORAGE_READ + SDL_ANDROID_EXTERNAL_STORAGE_WRITE + If external storage is currently unavailable, this will return 0. +*/ +extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(); + +/* Get the path used for external storage for this application */ +extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(); + +#endif /* __ANDROID__ */ + /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/core/android/SDL_android.cpp b/src/core/android/SDL_android.cpp index b01735dc3..f78a721fe 100644 --- a/src/core/android/SDL_android.cpp +++ b/src/core/android/SDL_android.cpp @@ -24,6 +24,7 @@ #ifdef __ANDROID__ +#include "SDL_system.h" #include "SDL_android.h" extern "C" { @@ -963,8 +964,6 @@ extern "C" int Android_JNI_ShowTextInput(SDL_Rect *inputRect) /*extern "C" int Android_JNI_HideTextInput() { - - JNIEnv *env = Android_JNI_GetEnv(); if (!env) { return -1; @@ -978,6 +977,155 @@ extern "C" int Android_JNI_ShowTextInput(SDL_Rect *inputRect) return 0; }*/ +////////////////////////////////////////////////////////////////////////////// +// +// Functions exposed to SDL applications in SDL_system.h +// + +extern "C" void *SDL_AndroidGetJNIEnv() +{ + return Android_JNI_GetEnv(); +} + +extern "C" void *SDL_AndroidGetActivity() +{ + LocalReferenceHolder refs; + jmethodID mid; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return NULL; + } + + // return SDLActivity.getContext(); + mid = env->GetStaticMethodID(mActivityClass, + "getContext","()Landroid/content/Context;"); + return env->CallStaticObjectMethod(mActivityClass, mid); +} + +extern "C" const char * SDL_AndroidGetInternalStoragePath() +{ + static char *s_AndroidInternalFilesPath = NULL; + + if (!s_AndroidInternalFilesPath) { + LocalReferenceHolder refs; + jmethodID mid; + jobject context; + jobject fileObject; + jstring pathString; + const char *path; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return NULL; + } + + // context = SDLActivity.getContext(); + mid = env->GetStaticMethodID(mActivityClass, + "getContext","()Landroid/content/Context;"); + context = env->CallStaticObjectMethod(mActivityClass, mid); + + // fileObj = context.getFilesDir(); + mid = env->GetMethodID(env->GetObjectClass(context), + "getFilesDir", "()Ljava/io/File;"); + fileObject = env->CallObjectMethod(context, mid); + if (!fileObject) { + SDL_SetError("Couldn't get internal directory"); + return NULL; + } + + // path = fileObject.getAbsolutePath(); + mid = env->GetMethodID(env->GetObjectClass(fileObject), + "getAbsolutePath", "()Ljava/lang/String;"); + pathString = (jstring)env->CallObjectMethod(fileObject, mid); + + path = env->GetStringUTFChars(pathString, NULL); + s_AndroidInternalFilesPath = SDL_strdup(path); + env->ReleaseStringUTFChars(pathString, path); + } + return s_AndroidInternalFilesPath; +} + +extern "C" int SDL_AndroidGetExternalStorageState() +{ + LocalReferenceHolder refs; + jmethodID mid; + jclass cls; + jstring stateString; + const char *state; + int stateFlags; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return 0; + } + + cls = env->FindClass("android/os/Environment"); + mid = env->GetStaticMethodID(cls, + "getExternalStorageState", "()Ljava/lang/String;"); + stateString = (jstring)env->CallStaticObjectMethod(cls, mid); + + state = env->GetStringUTFChars(stateString, NULL); + + // Print an info message so people debugging know the storage state + __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state); + + if (SDL_strcmp(state, "mounted") == 0) { + stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ | + SDL_ANDROID_EXTERNAL_STORAGE_WRITE; + } else if (SDL_strcmp(state, "mounted_ro") == 0) { + stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ; + } else { + stateFlags = 0; + } + env->ReleaseStringUTFChars(stateString, state); + + return stateFlags; +} + +extern "C" const char * SDL_AndroidGetExternalStoragePath() +{ + static char *s_AndroidExternalFilesPath = NULL; + + if (!s_AndroidExternalFilesPath) { + LocalReferenceHolder refs; + jmethodID mid; + jobject context; + jobject fileObject; + jstring pathString; + const char *path; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return NULL; + } + + // context = SDLActivity.getContext(); + mid = env->GetStaticMethodID(mActivityClass, + "getContext","()Landroid/content/Context;"); + context = env->CallStaticObjectMethod(mActivityClass, mid); + + // fileObj = context.getExternalFilesDir(); + mid = env->GetMethodID(env->GetObjectClass(context), + "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;"); + fileObject = env->CallObjectMethod(context, mid, NULL); + if (!fileObject) { + SDL_SetError("Couldn't get external directory"); + return NULL; + } + + // path = fileObject.getAbsolutePath(); + mid = env->GetMethodID(env->GetObjectClass(fileObject), + "getAbsolutePath", "()Ljava/lang/String;"); + pathString = (jstring)env->CallObjectMethod(fileObject, mid); + + path = env->GetStringUTFChars(pathString, NULL); + s_AndroidExternalFilesPath = SDL_strdup(path); + env->ReleaseStringUTFChars(pathString, path); + } + return s_AndroidExternalFilesPath; +} + #endif /* __ANDROID__ */ /* vi: set ts=4 sw=4 expandtab: */