Android: factorize asset manager code (bug 2131 and 4297)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index c7add21..81bf846 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -356,6 +356,12 @@ static SDL_bool bHasEnvironmentVariables;
static SDL_atomic_t bPermissionRequestPending;
static SDL_bool bPermissionRequestResult;
+/* Android AssetManager */
+static void Internal_Android_Create_AssetManager(void);
+static void Internal_Android_Destroy_AssetManager(void);
+static AAssetManager *asset_manager = NULL;
+static jobject javaAssetManagerRef = 0;
+
/*******************************************************************************
Functions called by JNI
*******************************************************************************/
@@ -1177,6 +1183,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
Android_ResumeSem = NULL;
}
+ Internal_Android_Destroy_AssetManager();
+
str = SDL_GetError();
if (str && str[0]) {
__android_log_print(ANDROID_LOG_ERROR, "SDL", "SDLActivity thread ends (error=%s)", str);
@@ -1799,6 +1807,53 @@ static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
return SDL_FALSE;
}
+static void Internal_Android_Create_AssetManager() {
+
+ struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+ JNIEnv *env = Android_JNI_GetEnv();
+ jmethodID mid;
+ jobject context;
+ jobject javaAssetManager;
+
+ if (!LocalReferenceHolder_Init(&refs, env)) {
+ LocalReferenceHolder_Cleanup(&refs);
+ return;
+ }
+
+ /* context = SDLActivity.getContext(); */
+ context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
+
+ /* javaAssetManager = context.getAssets(); */
+ mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
+ "getAssets", "()Landroid/content/res/AssetManager;");
+ javaAssetManager = (*env)->CallObjectMethod(env, context, mid);
+
+ /**
+ * Given a Dalvik AssetManager object, obtain the corresponding native AAssetManager
+ * object. Note that the caller is responsible for obtaining and holding a VM reference
+ * to the jobject to prevent its being garbage collected while the native object is
+ * in use.
+ */
+ javaAssetManagerRef = (*env)->NewGlobalRef(env, javaAssetManager);
+ asset_manager = AAssetManager_fromJava(env, javaAssetManagerRef);
+
+ if (asset_manager == NULL) {
+ (*env)->DeleteGlobalRef(env, javaAssetManagerRef);
+ Android_JNI_ExceptionOccurred(SDL_TRUE);
+ }
+
+ LocalReferenceHolder_Cleanup(&refs);
+}
+
+static void Internal_Android_Destroy_AssetManager() {
+ JNIEnv *env = Android_JNI_GetEnv();
+
+ if (asset_manager) {
+ (*env)->DeleteGlobalRef(env, javaAssetManagerRef);
+ asset_manager = NULL;
+ }
+}
+
static int Internal_Android_JNI_FileOpen(SDL_RWops *ctx)
{
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
@@ -2800,50 +2855,32 @@ SDL_bool Android_JNI_RequestPermission(const char *permission)
int Android_JNI_GetLocale(char *buf, size_t buflen)
{
- struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
- JNIEnv* env = Android_JNI_GetEnv();
- int retval = -1;
-
- JNIEnv *mEnv = Android_JNI_GetEnv();
- if (!LocalReferenceHolder_Init(&refs, env)) {
- LocalReferenceHolder_Cleanup(&refs);
- return -1;
- }
+ AConfiguration *cfg;
SDL_assert(buflen > 6);
- jmethodID mid;
- jobject context;
- jobject assetManager;
-
- /* context = SDLActivity.getContext(); */
- mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
- "getContext","()Landroid/content/Context;");
- context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
-
- /* assetManager = context.getAssets(); */
- mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
- "getAssets", "()Landroid/content/res/AssetManager;");
- assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
+ if (asset_manager == NULL) {
+ Internal_Android_Create_AssetManager();
+ }
+ if (asset_manager == NULL) {
+ return -1;
+ }
- /* API from NDK: android/configuration.h */
- /* API from NDK: android/asset_manager_jni.h */
- AAssetManager* asset_mgr = AAssetManager_fromJava(env, assetManager);
- AConfiguration *cfg = AConfiguration_new();
+ cfg = AConfiguration_new();
+ if (cfg == NULL) {
+ return -1;
+ }
- if (asset_mgr && cfg)
{
char language[2] = {};
char country[2] = {};
size_t id = 0;
- AConfiguration_fromAssetManager(cfg, asset_mgr);
+ AConfiguration_fromAssetManager(cfg, asset_manager);
AConfiguration_getLanguage(cfg, language);
AConfiguration_getCountry(cfg, country);
- retval = 0;
-
/* copy language (not null terminated) */
if (language[0]) {
buf[id++] = language[0];
@@ -2866,12 +2903,9 @@ int Android_JNI_GetLocale(char *buf, size_t buflen)
SDL_assert(id <= buflen);
}
- if (cfg) {
- AConfiguration_delete(cfg);
- }
+ AConfiguration_delete(cfg);
- LocalReferenceHolder_Cleanup(&refs);
- return retval;
+ return 0;
}
#endif /* __ANDROID__ */