Fixed bug 3917 - Android, issues with getManifestEnvironmentVariable
authorSam Lantinga <slouken@libsdl.org>
Sat, 04 Nov 2017 09:37:29 -0700
changeset 116781f10a52295e3
parent 11677 aed6a9ff3c99
child 11679 d25d94d7dd86
Fixed bug 3917 - Android, issues with getManifestEnvironmentVariable

We're going to push the manifest environment variables from the Java side instead of continually querying for them from the native side.
android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
src/core/android/SDL_android.c
src/core/android/SDL_android.h
src/stdlib/SDL_getenv.c
     1.1 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Sat Nov 04 09:07:33 2017 -0700
     1.2 +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Sat Nov 04 09:37:29 2017 -0700
     1.3 @@ -512,6 +512,8 @@
     1.4      public static native void onNativeSurfaceChanged();
     1.5      public static native void onNativeSurfaceDestroyed();
     1.6      public static native String nativeGetHint(String name);
     1.7 +    public static native void nativeSetenv(String name, String value);
     1.8 +    public static native void nativeEnvironmentVariablesSet();
     1.9  
    1.10      /**
    1.11       * This method is called by SDL using JNI.
    1.12 @@ -616,23 +618,25 @@
    1.13      /**
    1.14       * This method is called by SDL using JNI.
    1.15       */
    1.16 -    public static String getManifestEnvironmentVariable(String variableName) {
    1.17 +    public static void getManifestEnvironmentVariables() {
    1.18          try {
    1.19              ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA);
    1.20 -            if (applicationInfo.metaData == null) {
    1.21 -                return null;
    1.22 +            Bundle bundle = applicationInfo.metaData;
    1.23 +            if (bundle == null) {
    1.24 +                return;
    1.25              }
    1.26 -
    1.27 -            String key = "SDL_ENV." + variableName;
    1.28 -            if (!applicationInfo.metaData.containsKey(key)) {
    1.29 -                return null;
    1.30 +			String prefix = "SDL_ENV.";
    1.31 +            final int trimLength = prefix.length();
    1.32 +            for (String key : bundle.keySet()) {
    1.33 +                if (key.startsWith(prefix)) {
    1.34 +                    String name = key.substring(trimLength);
    1.35 +                    String value = bundle.get(key).toString();
    1.36 +                    nativeSetenv(name, value);
    1.37 +                }
    1.38              }
    1.39 -
    1.40 -            return applicationInfo.metaData.get(key).toString();
    1.41 -        }
    1.42 -        catch (PackageManager.NameNotFoundException e)
    1.43 -        {
    1.44 -            return null;
    1.45 +			nativeEnvironmentVariablesSet();
    1.46 +        } catch (Exception e) {
    1.47 +           Log.v("SDL", "exception " + e.toString());
    1.48          }
    1.49      }
    1.50  
     2.1 --- a/src/core/android/SDL_android.c	Sat Nov 04 09:07:33 2017 -0700
     2.2 +++ b/src/core/android/SDL_android.c	Sat Nov 04 09:37:29 2017 -0700
     2.3 @@ -128,6 +128,13 @@
     2.4          JNIEnv* env, jclass cls,
     2.5          jstring name);
     2.6  
     2.7 +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
     2.8 +        JNIEnv* env, jclass cls,
     2.9 +        jstring name, jstring value);
    2.10 +
    2.11 +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeEnvironmentVariablesSet)(
    2.12 +        JNIEnv* env, jclass cls);
    2.13 +
    2.14  /* Java class SDLInputConnection */
    2.15  JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
    2.16          JNIEnv* env, jclass cls,
    2.17 @@ -213,7 +220,7 @@
    2.18  static jmethodID midClipboardGetText;
    2.19  static jmethodID midClipboardHasText;
    2.20  static jmethodID midOpenAPKExpansionInputStream;
    2.21 -static jmethodID midGetManifestEnvironmentVariable;
    2.22 +static jmethodID midGetManifestEnvironmentVariables;
    2.23  static jmethodID midGetDisplayDPI;
    2.24  
    2.25  /* audio manager */
    2.26 @@ -244,6 +251,8 @@
    2.27  static float fLastAccelerometer[3];
    2.28  static SDL_bool bHasNewData;
    2.29  
    2.30 +static SDL_bool bHasEnvironmentVariables;
    2.31 +
    2.32  /*******************************************************************************
    2.33                   Functions called by JNI
    2.34  *******************************************************************************/
    2.35 @@ -314,16 +323,16 @@
    2.36      midOpenAPKExpansionInputStream = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
    2.37                                  "openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
    2.38  
    2.39 -    midGetManifestEnvironmentVariable = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
    2.40 -                                "getManifestEnvironmentVariable", "(Ljava/lang/String;)Ljava/lang/String;");
    2.41 +    midGetManifestEnvironmentVariables = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
    2.42 +                                "getManifestEnvironmentVariables", "()V");
    2.43  
    2.44      midGetDisplayDPI = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "getDisplayDPI", "()Landroid/util/DisplayMetrics;");
    2.45  
    2.46      if (!midGetNativeSurface ||
    2.47         !midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
    2.48 -       !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown || 
    2.49 +       !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
    2.50         !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
    2.51 -       !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariable || !midGetDisplayDPI) {
    2.52 +       !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables|| !midGetDisplayDPI) {
    2.53          __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
    2.54      }
    2.55  
    2.56 @@ -808,6 +817,26 @@
    2.57      return result;
    2.58  }
    2.59  
    2.60 +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
    2.61 +                                    JNIEnv* env, jclass cls,
    2.62 +                                    jstring name, jstring value)
    2.63 +{
    2.64 +    const char *utfname = (*env)->GetStringUTFChars(env, name, NULL);
    2.65 +    const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL);
    2.66 +
    2.67 +    SDL_setenv(utfname, utfvalue, 1);
    2.68 +
    2.69 +    (*env)->ReleaseStringUTFChars(env, name, utfname);
    2.70 +    (*env)->ReleaseStringUTFChars(env, value, utfvalue);
    2.71 +
    2.72 +}
    2.73 +
    2.74 +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeEnvironmentVariablesSet)(
    2.75 +        JNIEnv* env, jclass cls)
    2.76 +{
    2.77 +    bHasEnvironmentVariables = SDL_TRUE;
    2.78 +}
    2.79 +
    2.80  /*******************************************************************************
    2.81               Functions called by SDL into Java
    2.82  *******************************************************************************/
    2.83 @@ -2105,40 +2134,17 @@
    2.84      return s_AndroidExternalFilesPath;
    2.85  }
    2.86  
    2.87 -// Ugh, but we have to SDL_strdup() our result to pass it safely back
    2.88 -// out into normal SDL_getenv flow.  So we'll just do the same sort
    2.89 -// of trick as on Win32 over in SDL_getenv.c.
    2.90 -char *SDL_AndroidEnvMem;
    2.91 -
    2.92 -char *SDL_AndroidGetManifestEnvironmentVariable(const char *variableName)
    2.93 +void Android_JNI_GetManifestEnvironmentVariables(void)
    2.94  {
    2.95 -    if ((mActivityClass == NULL) || (midGetManifestEnvironmentVariable == 0)) {
    2.96 -        __android_log_print(ANDROID_LOG_WARN, "SDL", "request to get environment variable before JNI is ready: %s", variableName);
    2.97 -        return NULL;
    2.98 +    if (!mActivityClass || !midGetManifestEnvironmentVariables) {
    2.99 +        __android_log_print(ANDROID_LOG_WARN, "SDL", "Request to get environment variables before JNI is ready");
   2.100 +        return;
   2.101      }
   2.102  
   2.103 -    JNIEnv *env = Android_JNI_GetEnv();
   2.104 -
   2.105 -    jstring jVariableName = (*env)->NewStringUTF(env, variableName);
   2.106 -    jstring jResult = (jstring)((*env)->CallStaticObjectMethod(env, mActivityClass, midGetManifestEnvironmentVariable, jVariableName));
   2.107 -    (*env)->DeleteLocalRef(env, jVariableName);
   2.108 -
   2.109 -    if (jResult == NULL) {
   2.110 -        return NULL;        
   2.111 +    if (!bHasEnvironmentVariables) {
   2.112 +        JNIEnv *env = Android_JNI_GetEnv();
   2.113 +        (*env)->CallStaticVoidMethod(env, mActivityClass, midGetManifestEnvironmentVariables);
   2.114      }
   2.115 -
   2.116 -    if (SDL_AndroidEnvMem) {
   2.117 -        SDL_free(SDL_AndroidEnvMem);
   2.118 -        SDL_AndroidEnvMem = NULL;
   2.119 -    }
   2.120 -
   2.121 -    const char *result = (*env)->GetStringUTFChars(env, jResult, NULL);
   2.122 -    SDL_AndroidEnvMem = SDL_strdup(result);
   2.123 -    (*env)->ReleaseStringUTFChars(env, jResult, result);
   2.124 -    (*env)->DeleteLocalRef(env, jResult);
   2.125 -
   2.126 -    __android_log_print(ANDROID_LOG_INFO, "SDL", "environment variable in metadata: %s = %s", variableName, SDL_AndroidEnvMem);
   2.127 -    return SDL_AndroidEnvMem;
   2.128  }
   2.129  
   2.130  #endif /* __ANDROID__ */
     3.1 --- a/src/core/android/SDL_android.h	Sat Nov 04 09:07:33 2017 -0700
     3.2 +++ b/src/core/android/SDL_android.h	Sat Nov 04 09:37:29 2017 -0700
     3.3 @@ -62,7 +62,7 @@
     3.4  int Android_JNI_FileClose(SDL_RWops* ctx);
     3.5  
     3.6  /* Environment support */
     3.7 -char *SDL_AndroidGetManifestEnvironmentVariable(const char *variableName);
     3.8 +void Android_JNI_GetManifestEnvironmentVariables(void);
     3.9  
    3.10  /* Clipboard support */
    3.11  int Android_JNI_SetClipboardText(const char* text);
     4.1 --- a/src/stdlib/SDL_getenv.c	Sat Nov 04 09:07:33 2017 -0700
     4.2 +++ b/src/stdlib/SDL_getenv.c	Sat Nov 04 09:37:29 2017 -0700
     4.3 @@ -171,23 +171,17 @@
     4.4  #endif
     4.5  
     4.6  /* Retrieve a variable named "name" from the environment */
     4.7 -#if defined(__ANDROID__)
     4.8 +#if defined(HAVE_GETENV)
     4.9  char *
    4.10  SDL_getenv(const char *name)
    4.11  {
    4.12 +#if defined(__ANDROID__)
    4.13 +    /* Make sure variables from the application manifest are available */
    4.14 +    Android_JNI_GetManifestEnvironmentVariables();
    4.15 +#endif
    4.16 +
    4.17      /* Input validation */
    4.18 -    if (!name || SDL_strlen(name)==0) {
    4.19 -        return NULL;
    4.20 -    }
    4.21 -
    4.22 -    return SDL_AndroidGetManifestEnvironmentVariable(name);    
    4.23 -}
    4.24 -#elif defined(HAVE_GETENV)
    4.25 -char *
    4.26 -SDL_getenv(const char *name)
    4.27 -{
    4.28 -    /* Input validation */
    4.29 -    if (!name || SDL_strlen(name)==0) {
    4.30 +    if (!name || !*name) {
    4.31          return NULL;
    4.32      }
    4.33