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.
This commit is contained in:
Sam Lantinga 2017-11-04 09:37:29 -07:00
parent 7334a2a1b5
commit 758156a765
4 changed files with 67 additions and 63 deletions

View file

@ -512,6 +512,8 @@ public class SDLActivity extends Activity {
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.
@ -616,23 +618,25 @@ public class SDLActivity extends Activity {
/**
* 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());
}
}

View file

@ -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,
@ -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 */
@ -244,6 +251,8 @@ static jfieldID fidSeparateMouseAndTouch;
static float fLastAccelerometer[3];
static SDL_bool bHasNewData;
static SDL_bool bHasEnvironmentVariables;
/*******************************************************************************
Functions called by JNI
*******************************************************************************/
@ -314,8 +323,8 @@ 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;");
@ -323,7 +332,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
!midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
!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?");
}
@ -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
*******************************************************************************/
@ -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;
if (!mActivityClass || !midGetManifestEnvironmentVariables) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "Request to get environment variables before JNI is ready");
return;
}
if (!bHasEnvironmentVariables) {
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;
(*env)->CallStaticVoidMethod(env, mActivityClass, midGetManifestEnvironmentVariables);
}
if (SDL_AndroidEnvMem) {
SDL_free(SDL_AndroidEnvMem);
SDL_AndroidEnvMem = NULL;
}
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__ */

View file

@ -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);

View file

@ -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(HAVE_GETENV)
char *
SDL_getenv(const char *name)
{
#if defined(__ANDROID__)
char *
SDL_getenv(const char *name)
{
/* Input validation */
if (!name || SDL_strlen(name)==0) {
return NULL;
}
/* 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;
}