21 #include "../../SDL_internal.h" 33 #include "keyinfotable.h" 35 #include "../../events/SDL_events_c.h" 36 #include "../../video/android/SDL_androidkeyboard.h" 37 #include "../../video/android/SDL_androidmouse.h" 38 #include "../../video/android/SDL_androidtouch.h" 39 #include "../../video/android/SDL_androidvideo.h" 40 #include "../../video/android/SDL_androidwindow.h" 41 #include "../../joystick/android/SDL_sysjoystick_c.h" 42 #include "../../haptic/android/SDL_syshaptic_c.h" 44 #include <android/log.h> 46 #include <sys/types.h> 52 #define LOGI(...) do {} while (0) 53 #define LOGE(...) do {} while (0) 56 #define SDL_JAVA_PREFIX org_libsdl_app 57 #define CONCAT1(prefix, class, function) CONCAT2(prefix, class, function) 58 #define CONCAT2(prefix, class, function) Java_ ## prefix ## _ ## class ## _ ## function 59 #define SDL_JAVA_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLActivity, function) 60 #define SDL_JAVA_AUDIO_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLAudioManager, function) 61 #define SDL_JAVA_CONTROLLER_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLControllerManager, function) 62 #define SDL_JAVA_INTERFACE_INPUT_CONNECTION(function) CONCAT1(SDL_JAVA_PREFIX, SDLInputConnection, function) 66 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(
67 JNIEnv* mEnv, jclass cls);
69 JNIEXPORT
int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(
70 JNIEnv* env, jclass cls,
71 jstring library, jstring
function, jobject
array);
73 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
74 JNIEnv* env, jclass jcls,
77 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
78 JNIEnv* env, jclass jcls,
81 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
82 JNIEnv* env, jclass jcls);
84 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(
85 JNIEnv* env, jclass jcls);
87 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)(
88 JNIEnv* env, jclass jcls,
91 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)(
92 JNIEnv* env, jclass jcls,
95 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)(
96 JNIEnv* env, jclass jcls);
98 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
99 JNIEnv* env, jclass jcls,
100 jint touch_device_id_in, jint pointer_finger_id_in,
101 jint action, jfloat
x, jfloat
y, jfloat
p);
103 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
104 JNIEnv* env, jclass jcls,
105 jint
button, jint action, jfloat
x, jfloat
y);
107 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
108 JNIEnv* env, jclass jcls,
109 jfloat
x, jfloat
y, jfloat
z);
111 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeClipboardChanged)(
112 JNIEnv* env, jclass jcls);
114 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeLowMemory)(
115 JNIEnv* env, jclass cls);
117 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
118 JNIEnv* env, jclass cls);
120 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativePause)(
121 JNIEnv* env, jclass cls);
123 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
124 JNIEnv* env, jclass cls);
126 JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
127 JNIEnv* env, jclass cls,
130 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
131 JNIEnv* env, jclass cls,
134 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeEnvironmentVariablesSet)(
135 JNIEnv* env, jclass cls);
138 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
139 JNIEnv* env, jclass cls,
140 jstring
text, jint newCursorPosition);
142 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
143 JNIEnv* env, jclass cls,
144 jstring
text, jint newCursorPosition);
147 JNIEXPORT
void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(
148 JNIEnv *env, jclass jcls);
151 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(
152 JNIEnv *env, jclass jcls);
154 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
155 JNIEnv* env, jclass jcls,
156 jint device_id, jint keycode);
158 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
159 JNIEnv* env, jclass jcls,
160 jint device_id, jint keycode);
162 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
163 JNIEnv* env, jclass jcls,
164 jint device_id, jint
axis, jfloat
value);
166 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
167 JNIEnv* env, jclass jcls,
168 jint device_id, jint hat_id, jint
x, jint
y);
170 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
171 JNIEnv* env, jclass jcls,
172 jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
173 jint nbuttons, jint naxes, jint nhats, jint nballs);
175 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
176 JNIEnv* env, jclass jcls,
179 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
180 JNIEnv* env, jclass jcls,
181 jint device_id, jstring device_name);
183 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
184 JNIEnv* env, jclass jcls,
192 static void Android_JNI_ThreadDestroyed(
void*);
203 static pthread_key_t mThreadKey;
204 static JavaVM* mJavaVM;
207 static jclass mActivityClass;
210 static jmethodID midGetNativeSurface;
211 static jmethodID midSetActivityTitle;
212 static jmethodID midSetWindowStyle;
213 static jmethodID midSetOrientation;
214 static jmethodID midGetContext;
215 static jmethodID midIsAndroidTV;
216 static jmethodID midInputGetInputDeviceIds;
217 static jmethodID midSendMessage;
218 static jmethodID midShowTextInput;
219 static jmethodID midIsScreenKeyboardShown;
220 static jmethodID midClipboardSetText;
221 static jmethodID midClipboardGetText;
222 static jmethodID midClipboardHasText;
223 static jmethodID midOpenAPKExpansionInputStream;
224 static jmethodID midGetManifestEnvironmentVariables;
225 static jmethodID midGetDisplayDPI;
228 static jclass mAudioManagerClass;
231 static jmethodID midAudioOpen;
232 static jmethodID midAudioWriteShortBuffer;
233 static jmethodID midAudioWriteByteBuffer;
234 static jmethodID midAudioClose;
235 static jmethodID midCaptureOpen;
236 static jmethodID midCaptureReadShortBuffer;
237 static jmethodID midCaptureReadByteBuffer;
238 static jmethodID midCaptureClose;
241 static jclass mControllerManagerClass;
244 static jmethodID midPollInputDevices;
245 static jmethodID midPollHapticDevices;
246 static jmethodID midHapticRun;
249 static jfieldID fidSeparateMouseAndTouch;
252 static float fLastAccelerometer[3];
262 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,
void* reserved)
266 LOGI(
"JNI_OnLoad called");
267 if ((*mJavaVM)->GetEnv(mJavaVM, (
void**) &env, JNI_VERSION_1_4) != JNI_OK) {
268 LOGE(
"Failed to get the environment using GetEnv()");
275 if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed) != 0) {
276 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"Error initializing pthread key");
280 return JNI_VERSION_1_4;
285 if (!mActivityClass || !mAudioManagerClass || !mControllerManagerClass) {
294 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
296 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeSetupJNI()");
300 mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
302 midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
303 "getNativeSurface",
"()Landroid/view/Surface;");
304 midSetActivityTitle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
305 "setActivityTitle",
"(Ljava/lang/String;)Z");
306 midSetWindowStyle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
307 "setWindowStyle",
"(Z)V");
308 midSetOrientation = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
309 "setOrientation",
"(IIZLjava/lang/String;)V");
310 midGetContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
311 "getContext",
"()Landroid/content/Context;");
312 midIsAndroidTV = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
313 "isAndroidTV",
"()Z");
314 midInputGetInputDeviceIds = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
315 "inputGetInputDeviceIds",
"(I)[I");
316 midSendMessage = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
317 "sendMessage",
"(II)Z");
318 midShowTextInput = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
319 "showTextInput",
"(IIII)Z");
320 midIsScreenKeyboardShown = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
321 "isScreenKeyboardShown",
"()Z");
322 midClipboardSetText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
323 "clipboardSetText",
"(Ljava/lang/String;)V");
324 midClipboardGetText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
325 "clipboardGetText",
"()Ljava/lang/String;");
326 midClipboardHasText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
327 "clipboardHasText",
"()Z");
328 midOpenAPKExpansionInputStream = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
329 "openAPKExpansionInputStream",
"(Ljava/lang/String;)Ljava/io/InputStream;");
331 midGetManifestEnvironmentVariables = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
332 "getManifestEnvironmentVariables",
"()Z");
334 midGetDisplayDPI = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"getDisplayDPI",
"()Landroid/util/DisplayMetrics;");
335 midGetDisplayDPI = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"getDisplayDPI",
"()Landroid/util/DisplayMetrics;");
337 if (!midGetNativeSurface ||
338 !midSetActivityTitle || !midSetWindowStyle || !midSetOrientation || !midGetContext || !midIsAndroidTV || !midInputGetInputDeviceIds ||
339 !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
340 !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
341 !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables|| !midGetDisplayDPI) {
342 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
345 fidSeparateMouseAndTouch = (*mEnv)->GetStaticFieldID(mEnv, mActivityClass,
"mSeparateMouseAndTouch",
"Z");
347 if (!fidSeparateMouseAndTouch) {
348 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java static fields, do you have the latest version of SDLActivity.java?");
355 JNIEXPORT
void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
357 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"AUDIO nativeSetupJNI()");
361 mAudioManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
363 midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
364 "audioOpen",
"(IZZI)I");
365 midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
366 "audioWriteShortBuffer",
"([S)V");
367 midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
368 "audioWriteByteBuffer",
"([B)V");
369 midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
370 "audioClose",
"()V");
371 midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
372 "captureOpen",
"(IZZI)I");
373 midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
374 "captureReadShortBuffer",
"([SZ)I");
375 midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
376 "captureReadByteBuffer",
"([BZ)I");
377 midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
378 "captureClose",
"()V");
380 if (!midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
381 !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose) {
382 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?");
389 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
391 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"CONTROLLER nativeSetupJNI()");
395 mControllerManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
397 midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
398 "pollInputDevices",
"()V");
399 midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
400 "pollHapticDevices",
"()V");
401 midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
402 "hapticRun",
"(II)V");
404 if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun) {
405 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
412 typedef int (*SDL_main_func)(
int argc,
char *argv[]);
415 JNIEXPORT
int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv* env, jclass cls, jstring library, jstring
function, jobject
array)
418 const char *library_file;
419 void *library_handle;
421 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeRunMain()");
423 library_file = (*env)->GetStringUTFChars(env, library,
NULL);
424 library_handle = dlopen(library_file, RTLD_GLOBAL);
425 if (library_handle) {
426 const char *function_name;
429 function_name = (*env)->GetStringUTFChars(env,
function,
NULL);
430 SDL_main = (SDL_main_func)dlsym(library_handle, function_name);
438 len = (*env)->GetArrayLength(env,
array);
445 for (i = 0; i <
len; ++
i) {
448 jstring
string = (*env)->GetObjectArrayElement(env,
array, i);
450 utf = (*env)->GetStringUTFChars(env,
string, 0);
453 (*env)->ReleaseStringUTFChars(env,
string, utf);
455 (*env)->DeleteLocalRef(env,
string);
469 for (i = 0; i < argc; ++
i) {
475 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"nativeRunMain(): Couldn't find function %s in library %s", function_name, library_file);
477 (*env)->ReleaseStringUTFChars(env,
function, function_name);
479 dlclose(library_handle);
482 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"nativeRunMain(): Couldn't load library %s", library_file);
484 (*env)->ReleaseStringUTFChars(env, library, library_file);
493 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
494 JNIEnv* env, jclass jcls,
499 (*env)->ReleaseStringUTFChars(env,
filename, path);
504 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
505 JNIEnv* env, jclass jcls,
512 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
513 JNIEnv* env, jclass jcls,
514 jint device_id, jint keycode)
516 return Android_OnPadDown(device_id, keycode);
520 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
521 JNIEnv* env, jclass jcls,
522 jint device_id, jint keycode)
524 return Android_OnPadUp(device_id, keycode);
528 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
529 JNIEnv* env, jclass jcls,
532 Android_OnJoy(device_id, axis,
value);
536 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
537 JNIEnv* env, jclass jcls,
538 jint device_id, jint hat_id, jint
x, jint
y)
540 Android_OnHat(device_id, hat_id, x,
y);
544 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
545 JNIEnv* env, jclass jcls,
546 jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
547 jint nbuttons, jint naxes, jint nhats, jint nballs)
550 const char *
name = (*env)->GetStringUTFChars(env, device_name,
NULL);
551 const char *desc = (*env)->GetStringUTFChars(env, device_desc,
NULL);
553 retval = Android_AddJoystick(device_id, name, desc, (
SDL_bool) is_accelerometer, nbuttons, naxes, nhats, nballs);
555 (*env)->ReleaseStringUTFChars(env, device_name, name);
556 (*env)->ReleaseStringUTFChars(env, device_desc, desc);
561 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
562 JNIEnv* env, jclass jcls,
565 return Android_RemoveJoystick(device_id);
568 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
569 JNIEnv* env, jclass jcls, jint device_id, jstring device_name)
572 const char *name = (*env)->GetStringUTFChars(env, device_name,
NULL);
574 retval = Android_AddHaptic(device_id, name);
576 (*env)->ReleaseStringUTFChars(env, device_name, name);
581 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
582 JNIEnv* env, jclass jcls, jint device_id)
584 return Android_RemoveHaptic(device_id);
589 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv* env, jclass jcls)
615 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv* env, jclass jcls)
632 SDL_EGL_MakeCurrent(_this,
NULL,
NULL);
642 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)(
643 JNIEnv* env, jclass jcls,
650 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)(
651 JNIEnv* env, jclass jcls,
658 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)(
659 JNIEnv* env, jclass jcls)
667 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
668 JNIEnv* env, jclass jcls,
669 jint touch_device_id_in, jint pointer_finger_id_in,
670 jint action, jfloat
x, jfloat
y, jfloat
p)
676 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
677 JNIEnv* env, jclass jcls,
678 jint
button, jint action, jfloat
x, jfloat
y)
684 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
685 JNIEnv* env, jclass jcls,
686 jfloat
x, jfloat
y, jfloat
z)
688 fLastAccelerometer[0] =
x;
689 fLastAccelerometer[1] =
y;
690 fLastAccelerometer[2] =
z;
695 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeClipboardChanged)(
696 JNIEnv* env, jclass jcls)
702 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeLowMemory)(
703 JNIEnv* env, jclass cls)
709 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
710 JNIEnv* env, jclass cls)
725 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativePause)(
726 JNIEnv* env, jclass cls)
728 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativePause()");
743 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
744 JNIEnv* env, jclass cls)
746 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeResume()");
761 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
762 JNIEnv* env, jclass cls,
763 jstring
text, jint newCursorPosition)
765 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
769 (*env)->ReleaseStringUTFChars(env, text, utftext);
772 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancodeForUnichar)(
773 JNIEnv* env, jclass cls,
780 if (chUnicode < 127) {
795 if (mod & KMOD_SHIFT) {
802 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
803 JNIEnv* env, jclass cls,
804 jstring
text, jint newCursorPosition)
806 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
810 (*env)->ReleaseStringUTFChars(env, text, utftext);
813 JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
814 JNIEnv* env, jclass cls,
817 const char *utfname = (*env)->GetStringUTFChars(env, name,
NULL);
820 jstring
result = (*env)->NewStringUTF(env, hint);
821 (*env)->ReleaseStringUTFChars(env, name, utfname);
826 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
827 JNIEnv* env, jclass cls,
830 const char *utfname = (*env)->GetStringUTFChars(env, name,
NULL);
831 const char *utfvalue = (*env)->GetStringUTFChars(env,
value,
NULL);
835 (*env)->ReleaseStringUTFChars(env, name, utfname);
836 (*env)->ReleaseStringUTFChars(env,
value, utfvalue);
844 static int s_active = 0;
845 struct LocalReferenceHolder
851 static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *
func)
853 struct LocalReferenceHolder refholder;
854 refholder.m_env =
NULL;
855 refholder.m_func =
func;
862 static SDL_bool LocalReferenceHolder_Init(
struct LocalReferenceHolder *refholder, JNIEnv *env)
864 const int capacity = 16;
865 if ((*env)->PushLocalFrame(env, capacity) < 0) {
866 SDL_SetError(
"Failed to allocate enough JVM local references");
870 refholder->m_env = env;
874 static void LocalReferenceHolder_Cleanup(
struct LocalReferenceHolder *refholder)
877 SDL_Log(
"Leaving function %s", refholder->m_func);
879 if (refholder->m_env) {
880 JNIEnv* env = refholder->m_env;
881 (*env)->PopLocalFrame(env,
NULL);
886 static SDL_bool LocalReferenceHolder_IsActive(
void)
897 s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
898 anw = ANativeWindow_fromSurface(env, s);
899 (*env)->DeleteLocalRef(env, s);
908 jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
909 (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midSetActivityTitle, jtitle);
910 (*mEnv)->DeleteLocalRef(mEnv, jtitle);
916 (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midSetWindowStyle, fullscreen ? 1 : 0);
923 jstring jhint = (jstring)((*mEnv)->NewStringUTF(mEnv, (hint ? hint :
"")));
924 (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midSetOrientation, w, h, (resizable? 1 : 0), jhint);
925 (*mEnv)->DeleteLocalRef(mEnv, jhint);
934 for (i = 0; i < 3; ++
i) {
935 values[
i] = fLastAccelerometer[
i];
944 static void Android_JNI_ThreadDestroyed(
void*
value)
947 JNIEnv *env = (JNIEnv*) value;
949 (*mJavaVM)->DetachCurrentThread(mJavaVM);
950 pthread_setspecific(mThreadKey,
NULL);
969 int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env,
NULL);
971 LOGE(
"failed to attach current thread");
984 pthread_setspecific(mThreadKey, (
void*) env);
998 static jboolean audioBuffer16Bit = JNI_FALSE;
999 static jobject audioBuffer =
NULL;
1000 static void* audioBufferPinned =
NULL;
1001 static jboolean captureBuffer16Bit = JNI_FALSE;
1002 static jobject captureBuffer =
NULL;
1006 jboolean audioBufferStereo;
1007 int audioBufferFrames;
1008 jobject jbufobj =
NULL;
1014 LOGE(
"callback_handler: failed to attach current thread");
1018 audioBufferStereo = channelCount > 1;
1021 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for capture");
1022 captureBuffer16Bit = is16Bit;
1023 if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
1025 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioRecord initialization!");
1029 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for output");
1030 audioBuffer16Bit = is16Bit;
1031 if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
1033 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioTrack initialization!");
1042 jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
1043 if (audioBufferLocal) {
1044 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
1045 (*env)->DeleteLocalRef(env, audioBufferLocal);
1049 jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
1050 if (audioBufferLocal) {
1051 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
1052 (*env)->DeleteLocalRef(env, audioBufferLocal);
1056 if (jbufobj ==
NULL) {
1057 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: could not allocate an audio buffer!");
1062 captureBuffer = jbufobj;
1064 audioBuffer = jbufobj;
1071 audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
1073 audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
1076 audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
1078 audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
1081 if (audioBufferStereo) {
1082 audioBufferFrames /= 2;
1085 return audioBufferFrames;
1092 jobject jDisplayObj = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetDisplayDPI);
1093 jclass jDisplayClass = (*env)->GetObjectClass(env, jDisplayObj);
1095 jfieldID fidXdpi = (*env)->GetFieldID(env, jDisplayClass,
"xdpi",
"F");
1096 jfieldID fidYdpi = (*env)->GetFieldID(env, jDisplayClass,
"ydpi",
"F");
1097 jfieldID fidDdpi = (*env)->GetFieldID(env, jDisplayClass,
"densityDpi",
"I");
1099 float nativeXdpi = (*env)->GetFloatField(env, jDisplayObj, fidXdpi);
1100 float nativeYdpi = (*env)->GetFloatField(env, jDisplayObj, fidYdpi);
1101 int nativeDdpi = (*env)->GetIntField(env, jDisplayObj, fidDdpi);
1104 (*env)->DeleteLocalRef(env, jDisplayObj);
1105 (*env)->DeleteLocalRef(env, jDisplayClass);
1108 *ddpi = (float)nativeDdpi;
1122 return audioBufferPinned;
1129 if (audioBuffer16Bit) {
1130 (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
1131 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
1133 (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
1134 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
1143 jboolean isCopy = JNI_FALSE;
1146 if (captureBuffer16Bit) {
1147 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
1148 br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
1150 jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
1153 (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
1156 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
1157 br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
1159 jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
1161 (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
1172 if (captureBuffer16Bit) {
1173 const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
1174 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) ==
len) { }
1176 const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
1177 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) ==
len) { }
1180 if (captureBuffer16Bit) {
1181 (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
1183 (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
1193 (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midCaptureClose);
1194 if (captureBuffer) {
1195 (*env)->DeleteGlobalRef(env, captureBuffer);
1196 captureBuffer =
NULL;
1199 (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioClose);
1201 (*env)->DeleteGlobalRef(env, audioBuffer);
1203 audioBufferPinned =
NULL;
1213 jthrowable exception;
1217 exception = (*mEnv)->ExceptionOccurred(mEnv);
1218 if (exception !=
NULL) {
1222 (*mEnv)->ExceptionClear(mEnv);
1225 jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
1226 jclass classClass = (*mEnv)->FindClass(mEnv,
"java/lang/Class");
1227 jstring exceptionName;
1228 const char* exceptionNameUTF8;
1229 jstring exceptionMessage;
1231 mid = (*mEnv)->GetMethodID(mEnv, classClass,
"getName",
"()Ljava/lang/String;");
1232 exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
1233 exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
1235 mid = (*mEnv)->GetMethodID(mEnv, exceptionClass,
"getMessage",
"()Ljava/lang/String;");
1236 exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
1238 if (exceptionMessage !=
NULL) {
1239 const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
1240 SDL_SetError(
"%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
1241 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
1246 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
1255 static int Internal_Android_JNI_FileOpen(
SDL_RWops*
ctx)
1257 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1263 jobject assetManager;
1264 jobject inputStream;
1266 jobject readableByteChannel;
1267 jstring fileNameJString;
1270 jfieldID descriptor;
1273 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1277 fileNameJString = (jstring)ctx->
hidden.androidio.fileNameRef;
1278 ctx->
hidden.androidio.position = 0;
1281 context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, midGetContext);
1284 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
1285 "getAssets",
"()Landroid/content/res/AssetManager;");
1286 assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
1291 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
"openFd",
"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
1292 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
1293 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1297 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getStartOffset",
"()J");
1298 ctx->
hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
1299 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1303 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getDeclaredLength",
"()J");
1304 ctx->
hidden.androidio.
size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
1305 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1309 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getFileDescriptor",
"()Ljava/io/FileDescriptor;");
1310 fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
1311 fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
1312 descriptor = (*mEnv)->GetFieldID(mEnv, fdCls,
"descriptor",
"I");
1313 ctx->
hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
1314 ctx->
hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
1317 lseek(ctx->
hidden.androidio.fd, (off_t)ctx->
hidden.androidio.offset, SEEK_SET);
1325 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
1328 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
1329 "open",
"(Ljava/lang/String;I)Ljava/io/InputStream;");
1330 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 );
1331 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1333 inputStream = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, midOpenAPKExpansionInputStream, fileNameJString);
1338 if (Android_JNI_ExceptionOccurred(
SDL_FALSE) || !inputStream) {
1343 ctx->
hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
1353 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1354 "available",
"()I");
1355 ctx->
hidden.androidio.
size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
1356 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1361 channels = (*mEnv)->FindClass(mEnv,
"java/nio/channels/Channels");
1362 mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
1364 "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
1365 readableByteChannel = (*mEnv)->CallStaticObjectMethod(
1366 mEnv, channels, mid, inputStream);
1367 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1371 ctx->
hidden.androidio.readableByteChannelRef =
1372 (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
1375 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
1376 "read",
"(Ljava/nio/ByteBuffer;)I");
1377 ctx->
hidden.androidio.readMethod = mid;
1384 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1386 if(ctx->
hidden.androidio.inputStreamRef !=
NULL) {
1387 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1390 if(ctx->
hidden.androidio.readableByteChannelRef !=
NULL) {
1391 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1394 if(ctx->
hidden.androidio.assetFileDescriptorRef !=
NULL) {
1395 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1400 LocalReferenceHolder_Cleanup(&refs);
1405 const char* fileName,
const char*
mode)
1407 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1410 jstring fileNameJString;
1412 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1413 LocalReferenceHolder_Cleanup(&refs);
1418 LocalReferenceHolder_Cleanup(&refs);
1422 fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
1423 ctx->
hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
1425 ctx->
hidden.androidio.readableByteChannelRef =
NULL;
1427 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
1429 retval = Internal_Android_JNI_FileOpen(ctx);
1430 LocalReferenceHolder_Cleanup(&refs);
1435 size_t size,
size_t maxnum)
1437 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1439 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1440 size_t bytesMax = size * maxnum;
1445 result = read(ctx->
hidden.androidio.fd, buffer, bytesMax );
1448 LocalReferenceHolder_Cleanup(&refs);
1449 return result /
size;
1451 LocalReferenceHolder_Cleanup(&refs);
1454 jlong bytesRemaining = (jlong) (size * maxnum);
1455 jlong bytesMax = (jlong) (ctx->
hidden.androidio.
size - ctx->
hidden.androidio.position);
1458 jobject readableByteChannel;
1459 jmethodID readMethod;
1463 if (bytesRemaining > bytesMax) bytesRemaining = bytesMax;
1466 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1467 LocalReferenceHolder_Cleanup(&refs);
1471 readableByteChannel = (jobject)ctx->
hidden.androidio.readableByteChannelRef;
1472 readMethod = (jmethodID)ctx->
hidden.androidio.readMethod;
1473 byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
1475 while (bytesRemaining > 0) {
1477 int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
1479 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1480 LocalReferenceHolder_Cleanup(&refs);
1488 bytesRemaining -=
result;
1492 LocalReferenceHolder_Cleanup(&refs);
1493 return bytesRead /
size;
1498 size_t size,
size_t num)
1500 SDL_SetError(
"Cannot write to Android package filesystem");
1506 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1511 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1512 LocalReferenceHolder_Cleanup(&refs);
1513 return SDL_SetError(
"Failed to allocate enough JVM local references");
1518 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1521 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1522 jobject inputStream = (jobject)ctx->
hidden.androidio.assetFileDescriptorRef;
1523 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1525 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1526 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1527 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1532 jobject inputStream = (jobject)ctx->
hidden.androidio.inputStreamRef;
1535 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1537 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1538 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1539 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1540 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1550 LocalReferenceHolder_Cleanup(&refs);
1562 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1567 offset += ctx->
hidden.androidio.offset;
1570 offset += ctx->
hidden.androidio.position;
1572 offset += ctx->
hidden.androidio.offset;
1582 ret = lseek(ctx->
hidden.androidio.fd, (off_t)offset, SEEK_SET);
1583 if (ret == -1)
return -1;
1584 ctx->
hidden.androidio.position = ret - ctx->
hidden.androidio.offset;
1604 if (newPosition < 0) {
1607 if (newPosition > ctx->
hidden.androidio.
size) {
1611 movement = newPosition - ctx->
hidden.androidio.position;
1613 unsigned char buffer[4096];
1616 while (movement > 0) {
1619 if (amount > movement) {
1631 }
else if (movement < 0) {
1634 Internal_Android_JNI_FileClose(ctx,
SDL_FALSE);
1635 Internal_Android_JNI_FileOpen(ctx);
1640 return ctx->
hidden.androidio.position;
1646 return Internal_Android_JNI_FileClose(ctx,
SDL_TRUE);
1652 jstring
string = (*env)->NewStringUTF(env, text);
1653 (*env)->CallStaticVoidMethod(env, mActivityClass, midClipboardSetText,
string);
1654 (*env)->DeleteLocalRef(env,
string);
1664 string = (*env)->CallStaticObjectMethod(env, mActivityClass, midClipboardGetText);
1666 const char* utf = (*env)->GetStringUTFChars(env,
string, 0);
1669 (*env)->ReleaseStringUTFChars(env,
string, utf);
1671 (*env)->DeleteLocalRef(env,
string);
1680 jboolean retval = (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText);
1690 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1702 if (!LocalReferenceHolder_Init(&refs, env)) {
1703 LocalReferenceHolder_Cleanup(&refs);
1709 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1711 action = (*env)->NewStringUTF(env,
"android.intent.action.BATTERY_CHANGED");
1713 cls = (*env)->FindClass(env,
"android/content/IntentFilter");
1715 mid = (*env)->GetMethodID(env, cls,
"<init>",
"(Ljava/lang/String;)V");
1716 filter = (*env)->NewObject(env, cls, mid, action);
1718 (*env)->DeleteLocalRef(env, action);
1720 mid = (*env)->GetMethodID(env, mActivityClass,
"registerReceiver",
"(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
1721 intent = (*env)->CallObjectMethod(env, context, mid,
NULL, filter);
1723 (*env)->DeleteLocalRef(env, filter);
1725 cls = (*env)->GetObjectClass(env, intent);
1727 imid = (*env)->GetMethodID(env, cls,
"getIntExtra",
"(Ljava/lang/String;I)I");
1730 #define GET_INT_EXTRA(var, key) \ 1732 iname = (*env)->NewStringUTF(env, key); \ 1733 var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \ 1734 (*env)->DeleteLocalRef(env, iname); 1736 bmid = (*env)->GetMethodID(env, cls,
"getBooleanExtra",
"(Ljava/lang/String;Z)Z");
1739 #define GET_BOOL_EXTRA(var, key) \ 1741 bname = (*env)->NewStringUTF(env, key); \ 1742 var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \ 1743 (*env)->DeleteLocalRef(env, bname); 1747 GET_INT_EXTRA(plug,
"plugged")
1749 LocalReferenceHolder_Cleanup(&refs);
1754 *plugged = (0 < plug) ? 1 : 0;
1759 GET_INT_EXTRA(status,
"status")
1761 LocalReferenceHolder_Cleanup(&refs);
1765 *charged = (status == 5) ? 1 : 0;
1769 GET_BOOL_EXTRA(present,
"present")
1770 *battery = present ? 1 : 0;
1783 GET_INT_EXTRA(level_temp,
"level")
1788 GET_INT_EXTRA(scale_temp,
"scale")
1792 if ((level == -1) || (scale == -1)) {
1793 LocalReferenceHolder_Cleanup(&refs);
1796 *percent = level * 100 /
scale;
1799 (*env)->DeleteLocalRef(env, intent);
1801 LocalReferenceHolder_Cleanup(&refs);
1809 jintArray
array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, midInputGetInputDeviceIds, sources);
1813 number = (int) (*env)->GetArrayLength(env, array);
1815 jint* elements = (*env)->GetIntArrayElements(env, array,
NULL);
1819 for (i = 0; i < number; ++
i) {
1820 (*ids)[
i] = elements[
i];
1822 (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
1825 (*env)->DeleteLocalRef(env, array);
1834 (*env)->SetStaticBooleanField(env, mActivityClass, fidSeparateMouseAndTouch, new_value ? JNI_TRUE : JNI_FALSE);
1840 (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollInputDevices);
1846 (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollHapticDevices);
1852 (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, length);
1857 #define COMMAND_SET_KEEP_SCREEN_ON 5 1864 success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midSendMessage, command, param);
1865 return success ? 0 : -1;
1876 (*env)->CallStaticBooleanMethod(env, mActivityClass, midShowTextInput,
1886 const int COMMAND_TEXTEDIT_HIDE = 3;
1893 jboolean is_shown = 0;
1894 is_shown = (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midIsScreenKeyboardShown);
1907 jintArray button_flags;
1908 jintArray button_ids;
1909 jobjectArray button_texts;
1919 clazz = (*env)->FindClass(env,
"java/lang/String");
1921 title = (*env)->NewStringUTF(env, messageboxdata->
title);
1922 message = (*env)->NewStringUTF(env, messageboxdata->
message);
1924 button_flags = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1925 button_ids = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1926 button_texts = (*env)->NewObjectArray(env, messageboxdata->
numbuttons,
1928 for (i = 0; i < messageboxdata->
numbuttons; ++
i) {
1930 (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
1932 (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
1933 text = (*env)->NewStringUTF(env, messageboxdata->
buttons[i].
text);
1934 (*env)->SetObjectArrayElement(env, button_texts, i, text);
1935 (*env)->DeleteLocalRef(env, text);
1941 temp = (0xFF << 24) |
1945 (*env)->SetIntArrayRegion(env, colors, i, 1, &temp);
1951 (*env)->DeleteLocalRef(env, clazz);
1954 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1956 clazz = (*env)->GetObjectClass(env, context);
1958 mid = (*env)->GetMethodID(env, clazz,
1959 "messageboxShowMessageBox",
"(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
1960 *buttonid = (*env)->CallIntMethod(env, context, mid,
1961 messageboxdata->
flags,
1969 (*env)->DeleteLocalRef(env, context);
1970 (*env)->DeleteLocalRef(env, clazz);
1974 (*env)->DeleteLocalRef(env, title);
1975 (*env)->DeleteLocalRef(env, message);
1976 (*env)->DeleteLocalRef(env, button_flags);
1977 (*env)->DeleteLocalRef(env, button_ids);
1978 (*env)->DeleteLocalRef(env, button_texts);
1979 (*env)->DeleteLocalRef(env, colors);
1987 // Functions exposed to SDL applications in SDL_system.h
2006 return (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
2012 return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsAndroidTV);
2017 static char *s_AndroidInternalFilesPath =
NULL;
2019 if (!s_AndroidInternalFilesPath) {
2020 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
2028 if (!LocalReferenceHolder_Init(&refs, env)) {
2029 LocalReferenceHolder_Cleanup(&refs);
2034 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
2037 LocalReferenceHolder_Cleanup(&refs);
2042 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
2043 "getFilesDir",
"()Ljava/io/File;");
2044 fileObject = (*env)->CallObjectMethod(env, context, mid);
2047 LocalReferenceHolder_Cleanup(&refs);
2052 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
2053 "getCanonicalPath",
"()Ljava/lang/String;");
2054 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
2055 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
2056 LocalReferenceHolder_Cleanup(&refs);
2060 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
2061 s_AndroidInternalFilesPath =
SDL_strdup(path);
2062 (*env)->ReleaseStringUTFChars(env, pathString, path);
2064 LocalReferenceHolder_Cleanup(&refs);
2066 return s_AndroidInternalFilesPath;
2071 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
2074 jstring stateString;
2079 if (!LocalReferenceHolder_Init(&refs, env)) {
2080 LocalReferenceHolder_Cleanup(&refs);
2084 cls = (*env)->FindClass(env,
"android/os/Environment");
2085 mid = (*env)->GetStaticMethodID(env, cls,
2086 "getExternalStorageState",
"()Ljava/lang/String;");
2087 stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
2089 state = (*env)->GetStringUTFChars(env, stateString,
NULL);
2092 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"external storage state: %s", state);
2095 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
2096 SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
2097 }
else if (
SDL_strcmp(state,
"mounted_ro") == 0) {
2098 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
2102 (*env)->ReleaseStringUTFChars(env, stateString, state);
2104 LocalReferenceHolder_Cleanup(&refs);
2110 static char *s_AndroidExternalFilesPath =
NULL;
2112 if (!s_AndroidExternalFilesPath) {
2113 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
2121 if (!LocalReferenceHolder_Init(&refs, env)) {
2122 LocalReferenceHolder_Cleanup(&refs);
2127 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
2130 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
2131 "getExternalFilesDir",
"(Ljava/lang/String;)Ljava/io/File;");
2132 fileObject = (*env)->CallObjectMethod(env, context, mid,
NULL);
2135 LocalReferenceHolder_Cleanup(&refs);
2140 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
2141 "getAbsolutePath",
"()Ljava/lang/String;");
2142 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
2144 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
2145 s_AndroidExternalFilesPath =
SDL_strdup(path);
2146 (*env)->ReleaseStringUTFChars(env, pathString, path);
2148 LocalReferenceHolder_Cleanup(&refs);
2150 return s_AndroidExternalFilesPath;
2155 if (!mActivityClass || !midGetManifestEnvironmentVariables) {
2156 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Request to get environment variables before JNI is ready");
2160 if (!bHasEnvironmentVariables) {
2162 SDL_bool ret = (*env)->CallStaticBooleanMethod(env, mActivityClass, midGetManifestEnvironmentVariables);
2164 bHasEnvironmentVariables =
SDL_TRUE;
int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
void Android_SetScreenResolution(int width, int height, Uint32 format, float rate)
GLenum GLenum GLenum GLenum GLenum scale
int Android_JNI_GetDisplayDPI(float *ddpi, float *xdpi, float *ydpi)
int Android_JNI_FileClose(SDL_RWops *ctx)
void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint)
int Android_OnKeyUp(int keycode)
int Android_JNI_SendMessage(int command, int param)
void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
void Android_JNI_WriteAudioBuffer(void)
GLsizei const GLchar *const * string
GLint GLint GLint GLint GLint x
GLuint GLsizei const GLchar * message
SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
int SDL_SendDropFile(SDL_Window *window, const char *file)
GLfloat GLfloat GLfloat GLfloat h
#define SDL_AndroidGetExternalStoragePath
void Android_JNI_SetActivityTitle(const char *title)
static screen_context_t context
char * Android_JNI_GetClipboardText(void)
int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
int Android_OnKeyDown(int keycode)
void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
static AndroidKeyInfo unicharToAndroidKeyInfoTable[]
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
void Android_JNI_SetSeparateMouseAndTouch(SDL_bool new_value)
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
int Android_JNI_FileOpen(SDL_RWops *ctx, const char *fileName, const char *mode)
int SDL_SendDropComplete(SDL_Window *window)
GLuint const GLchar * name
GLint GLint GLsizei width
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
SDL_sem * Android_PauseSem
int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
static SDL_VideoDevice * _this
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
int Android_JNI_SetupThread(void)
GLenum GLsizei GLsizei GLint * values
void Android_JNI_FlushCapturedAudio(void)
#define SDL_StopTextInput
GLenum GLsizei const void * pathString
int SDL_SendClipboardUpdate(void)
int SDL_SendKeyboardText(const char *text)
#define SDL_stack_alloc(type, count)
void Android_JNI_CloseAudioDevice(const int iscapture)
SDL_bool Android_JNI_HasClipboardText(void)
int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seconds, int *percent)
size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size, size_t num)
SDL_Window * Android_Window
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
void * Android_JNI_GetAudioBuffer(void)
GLint GLint GLint GLint GLint GLint y
void Android_JNI_SuspendScreenSaver(SDL_bool suspend)
void Android_JNI_PollHapticDevices(void)
const SDL_MessageBoxButtonData * buttons
MessageBox structure containing title, text, window, etc.
void Android_OnMouse(int button, int action, float x, float y)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Sint64(* size)(struct SDL_RWops *context)
#define SDL_assert(condition)
ANativeWindow * Android_JNI_GetNativeWindow(void)
void Android_JNI_GetManifestEnvironmentVariables(void)
union SDL_RWops::@10 hidden
static char text[MAX_TEXT_LENGTH]
GLint GLint GLsizei GLsizei height
void Android_JNI_HideTextInput(void)
#define SDL_AndroidGetActivity
SDL_sem * Android_ResumeSem
size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size, size_t maxnum)
C_LINKAGE SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[])
int Android_JNI_SetClipboardText(const char *text)
#define SDL_AndroidGetExternalStorageState
SDL_VideoDevice * SDL_GetVideoDevice(void)
SDL_bool Android_JNI_IsScreenKeyboardShown(void)
void Android_JNI_SetWindowStyle(SDL_bool fullscreen)
GLsizei const GLchar *const * path
int SDL_SendAppEvent(SDL_EventType eventType)
void Android_JNI_PollInputDevices(void)
#define SDL_stack_free(data)
#define SDL_AndroidGetJNIEnv
ANativeWindow * native_window
int Android_JNI_GetTouchDeviceIds(int **ids)
GLuint GLsizei GLsizei * length
const SDL_MessageBoxColorScheme * colorScheme
SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX]
#define SDL_AndroidGetInternalStoragePath
JNIEnv * Android_JNI_GetEnv(void)
SDL_Scancode
The SDL keyboard scancode representation.
void Android_JNI_HapticRun(int device_id, int length)
int SDL_SendEditingText(const char *text, int start, int length)
Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence)
A rectangle, with the origin at the upper left.
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Sint64 Android_JNI_FileSize(SDL_RWops *ctx)