Added the ability to set SDL hints from AndroidManifest.xml (thanks Rachel!)
authorSam Lantinga <slouken@libsdl.org>
Tue, 24 Oct 2017 00:17:07 -0700
changeset 116534130b92b6be4
parent 11652 c3bf2954de06
child 11654 64ae77236054
Added the ability to set SDL hints from AndroidManifest.xml (thanks Rachel!)
This is especially useful for things like the accelerometer hint which could be needed before application main().
android-project/app/src/main/AndroidManifest.xml
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/AndroidManifest.xml	Tue Oct 24 00:04:40 2017 -0700
     1.2 +++ b/android-project/app/src/main/AndroidManifest.xml	Tue Oct 24 00:17:07 2017 -0700
     1.3 @@ -8,6 +8,10 @@
     1.4      android:versionName="1.0"
     1.5      android:installLocation="auto">
     1.6  
     1.7 +    <!-- Example of setting SDL hints from AndroidManifest.xml:
     1.8 +    <meta-data android:value="0" android:name="SDL_ENV.SDL_ACCELEROMETER_AS_JOYSTICK"/>
     1.9 +     -->
    1.10 +     
    1.11      <!-- Android 4.0.1 -->
    1.12      <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="16" />
    1.13  
     2.1 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Tue Oct 24 00:04:40 2017 -0700
     2.2 +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Tue Oct 24 00:17:07 2017 -0700
     2.3 @@ -24,6 +24,8 @@
     2.4  import android.graphics.drawable.Drawable;
     2.5  import android.hardware.*;
     2.6  import android.content.pm.ActivityInfo;
     2.7 +import android.content.pm.PackageManager;
     2.8 +import android.content.pm.ApplicationInfo;
     2.9  
    2.10  /**
    2.11      SDL Activity
    2.12 @@ -613,6 +615,29 @@
    2.13          return SDL.getContext();
    2.14      }
    2.15  
    2.16 +    /**
    2.17 +     * This method is called by SDL using JNI.
    2.18 +     */
    2.19 +    public static String getManifestEnvironmentVariable(String variableName) {
    2.20 +        try {
    2.21 +            ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA);
    2.22 +            if (applicationInfo.metaData == null) {
    2.23 +                return null;
    2.24 +            }
    2.25 +
    2.26 +            String key = "SDL_ENV." + variableName;
    2.27 +            if (!applicationInfo.metaData.containsKey(key)) {
    2.28 +                return null;
    2.29 +            }
    2.30 +
    2.31 +            return applicationInfo.metaData.get(key).toString();
    2.32 +        }
    2.33 +        catch (PackageManager.NameNotFoundException e)
    2.34 +        {
    2.35 +            return null;
    2.36 +        }
    2.37 +    }
    2.38 +
    2.39      static class ShowTextInputTask implements Runnable {
    2.40          /*
    2.41           * This is used to regulate the pan&scan method to have some offset from
     3.1 --- a/src/core/android/SDL_android.c	Tue Oct 24 00:04:40 2017 -0700
     3.2 +++ b/src/core/android/SDL_android.c	Tue Oct 24 00:17:07 2017 -0700
     3.3 @@ -211,6 +211,7 @@
     3.4  static jmethodID midClipboardGetText;
     3.5  static jmethodID midClipboardHasText;
     3.6  static jmethodID midOpenAPKExpansionInputStream;
     3.7 +static jmethodID midGetManifestEnvironmentVariable;
     3.8  
     3.9  /* audio manager */
    3.10  static jclass mAudioManagerClass;
    3.11 @@ -310,11 +311,14 @@
    3.12      midOpenAPKExpansionInputStream = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
    3.13                                  "openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
    3.14  
    3.15 +    midGetManifestEnvironmentVariable = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
    3.16 +                                "getManifestEnvironmentVariable", "(Ljava/lang/String;)Ljava/lang/String;");
    3.17 +
    3.18      if (!midGetNativeSurface ||
    3.19         !midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
    3.20         !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown || 
    3.21         !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
    3.22 -       !midOpenAPKExpansionInputStream) {
    3.23 +       !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariable) {
    3.24          __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
    3.25      }
    3.26  
    3.27 @@ -2034,6 +2038,41 @@
    3.28      return s_AndroidExternalFilesPath;
    3.29  }
    3.30  
    3.31 +// Ugh, but we have to SDL_strdup() our result to pass it safely back
    3.32 +// out into normal SDL_getenv flow.  So we'll just do the same sort
    3.33 +// of trick as on Win32 over in SDL_getenv.c.
    3.34 +char *SDL_AndroidEnvMem;
    3.35 +
    3.36 +char *SDL_AndroidGetManifestEnvironmentVariable(const char *variableName)
    3.37 +{
    3.38 +    if ((mActivityClass == NULL) || (midGetManifestEnvironmentVariable == 0)) {
    3.39 +        __android_log_print(ANDROID_LOG_WARN, "SDL", "request to get environment variable before JNI is ready: %s", variableName);
    3.40 +        return NULL;
    3.41 +    }
    3.42 +
    3.43 +    JNIEnv *env = Android_JNI_GetEnv();
    3.44 +
    3.45 +    jstring jVariableName = (*env)->NewStringUTF(env, variableName);
    3.46 +    jstring jResult = (jstring)((*env)->CallStaticObjectMethod(env, mActivityClass, midGetManifestEnvironmentVariable, jVariableName));
    3.47 +
    3.48 +    if (jResult == NULL) {
    3.49 +        return NULL;        
    3.50 +    }
    3.51 +
    3.52 +    if (SDL_AndroidEnvMem) {
    3.53 +        SDL_free(SDL_AndroidEnvMem);
    3.54 +        SDL_AndroidEnvMem = NULL;
    3.55 +    }
    3.56 +
    3.57 +    const char *result = (*env)->GetStringUTFChars(env, jResult, NULL);
    3.58 +    SDL_AndroidEnvMem = SDL_strdup(result);
    3.59 +    (*env)->ReleaseStringUTFChars(env, jResult, result);
    3.60 +    (*env)->DeleteLocalRef(env, jResult);
    3.61 +
    3.62 +    __android_log_print(ANDROID_LOG_INFO, "SDL", "environment variable in metadata: %s = %s", variableName, SDL_AndroidEnvMem);
    3.63 +    return SDL_AndroidEnvMem;
    3.64 +}
    3.65 +
    3.66  #endif /* __ANDROID__ */
    3.67  
    3.68  /* vi: set ts=4 sw=4 expandtab: */
     4.1 --- a/src/core/android/SDL_android.h	Tue Oct 24 00:04:40 2017 -0700
     4.2 +++ b/src/core/android/SDL_android.h	Tue Oct 24 00:17:07 2017 -0700
     4.3 @@ -59,6 +59,9 @@
     4.4  size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num);
     4.5  int Android_JNI_FileClose(SDL_RWops* ctx);
     4.6  
     4.7 +/* Environment support */
     4.8 +char *SDL_AndroidGetManifestEnvironmentVariable(const char *variableName);
     4.9 +
    4.10  /* Clipboard support */
    4.11  int Android_JNI_SetClipboardText(const char* text);
    4.12  char* Android_JNI_GetClipboardText(void);
     5.1 --- a/src/stdlib/SDL_getenv.c	Tue Oct 24 00:04:40 2017 -0700
     5.2 +++ b/src/stdlib/SDL_getenv.c	Tue Oct 24 00:17:07 2017 -0700
     5.3 @@ -29,6 +29,10 @@
     5.4  #include "../core/windows/SDL_windows.h"
     5.5  #endif
     5.6  
     5.7 +#if defined(__ANDROID__)
     5.8 +#include "../core/android/SDL_android.h"
     5.9 +#endif
    5.10 +
    5.11  #include "SDL_stdinc.h"
    5.12  
    5.13  #if defined(__WIN32__) && (!defined(HAVE_SETENV) || !defined(HAVE_GETENV))
    5.14 @@ -167,7 +171,18 @@
    5.15  #endif
    5.16  
    5.17  /* Retrieve a variable named "name" from the environment */
    5.18 -#if defined(HAVE_GETENV)
    5.19 +#if defined(__ANDROID__)
    5.20 +char *
    5.21 +SDL_getenv(const char *name)
    5.22 +{
    5.23 +    /* Input validation */
    5.24 +    if (!name || SDL_strlen(name)==0) {
    5.25 +        return NULL;
    5.26 +    }
    5.27 +
    5.28 +    return SDL_AndroidGetManifestEnvironmentVariable(name);    
    5.29 +}
    5.30 +#elif defined(HAVE_GETENV)
    5.31  char *
    5.32  SDL_getenv(const char *name)
    5.33  {