Fixed bug 1780 - SDL_RWFromFile() sets an error on Android although a valid SDL_RWops pointer is returned.
authorSam Lantinga <slouken@libsdl.org>
Tue, 02 Apr 2013 07:57:37 -0700
changeset 7045 4be2c24b7de1
parent 7044 30b7b0f09c51
child 7046 8d5636aafd1c
Fixed bug 1780 - SDL_RWFromFile() sets an error on Android although a valid SDL_RWops pointer is returned. Philipp Wiesemann SDL_RWFromFile() sets an error to be queried with SDL_GetError() on Android although a valid SDL_RWops pointer is returned. This happens if the fallback implemented in SDL_android.cpp is used to load compressed assets (see README.android in section "Loading assets") and results in a message like "java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed". I think this is confusing and not needed because the loading works as expected. I attached a patch which changes SDL_android.cpp to not set an error if compressed assets are loaded. In this case also no Exception is queried and no additional string are created.
src/core/android/SDL_android.cpp
--- a/src/core/android/SDL_android.cpp	Tue Apr 02 07:55:25 2013 -0700
+++ b/src/core/android/SDL_android.cpp	Tue Apr 02 07:57:37 2013 -0700
@@ -509,7 +509,8 @@
 }
 
 // Test for an exception and call SDL_SetError with its detail if one occurs
-static bool Android_JNI_ExceptionOccurred()
+// If optional parameter silent is truthy then SDL_SetError() is not called.
+static bool Android_JNI_ExceptionOccurred(bool silent = false)
 {
     SDL_assert(LocalReferenceHolder::IsActive());
     JNIEnv *mEnv = Android_JNI_GetEnv();
@@ -521,27 +522,28 @@
         // Until this happens most JNI operations have undefined behaviour
         mEnv->ExceptionClear();
 
-        jclass exceptionClass = mEnv->GetObjectClass(exception);
-        jclass classClass = mEnv->FindClass("java/lang/Class");
+        if (!silent) {
+            jclass exceptionClass = mEnv->GetObjectClass(exception);
+            jclass classClass = mEnv->FindClass("java/lang/Class");
 
-        mid = mEnv->GetMethodID(classClass, "getName", "()Ljava/lang/String;");
-        jstring exceptionName = (jstring)mEnv->CallObjectMethod(exceptionClass, mid);
-        const char* exceptionNameUTF8 = mEnv->GetStringUTFChars(exceptionName, 0);
+            mid = mEnv->GetMethodID(classClass, "getName", "()Ljava/lang/String;");
+            jstring exceptionName = (jstring)mEnv->CallObjectMethod(exceptionClass, mid);
+            const char* exceptionNameUTF8 = mEnv->GetStringUTFChars(exceptionName, 0);
 
-        mid = mEnv->GetMethodID(exceptionClass, "getMessage", "()Ljava/lang/String;");
-        jstring exceptionMessage = (jstring)mEnv->CallObjectMethod(exception, mid);
+            mid = mEnv->GetMethodID(exceptionClass, "getMessage", "()Ljava/lang/String;");
+            jstring exceptionMessage = (jstring)mEnv->CallObjectMethod(exception, mid);
 
-        if (exceptionMessage != NULL) {
-            const char* exceptionMessageUTF8 = mEnv->GetStringUTFChars(
-                    exceptionMessage, 0);
-            SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
-            mEnv->ReleaseStringUTFChars(exceptionMessage, exceptionMessageUTF8);
-        } else {
-            SDL_SetError("%s", exceptionNameUTF8);
+            if (exceptionMessage != NULL) {
+                const char* exceptionMessageUTF8 = mEnv->GetStringUTFChars(exceptionMessage, 0);
+                SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
+                mEnv->ReleaseStringUTFChars(exceptionMessage, exceptionMessageUTF8);
+            } else {
+                SDL_SetError("%s", exceptionNameUTF8);
+            }
+
+            mEnv->ReleaseStringUTFChars(exceptionName, exceptionNameUTF8);
         }
 
-        mEnv->ReleaseStringUTFChars(exceptionName, exceptionNameUTF8);
-
         return true;
     }
 
@@ -588,19 +590,19 @@
     */
     mid = mEnv->GetMethodID(mEnv->GetObjectClass(assetManager), "openFd", "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
     inputStream = mEnv->CallObjectMethod(assetManager, mid, fileNameJString);
-    if (Android_JNI_ExceptionOccurred()) {
+    if (Android_JNI_ExceptionOccurred(true)) {
         goto fallback;
     }
 
     mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream), "getStartOffset", "()J");
     ctx->hidden.androidio.offset = mEnv->CallLongMethod(inputStream, mid);
-    if (Android_JNI_ExceptionOccurred()) {
+    if (Android_JNI_ExceptionOccurred(true)) {
         goto fallback;
     }
 
     mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream), "getDeclaredLength", "()J");
     ctx->hidden.androidio.size = mEnv->CallLongMethod(inputStream, mid);
-    if (Android_JNI_ExceptionOccurred()) {
+    if (Android_JNI_ExceptionOccurred(true)) {
         goto fallback;
     }