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 70454be2c24b7de1
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
     1.1 --- a/src/core/android/SDL_android.cpp	Tue Apr 02 07:55:25 2013 -0700
     1.2 +++ b/src/core/android/SDL_android.cpp	Tue Apr 02 07:57:37 2013 -0700
     1.3 @@ -509,7 +509,8 @@
     1.4  }
     1.5  
     1.6  // Test for an exception and call SDL_SetError with its detail if one occurs
     1.7 -static bool Android_JNI_ExceptionOccurred()
     1.8 +// If optional parameter silent is truthy then SDL_SetError() is not called.
     1.9 +static bool Android_JNI_ExceptionOccurred(bool silent = false)
    1.10  {
    1.11      SDL_assert(LocalReferenceHolder::IsActive());
    1.12      JNIEnv *mEnv = Android_JNI_GetEnv();
    1.13 @@ -521,27 +522,28 @@
    1.14          // Until this happens most JNI operations have undefined behaviour
    1.15          mEnv->ExceptionClear();
    1.16  
    1.17 -        jclass exceptionClass = mEnv->GetObjectClass(exception);
    1.18 -        jclass classClass = mEnv->FindClass("java/lang/Class");
    1.19 +        if (!silent) {
    1.20 +            jclass exceptionClass = mEnv->GetObjectClass(exception);
    1.21 +            jclass classClass = mEnv->FindClass("java/lang/Class");
    1.22  
    1.23 -        mid = mEnv->GetMethodID(classClass, "getName", "()Ljava/lang/String;");
    1.24 -        jstring exceptionName = (jstring)mEnv->CallObjectMethod(exceptionClass, mid);
    1.25 -        const char* exceptionNameUTF8 = mEnv->GetStringUTFChars(exceptionName, 0);
    1.26 +            mid = mEnv->GetMethodID(classClass, "getName", "()Ljava/lang/String;");
    1.27 +            jstring exceptionName = (jstring)mEnv->CallObjectMethod(exceptionClass, mid);
    1.28 +            const char* exceptionNameUTF8 = mEnv->GetStringUTFChars(exceptionName, 0);
    1.29  
    1.30 -        mid = mEnv->GetMethodID(exceptionClass, "getMessage", "()Ljava/lang/String;");
    1.31 -        jstring exceptionMessage = (jstring)mEnv->CallObjectMethod(exception, mid);
    1.32 +            mid = mEnv->GetMethodID(exceptionClass, "getMessage", "()Ljava/lang/String;");
    1.33 +            jstring exceptionMessage = (jstring)mEnv->CallObjectMethod(exception, mid);
    1.34  
    1.35 -        if (exceptionMessage != NULL) {
    1.36 -            const char* exceptionMessageUTF8 = mEnv->GetStringUTFChars(
    1.37 -                    exceptionMessage, 0);
    1.38 -            SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
    1.39 -            mEnv->ReleaseStringUTFChars(exceptionMessage, exceptionMessageUTF8);
    1.40 -        } else {
    1.41 -            SDL_SetError("%s", exceptionNameUTF8);
    1.42 +            if (exceptionMessage != NULL) {
    1.43 +                const char* exceptionMessageUTF8 = mEnv->GetStringUTFChars(exceptionMessage, 0);
    1.44 +                SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
    1.45 +                mEnv->ReleaseStringUTFChars(exceptionMessage, exceptionMessageUTF8);
    1.46 +            } else {
    1.47 +                SDL_SetError("%s", exceptionNameUTF8);
    1.48 +            }
    1.49 +
    1.50 +            mEnv->ReleaseStringUTFChars(exceptionName, exceptionNameUTF8);
    1.51          }
    1.52  
    1.53 -        mEnv->ReleaseStringUTFChars(exceptionName, exceptionNameUTF8);
    1.54 -
    1.55          return true;
    1.56      }
    1.57  
    1.58 @@ -588,19 +590,19 @@
    1.59      */
    1.60      mid = mEnv->GetMethodID(mEnv->GetObjectClass(assetManager), "openFd", "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
    1.61      inputStream = mEnv->CallObjectMethod(assetManager, mid, fileNameJString);
    1.62 -    if (Android_JNI_ExceptionOccurred()) {
    1.63 +    if (Android_JNI_ExceptionOccurred(true)) {
    1.64          goto fallback;
    1.65      }
    1.66  
    1.67      mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream), "getStartOffset", "()J");
    1.68      ctx->hidden.androidio.offset = mEnv->CallLongMethod(inputStream, mid);
    1.69 -    if (Android_JNI_ExceptionOccurred()) {
    1.70 +    if (Android_JNI_ExceptionOccurred(true)) {
    1.71          goto fallback;
    1.72      }
    1.73  
    1.74      mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream), "getDeclaredLength", "()J");
    1.75      ctx->hidden.androidio.size = mEnv->CallLongMethod(inputStream, mid);
    1.76 -    if (Android_JNI_ExceptionOccurred()) {
    1.77 +    if (Android_JNI_ExceptionOccurred(true)) {
    1.78          goto fallback;
    1.79      }
    1.80