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().
This commit is contained in:
Sam Lantinga 2017-10-24 00:17:07 -07:00
parent 45536710f3
commit 8fd0c22adc
5 changed files with 88 additions and 2 deletions

View File

@ -8,6 +8,10 @@
android:versionName="1.0"
android:installLocation="auto">
<!-- Example of setting SDL hints from AndroidManifest.xml:
<meta-data android:value="0" android:name="SDL_ENV.SDL_ACCELEROMETER_AS_JOYSTICK"/>
-->
<!-- Android 4.0.1 -->
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="16" />

View File

@ -24,6 +24,8 @@ import android.graphics.*;
import android.graphics.drawable.Drawable;
import android.hardware.*;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ApplicationInfo;
/**
SDL Activity
@ -613,6 +615,29 @@ public class SDLActivity extends Activity {
return SDL.getContext();
}
/**
* This method is called by SDL using JNI.
*/
public static String getManifestEnvironmentVariable(String variableName) {
try {
ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo.metaData == null) {
return null;
}
String key = "SDL_ENV." + variableName;
if (!applicationInfo.metaData.containsKey(key)) {
return null;
}
return applicationInfo.metaData.get(key).toString();
}
catch (PackageManager.NameNotFoundException e)
{
return null;
}
}
static class ShowTextInputTask implements Runnable {
/*
* This is used to regulate the pan&scan method to have some offset from

View File

@ -211,6 +211,7 @@ static jmethodID midClipboardSetText;
static jmethodID midClipboardGetText;
static jmethodID midClipboardHasText;
static jmethodID midOpenAPKExpansionInputStream;
static jmethodID midGetManifestEnvironmentVariable;
/* audio manager */
static jclass mAudioManagerClass;
@ -310,11 +311,14 @@ 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;");
if (!midGetNativeSurface ||
!midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
!midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
!midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
!midOpenAPKExpansionInputStream) {
!midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariable) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
}
@ -2034,6 +2038,41 @@ 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)
{
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));
if (jResult == NULL) {
return NULL;
}
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__ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -59,6 +59,9 @@ size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer, size_t size, size_t ma
size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num);
int Android_JNI_FileClose(SDL_RWops* ctx);
/* Environment support */
char *SDL_AndroidGetManifestEnvironmentVariable(const char *variableName);
/* Clipboard support */
int Android_JNI_SetClipboardText(const char* text);
char* Android_JNI_GetClipboardText(void);

View File

@ -29,6 +29,10 @@
#include "../core/windows/SDL_windows.h"
#endif
#if defined(__ANDROID__)
#include "../core/android/SDL_android.h"
#endif
#include "SDL_stdinc.h"
#if defined(__WIN32__) && (!defined(HAVE_SETENV) || !defined(HAVE_GETENV))
@ -167,7 +171,18 @@ SDL_setenv(const char *name, const char *value, int overwrite)
#endif
/* Retrieve a variable named "name" from the environment */
#if defined(HAVE_GETENV)
#if defined(__ANDROID__)
char *
SDL_getenv(const char *name)
{
/* Input validation */
if (!name || SDL_strlen(name)==0) {
return NULL;
}
return SDL_AndroidGetManifestEnvironmentVariable(name);
}
#elif defined(HAVE_GETENV)
char *
SDL_getenv(const char *name)
{