Skip to content

Commit

Permalink
Fixed bug 3917 - Android, issues with getManifestEnvironmentVariable
Browse files Browse the repository at this point in the history
We're going to push the manifest environment variables from the Java side instead of continually querying for them from the native side.
  • Loading branch information
slouken committed Nov 4, 2017
1 parent 7334a2a commit 758156a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 61 deletions.
30 changes: 17 additions & 13 deletions android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
Expand Up @@ -512,6 +512,8 @@ public static native void onNativeTouch(int touchDevId, int pointerFingerId,
public static native void onNativeSurfaceChanged();
public static native void onNativeSurfaceDestroyed();
public static native String nativeGetHint(String name);
public static native void nativeSetenv(String name, String value);
public static native void nativeEnvironmentVariablesSet();

/**
* This method is called by SDL using JNI.
Expand Down Expand Up @@ -616,23 +618,25 @@ public static DisplayMetrics getDisplayDPI() {
/**
* This method is called by SDL using JNI.
*/
public static String getManifestEnvironmentVariable(String variableName) {
public static void getManifestEnvironmentVariables() {
try {
ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo.metaData == null) {
return null;
Bundle bundle = applicationInfo.metaData;
if (bundle == null) {
return;
}

String key = "SDL_ENV." + variableName;
if (!applicationInfo.metaData.containsKey(key)) {
return null;
String prefix = "SDL_ENV.";
final int trimLength = prefix.length();
for (String key : bundle.keySet()) {
if (key.startsWith(prefix)) {
String name = key.substring(trimLength);
String value = bundle.get(key).toString();
nativeSetenv(name, value);
}
}

return applicationInfo.metaData.get(key).toString();
}
catch (PackageManager.NameNotFoundException e)
{
return null;
nativeEnvironmentVariablesSet();
} catch (Exception e) {
Log.v("SDL", "exception " + e.toString());
}
}

Expand Down
76 changes: 41 additions & 35 deletions src/core/android/SDL_android.c
Expand Up @@ -128,6 +128,13 @@ JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
JNIEnv* env, jclass cls,
jstring name);

JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
JNIEnv* env, jclass cls,
jstring name, jstring value);

JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeEnvironmentVariablesSet)(
JNIEnv* env, jclass cls);

/* Java class SDLInputConnection */
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
JNIEnv* env, jclass cls,
Expand Down Expand Up @@ -213,7 +220,7 @@ static jmethodID midClipboardSetText;
static jmethodID midClipboardGetText;
static jmethodID midClipboardHasText;
static jmethodID midOpenAPKExpansionInputStream;
static jmethodID midGetManifestEnvironmentVariable;
static jmethodID midGetManifestEnvironmentVariables;
static jmethodID midGetDisplayDPI;

/* audio manager */
Expand Down Expand Up @@ -244,6 +251,8 @@ static jfieldID fidSeparateMouseAndTouch;
static float fLastAccelerometer[3];
static SDL_bool bHasNewData;

static SDL_bool bHasEnvironmentVariables;

/*******************************************************************************
Functions called by JNI
*******************************************************************************/
Expand Down Expand Up @@ -314,16 +323,16 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
midOpenAPKExpansionInputStream = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");

midGetManifestEnvironmentVariable = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"getManifestEnvironmentVariable", "(Ljava/lang/String;)Ljava/lang/String;");
midGetManifestEnvironmentVariables = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"getManifestEnvironmentVariables", "()V");

midGetDisplayDPI = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "getDisplayDPI", "()Landroid/util/DisplayMetrics;");

if (!midGetNativeSurface ||
!midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
!midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
!midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
!midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
!midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariable || !midGetDisplayDPI) {
!midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables|| !midGetDisplayDPI) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
}

Expand Down Expand Up @@ -808,6 +817,26 @@ JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
return result;
}

JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
JNIEnv* env, jclass cls,
jstring name, jstring value)
{
const char *utfname = (*env)->GetStringUTFChars(env, name, NULL);
const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL);

SDL_setenv(utfname, utfvalue, 1);

(*env)->ReleaseStringUTFChars(env, name, utfname);
(*env)->ReleaseStringUTFChars(env, value, utfvalue);

}

JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeEnvironmentVariablesSet)(
JNIEnv* env, jclass cls)
{
bHasEnvironmentVariables = SDL_TRUE;
}

/*******************************************************************************
Functions called by SDL into Java
*******************************************************************************/
Expand Down Expand Up @@ -2105,40 +2134,17 @@ const char * SDL_AndroidGetExternalStoragePath(void)
return s_AndroidExternalFilesPath;
}

// Ugh, but we have to SDL_strdup() our result to pass it safely back
// out into normal SDL_getenv flow. So we'll just do the same sort
// of trick as on Win32 over in SDL_getenv.c.
char *SDL_AndroidEnvMem;

char *SDL_AndroidGetManifestEnvironmentVariable(const char *variableName)
void Android_JNI_GetManifestEnvironmentVariables(void)
{
if ((mActivityClass == NULL) || (midGetManifestEnvironmentVariable == 0)) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "request to get environment variable before JNI is ready: %s", variableName);
return NULL;
}

JNIEnv *env = Android_JNI_GetEnv();

jstring jVariableName = (*env)->NewStringUTF(env, variableName);
jstring jResult = (jstring)((*env)->CallStaticObjectMethod(env, mActivityClass, midGetManifestEnvironmentVariable, jVariableName));
(*env)->DeleteLocalRef(env, jVariableName);

if (jResult == NULL) {
return NULL;
if (!mActivityClass || !midGetManifestEnvironmentVariables) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "Request to get environment variables before JNI is ready");
return;
}

if (SDL_AndroidEnvMem) {
SDL_free(SDL_AndroidEnvMem);
SDL_AndroidEnvMem = NULL;
if (!bHasEnvironmentVariables) {
JNIEnv *env = Android_JNI_GetEnv();
(*env)->CallStaticVoidMethod(env, mActivityClass, midGetManifestEnvironmentVariables);
}

const char *result = (*env)->GetStringUTFChars(env, jResult, NULL);
SDL_AndroidEnvMem = SDL_strdup(result);
(*env)->ReleaseStringUTFChars(env, jResult, result);
(*env)->DeleteLocalRef(env, jResult);

__android_log_print(ANDROID_LOG_INFO, "SDL", "environment variable in metadata: %s = %s", variableName, SDL_AndroidEnvMem);
return SDL_AndroidEnvMem;
}

#endif /* __ANDROID__ */
Expand Down
2 changes: 1 addition & 1 deletion src/core/android/SDL_android.h
Expand Up @@ -62,7 +62,7 @@ size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, si
int Android_JNI_FileClose(SDL_RWops* ctx);

/* Environment support */
char *SDL_AndroidGetManifestEnvironmentVariable(const char *variableName);
void Android_JNI_GetManifestEnvironmentVariables(void);

/* Clipboard support */
int Android_JNI_SetClipboardText(const char* text);
Expand Down
18 changes: 6 additions & 12 deletions src/stdlib/SDL_getenv.c
Expand Up @@ -171,23 +171,17 @@ SDL_setenv(const char *name, const char *value, int overwrite)
#endif

/* Retrieve a variable named "name" from the environment */
#if defined(__ANDROID__)
#if defined(HAVE_GETENV)
char *
SDL_getenv(const char *name)
{
/* Input validation */
if (!name || SDL_strlen(name)==0) {
return NULL;
}
#if defined(__ANDROID__)
/* Make sure variables from the application manifest are available */
Android_JNI_GetManifestEnvironmentVariables();
#endif

return SDL_AndroidGetManifestEnvironmentVariable(name);
}
#elif defined(HAVE_GETENV)
char *
SDL_getenv(const char *name)
{
/* Input validation */
if (!name || SDL_strlen(name)==0) {
if (!name || !*name) {
return NULL;
}

Expand Down

0 comments on commit 758156a

Please sign in to comment.