21 #include "../../SDL_internal.h" 34 #include "../../events/SDL_events_c.h" 35 #include "../../video/android/SDL_androidkeyboard.h" 36 #include "../../video/android/SDL_androidmouse.h" 37 #include "../../video/android/SDL_androidtouch.h" 38 #include "../../video/android/SDL_androidvideo.h" 39 #include "../../video/android/SDL_androidwindow.h" 40 #include "../../joystick/android/SDL_sysjoystick_c.h" 41 #include "../../haptic/android/SDL_syshaptic_c.h" 43 #include <android/log.h> 45 #include <sys/types.h> 51 #define LOGI(...) do {} while (0) 52 #define LOGE(...) do {} while (0) 55 #define SDL_JAVA_PREFIX org_libsdl_app 56 #define CONCAT1(prefix, class, function) CONCAT2(prefix, class, function) 57 #define CONCAT2(prefix, class, function) Java_ ## prefix ## _ ## class ## _ ## function 58 #define SDL_JAVA_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLActivity, function) 59 #define SDL_JAVA_AUDIO_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLAudioManager, function) 60 #define SDL_JAVA_CONTROLLER_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLControllerManager, function) 61 #define SDL_JAVA_INTERFACE_INPUT_CONNECTION(function) CONCAT1(SDL_JAVA_PREFIX, SDLInputConnection, function) 65 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(
66 JNIEnv* mEnv, jclass cls);
68 JNIEXPORT
int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(
69 JNIEnv* env, jclass cls,
70 jstring library, jstring
function, jobject
array);
72 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
73 JNIEnv* env, jclass jcls,
76 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
77 JNIEnv* env, jclass jcls,
80 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
81 JNIEnv* env, jclass jcls);
83 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(
84 JNIEnv* env, jclass jcls);
86 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)(
87 JNIEnv* env, jclass jcls,
90 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)(
91 JNIEnv* env, jclass jcls,
94 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)(
95 JNIEnv* env, jclass jcls);
97 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
98 JNIEnv* env, jclass jcls,
99 jint touch_device_id_in, jint pointer_finger_id_in,
100 jint action, jfloat
x, jfloat
y, jfloat
p);
102 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
103 JNIEnv* env, jclass jcls,
104 jint
button, jint action, jfloat
x, jfloat
y);
106 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
107 JNIEnv* env, jclass jcls,
108 jfloat
x, jfloat
y, jfloat
z);
110 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeClipboardChanged)(
111 JNIEnv* env, jclass jcls);
113 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeLowMemory)(
114 JNIEnv* env, jclass cls);
116 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
117 JNIEnv* env, jclass cls);
119 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativePause)(
120 JNIEnv* env, jclass cls);
122 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
123 JNIEnv* env, jclass cls);
125 JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
126 JNIEnv* env, jclass cls,
130 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
131 JNIEnv* env, jclass cls,
132 jstring
text, jint newCursorPosition);
134 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
135 JNIEnv* env, jclass cls,
136 jstring
text, jint newCursorPosition);
139 JNIEXPORT
void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(
140 JNIEnv *env, jclass jcls);
143 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(
144 JNIEnv *env, jclass jcls);
146 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
147 JNIEnv* env, jclass jcls,
148 jint device_id, jint keycode);
150 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
151 JNIEnv* env, jclass jcls,
152 jint device_id, jint keycode);
154 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
155 JNIEnv* env, jclass jcls,
156 jint device_id, jint
axis, jfloat
value);
158 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
159 JNIEnv* env, jclass jcls,
160 jint device_id, jint hat_id, jint
x, jint
y);
162 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
163 JNIEnv* env, jclass jcls,
164 jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
165 jint nbuttons, jint naxes, jint nhats, jint nballs);
167 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
168 JNIEnv* env, jclass jcls,
171 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
172 JNIEnv* env, jclass jcls,
173 jint device_id, jstring device_name);
175 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
176 JNIEnv* env, jclass jcls,
184 static void Android_JNI_ThreadDestroyed(
void*);
195 static pthread_key_t mThreadKey;
196 static JavaVM* mJavaVM;
199 static jclass mActivityClass;
202 static jmethodID midGetNativeSurface;
203 static jmethodID midSetActivityTitle;
204 static jmethodID midSetOrientation;
205 static jmethodID midGetContext;
206 static jmethodID midInputGetInputDeviceIds;
207 static jmethodID midSendMessage;
208 static jmethodID midShowTextInput;
209 static jmethodID midIsScreenKeyboardShown;
210 static jmethodID midClipboardSetText;
211 static jmethodID midClipboardGetText;
212 static jmethodID midClipboardHasText;
213 static jmethodID midOpenAPKExpansionInputStream;
216 static jclass mAudioManagerClass;
219 static jmethodID midAudioOpen;
220 static jmethodID midAudioWriteShortBuffer;
221 static jmethodID midAudioWriteByteBuffer;
222 static jmethodID midAudioClose;
223 static jmethodID midCaptureOpen;
224 static jmethodID midCaptureReadShortBuffer;
225 static jmethodID midCaptureReadByteBuffer;
226 static jmethodID midCaptureClose;
229 static jclass mControllerManagerClass;
232 static jmethodID midPollInputDevices;
233 static jmethodID midPollHapticDevices;
234 static jmethodID midHapticRun;
237 static jfieldID fidSeparateMouseAndTouch;
240 static float fLastAccelerometer[3];
248 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,
void* reserved)
252 LOGI(
"JNI_OnLoad called");
253 if ((*mJavaVM)->GetEnv(mJavaVM, (
void**) &env, JNI_VERSION_1_4) != JNI_OK) {
254 LOGE(
"Failed to get the environment using GetEnv()");
261 if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed) != 0) {
262 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"Error initializing pthread key");
266 return JNI_VERSION_1_4;
271 if (!mActivityClass || !mAudioManagerClass || !mControllerManagerClass) {
280 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
282 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeSetupJNI()");
286 mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
288 midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
289 "getNativeSurface",
"()Landroid/view/Surface;");
290 midSetActivityTitle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
291 "setActivityTitle",
"(Ljava/lang/String;)Z");
292 midSetOrientation = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
293 "setOrientation",
"(IIZLjava/lang/String;)V");
294 midGetContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
295 "getContext",
"()Landroid/content/Context;");
296 midInputGetInputDeviceIds = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
297 "inputGetInputDeviceIds",
"(I)[I");
298 midSendMessage = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
299 "sendMessage",
"(II)Z");
300 midShowTextInput = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
301 "showTextInput",
"(IIII)Z");
302 midIsScreenKeyboardShown = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
303 "isScreenKeyboardShown",
"()Z");
304 midClipboardSetText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
305 "clipboardSetText",
"(Ljava/lang/String;)V");
306 midClipboardGetText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
307 "clipboardGetText",
"()Ljava/lang/String;");
308 midClipboardHasText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
309 "clipboardHasText",
"()Z");
310 midOpenAPKExpansionInputStream = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
311 "openAPKExpansionInputStream",
"(Ljava/lang/String;)Ljava/io/InputStream;");
313 if (!midGetNativeSurface ||
314 !midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
315 !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
316 !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
317 !midOpenAPKExpansionInputStream) {
318 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
321 fidSeparateMouseAndTouch = (*mEnv)->GetStaticFieldID(mEnv, mActivityClass,
"mSeparateMouseAndTouch",
"Z");
323 if (!fidSeparateMouseAndTouch) {
324 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java static fields, do you have the latest version of SDLActivity.java?");
331 JNIEXPORT
void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
333 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"AUDIO nativeSetupJNI()");
337 mAudioManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
339 midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
340 "audioOpen",
"(IZZI)I");
341 midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
342 "audioWriteShortBuffer",
"([S)V");
343 midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
344 "audioWriteByteBuffer",
"([B)V");
345 midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
346 "audioClose",
"()V");
347 midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
348 "captureOpen",
"(IZZI)I");
349 midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
350 "captureReadShortBuffer",
"([SZ)I");
351 midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
352 "captureReadByteBuffer",
"([BZ)I");
353 midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
354 "captureClose",
"()V");
356 if (!midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
357 !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose) {
358 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?");
365 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
367 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"CONTROLLER nativeSetupJNI()");
371 mControllerManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
373 midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
374 "pollInputDevices",
"()V");
375 midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
376 "pollHapticDevices",
"()V");
377 midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
378 "hapticRun",
"(II)V");
380 if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun) {
381 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
388 typedef int (*SDL_main_func)(
int argc,
char *argv[]);
391 JNIEXPORT
int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv* env, jclass cls, jstring library, jstring
function, jobject
array)
394 const char *library_file;
395 void *library_handle;
397 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeRunMain()");
399 library_file = (*env)->GetStringUTFChars(env, library,
NULL);
400 library_handle = dlopen(library_file, RTLD_GLOBAL);
401 if (library_handle) {
402 const char *function_name;
405 function_name = (*env)->GetStringUTFChars(env,
function,
NULL);
406 SDL_main = (SDL_main_func)dlsym(library_handle, function_name);
414 len = (*env)->GetArrayLength(env,
array);
421 for (i = 0; i <
len; ++
i) {
424 jstring
string = (*env)->GetObjectArrayElement(env,
array, i);
426 utf = (*env)->GetStringUTFChars(env,
string, 0);
429 (*env)->ReleaseStringUTFChars(env,
string, utf);
431 (*env)->DeleteLocalRef(env,
string);
445 for (i = 0; i < argc; ++
i) {
451 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"nativeRunMain(): Couldn't find function %s in library %s", function_name, library_file);
453 (*env)->ReleaseStringUTFChars(env,
function, function_name);
455 dlclose(library_handle);
458 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"nativeRunMain(): Couldn't load library %s", library_file);
460 (*env)->ReleaseStringUTFChars(env, library, library_file);
469 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
470 JNIEnv* env, jclass jcls,
475 (*env)->ReleaseStringUTFChars(env,
filename, path);
480 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
481 JNIEnv* env, jclass jcls,
488 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
489 JNIEnv* env, jclass jcls,
490 jint device_id, jint keycode)
492 return Android_OnPadDown(device_id, keycode);
496 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
497 JNIEnv* env, jclass jcls,
498 jint device_id, jint keycode)
500 return Android_OnPadUp(device_id, keycode);
504 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
505 JNIEnv* env, jclass jcls,
508 Android_OnJoy(device_id, axis,
value);
512 JNIEXPORT
void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
513 JNIEnv* env, jclass jcls,
514 jint device_id, jint hat_id, jint
x, jint
y)
516 Android_OnHat(device_id, hat_id, x,
y);
520 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
521 JNIEnv* env, jclass jcls,
522 jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
523 jint nbuttons, jint naxes, jint nhats, jint nballs)
526 const char *
name = (*env)->GetStringUTFChars(env, device_name,
NULL);
527 const char *desc = (*env)->GetStringUTFChars(env, device_desc,
NULL);
529 retval = Android_AddJoystick(device_id, name, desc, (
SDL_bool) is_accelerometer, nbuttons, naxes, nhats, nballs);
531 (*env)->ReleaseStringUTFChars(env, device_name, name);
532 (*env)->ReleaseStringUTFChars(env, device_desc, desc);
537 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
538 JNIEnv* env, jclass jcls,
541 return Android_RemoveJoystick(device_id);
544 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
545 JNIEnv* env, jclass jcls, jint device_id, jstring device_name)
548 const char *name = (*env)->GetStringUTFChars(env, device_name,
NULL);
550 retval = Android_AddHaptic(device_id, name);
552 (*env)->ReleaseStringUTFChars(env, device_name, name);
557 JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
558 JNIEnv* env, jclass jcls, jint device_id)
560 return Android_RemoveHaptic(device_id);
565 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv* env, jclass jcls)
591 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv* env, jclass jcls)
608 SDL_EGL_MakeCurrent(_this,
NULL,
NULL);
618 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)(
619 JNIEnv* env, jclass jcls,
626 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)(
627 JNIEnv* env, jclass jcls,
634 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)(
635 JNIEnv* env, jclass jcls)
643 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
644 JNIEnv* env, jclass jcls,
645 jint touch_device_id_in, jint pointer_finger_id_in,
646 jint action, jfloat
x, jfloat
y, jfloat
p)
652 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
653 JNIEnv* env, jclass jcls,
654 jint
button, jint action, jfloat
x, jfloat
y)
660 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
661 JNIEnv* env, jclass jcls,
662 jfloat
x, jfloat
y, jfloat
z)
664 fLastAccelerometer[0] =
x;
665 fLastAccelerometer[1] =
y;
666 fLastAccelerometer[2] =
z;
671 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeClipboardChanged)(
672 JNIEnv* env, jclass jcls)
678 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeLowMemory)(
679 JNIEnv* env, jclass cls)
685 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
686 JNIEnv* env, jclass cls)
701 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativePause)(
702 JNIEnv* env, jclass cls)
704 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativePause()");
719 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
720 JNIEnv* env, jclass cls)
722 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeResume()");
737 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
738 JNIEnv* env, jclass cls,
739 jstring
text, jint newCursorPosition)
741 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
745 (*env)->ReleaseStringUTFChars(env, text, utftext);
748 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
749 JNIEnv* env, jclass cls,
750 jstring
text, jint newCursorPosition)
752 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
756 (*env)->ReleaseStringUTFChars(env, text, utftext);
759 JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
760 JNIEnv* env, jclass cls,
763 const char *utfname = (*env)->GetStringUTFChars(env, name,
NULL);
766 jstring
result = (*env)->NewStringUTF(env, hint);
767 (*env)->ReleaseStringUTFChars(env, name, utfname);
776 static int s_active = 0;
777 struct LocalReferenceHolder
783 static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *
func)
785 struct LocalReferenceHolder refholder;
786 refholder.m_env =
NULL;
787 refholder.m_func =
func;
794 static SDL_bool LocalReferenceHolder_Init(
struct LocalReferenceHolder *refholder, JNIEnv *env)
796 const int capacity = 16;
797 if ((*env)->PushLocalFrame(env, capacity) < 0) {
798 SDL_SetError(
"Failed to allocate enough JVM local references");
802 refholder->m_env = env;
806 static void LocalReferenceHolder_Cleanup(
struct LocalReferenceHolder *refholder)
809 SDL_Log(
"Leaving function %s", refholder->m_func);
811 if (refholder->m_env) {
812 JNIEnv* env = refholder->m_env;
813 (*env)->PopLocalFrame(env,
NULL);
818 static SDL_bool LocalReferenceHolder_IsActive(
void)
829 s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
830 anw = ANativeWindow_fromSurface(env, s);
831 (*env)->DeleteLocalRef(env, s);
840 jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
841 (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midSetActivityTitle, jtitle);
842 (*mEnv)->DeleteLocalRef(mEnv, jtitle);
849 jstring jhint = (jstring)((*mEnv)->NewStringUTF(mEnv, (hint ? hint :
"")));
850 (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midSetOrientation, w, h, (resizable? 1 : 0), jhint);
851 (*mEnv)->DeleteLocalRef(mEnv, jhint);
860 for (i = 0; i < 3; ++
i) {
861 values[
i] = fLastAccelerometer[
i];
870 static void Android_JNI_ThreadDestroyed(
void*
value)
873 JNIEnv *env = (JNIEnv*) value;
875 (*mJavaVM)->DetachCurrentThread(mJavaVM);
876 pthread_setspecific(mThreadKey,
NULL);
895 int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env,
NULL);
897 LOGE(
"failed to attach current thread");
910 pthread_setspecific(mThreadKey, (
void*) env);
924 static jboolean audioBuffer16Bit = JNI_FALSE;
925 static jobject audioBuffer =
NULL;
926 static void* audioBufferPinned =
NULL;
927 static jboolean captureBuffer16Bit = JNI_FALSE;
928 static jobject captureBuffer =
NULL;
932 jboolean audioBufferStereo;
933 int audioBufferFrames;
934 jobject jbufobj =
NULL;
940 LOGE(
"callback_handler: failed to attach current thread");
944 audioBufferStereo = channelCount > 1;
947 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for capture");
948 captureBuffer16Bit = is16Bit;
949 if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
951 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioRecord initialization!");
955 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for output");
956 audioBuffer16Bit = is16Bit;
957 if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
959 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioTrack initialization!");
968 jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
969 if (audioBufferLocal) {
970 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
971 (*env)->DeleteLocalRef(env, audioBufferLocal);
975 jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
976 if (audioBufferLocal) {
977 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
978 (*env)->DeleteLocalRef(env, audioBufferLocal);
982 if (jbufobj ==
NULL) {
983 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: could not allocate an audio buffer!");
988 captureBuffer = jbufobj;
990 audioBuffer = jbufobj;
997 audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
999 audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
1002 audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
1004 audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
1007 if (audioBufferStereo) {
1008 audioBufferFrames /= 2;
1011 return audioBufferFrames;
1016 return audioBufferPinned;
1023 if (audioBuffer16Bit) {
1024 (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
1025 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
1027 (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
1028 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
1037 jboolean isCopy = JNI_FALSE;
1040 if (captureBuffer16Bit) {
1041 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
1042 br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
1044 jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
1047 (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
1050 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
1051 br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
1053 jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
1055 (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
1066 if (captureBuffer16Bit) {
1067 const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
1068 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) ==
len) { }
1070 const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
1071 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) ==
len) { }
1074 if (captureBuffer16Bit) {
1075 (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
1077 (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
1087 (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midCaptureClose);
1088 if (captureBuffer) {
1089 (*env)->DeleteGlobalRef(env, captureBuffer);
1090 captureBuffer =
NULL;
1093 (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioClose);
1095 (*env)->DeleteGlobalRef(env, audioBuffer);
1097 audioBufferPinned =
NULL;
1107 jthrowable exception;
1111 exception = (*mEnv)->ExceptionOccurred(mEnv);
1112 if (exception !=
NULL) {
1116 (*mEnv)->ExceptionClear(mEnv);
1119 jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
1120 jclass classClass = (*mEnv)->FindClass(mEnv,
"java/lang/Class");
1121 jstring exceptionName;
1122 const char* exceptionNameUTF8;
1123 jstring exceptionMessage;
1125 mid = (*mEnv)->GetMethodID(mEnv, classClass,
"getName",
"()Ljava/lang/String;");
1126 exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
1127 exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
1129 mid = (*mEnv)->GetMethodID(mEnv, exceptionClass,
"getMessage",
"()Ljava/lang/String;");
1130 exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
1132 if (exceptionMessage !=
NULL) {
1133 const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
1134 SDL_SetError(
"%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
1135 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
1140 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
1149 static int Internal_Android_JNI_FileOpen(
SDL_RWops*
ctx)
1151 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1157 jobject assetManager;
1158 jobject inputStream;
1160 jobject readableByteChannel;
1161 jstring fileNameJString;
1164 jfieldID descriptor;
1167 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1171 fileNameJString = (jstring)ctx->
hidden.androidio.fileNameRef;
1172 ctx->
hidden.androidio.position = 0;
1175 context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, midGetContext);
1178 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
1179 "getAssets",
"()Landroid/content/res/AssetManager;");
1180 assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
1185 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
"openFd",
"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
1186 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
1187 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1191 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getStartOffset",
"()J");
1192 ctx->
hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
1193 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1197 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getDeclaredLength",
"()J");
1198 ctx->
hidden.androidio.
size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
1199 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1203 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getFileDescriptor",
"()Ljava/io/FileDescriptor;");
1204 fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
1205 fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
1206 descriptor = (*mEnv)->GetFieldID(mEnv, fdCls,
"descriptor",
"I");
1207 ctx->
hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
1208 ctx->
hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
1211 lseek(ctx->
hidden.androidio.fd, (off_t)ctx->
hidden.androidio.offset, SEEK_SET);
1219 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
1222 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
1223 "open",
"(Ljava/lang/String;I)Ljava/io/InputStream;");
1224 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 );
1225 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1227 inputStream = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, midOpenAPKExpansionInputStream, fileNameJString);
1232 if (Android_JNI_ExceptionOccurred(
SDL_FALSE) || !inputStream) {
1237 ctx->
hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
1247 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1248 "available",
"()I");
1249 ctx->
hidden.androidio.
size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
1250 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1255 channels = (*mEnv)->FindClass(mEnv,
"java/nio/channels/Channels");
1256 mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
1258 "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
1259 readableByteChannel = (*mEnv)->CallStaticObjectMethod(
1260 mEnv, channels, mid, inputStream);
1261 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1265 ctx->
hidden.androidio.readableByteChannelRef =
1266 (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
1269 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
1270 "read",
"(Ljava/nio/ByteBuffer;)I");
1271 ctx->
hidden.androidio.readMethod = mid;
1278 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1280 if(ctx->
hidden.androidio.inputStreamRef !=
NULL) {
1281 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1284 if(ctx->
hidden.androidio.readableByteChannelRef !=
NULL) {
1285 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1288 if(ctx->
hidden.androidio.assetFileDescriptorRef !=
NULL) {
1289 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1294 LocalReferenceHolder_Cleanup(&refs);
1299 const char* fileName,
const char*
mode)
1301 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1304 jstring fileNameJString;
1306 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1307 LocalReferenceHolder_Cleanup(&refs);
1312 LocalReferenceHolder_Cleanup(&refs);
1316 fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
1317 ctx->
hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
1319 ctx->
hidden.androidio.readableByteChannelRef =
NULL;
1321 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
1323 retval = Internal_Android_JNI_FileOpen(ctx);
1324 LocalReferenceHolder_Cleanup(&refs);
1329 size_t size,
size_t maxnum)
1331 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1333 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1334 size_t bytesMax = size * maxnum;
1339 result = read(ctx->
hidden.androidio.fd, buffer, bytesMax );
1342 LocalReferenceHolder_Cleanup(&refs);
1343 return result /
size;
1345 LocalReferenceHolder_Cleanup(&refs);
1348 jlong bytesRemaining = (jlong) (size * maxnum);
1349 jlong bytesMax = (jlong) (ctx->
hidden.androidio.
size - ctx->
hidden.androidio.position);
1352 jobject readableByteChannel;
1353 jmethodID readMethod;
1357 if (bytesRemaining > bytesMax) bytesRemaining = bytesMax;
1360 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1361 LocalReferenceHolder_Cleanup(&refs);
1365 readableByteChannel = (jobject)ctx->
hidden.androidio.readableByteChannelRef;
1366 readMethod = (jmethodID)ctx->
hidden.androidio.readMethod;
1367 byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
1369 while (bytesRemaining > 0) {
1371 int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
1373 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1374 LocalReferenceHolder_Cleanup(&refs);
1382 bytesRemaining -=
result;
1386 LocalReferenceHolder_Cleanup(&refs);
1387 return bytesRead /
size;
1392 size_t size,
size_t num)
1394 SDL_SetError(
"Cannot write to Android package filesystem");
1400 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1405 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1406 LocalReferenceHolder_Cleanup(&refs);
1407 return SDL_SetError(
"Failed to allocate enough JVM local references");
1412 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1415 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1416 jobject inputStream = (jobject)ctx->
hidden.androidio.assetFileDescriptorRef;
1417 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1419 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1420 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1421 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1426 jobject inputStream = (jobject)ctx->
hidden.androidio.inputStreamRef;
1429 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1431 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1432 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1433 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1434 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1444 LocalReferenceHolder_Cleanup(&refs);
1456 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1461 offset += ctx->
hidden.androidio.offset;
1464 offset += ctx->
hidden.androidio.position;
1466 offset += ctx->
hidden.androidio.offset;
1476 ret = lseek(ctx->
hidden.androidio.fd, (off_t)offset, SEEK_SET);
1477 if (ret == -1)
return -1;
1478 ctx->
hidden.androidio.position = ret - ctx->
hidden.androidio.offset;
1498 if (newPosition < 0) {
1501 if (newPosition > ctx->
hidden.androidio.
size) {
1505 movement = newPosition - ctx->
hidden.androidio.position;
1507 unsigned char buffer[4096];
1510 while (movement > 0) {
1513 if (amount > movement) {
1525 }
else if (movement < 0) {
1528 Internal_Android_JNI_FileClose(ctx,
SDL_FALSE);
1529 Internal_Android_JNI_FileOpen(ctx);
1534 return ctx->
hidden.androidio.position;
1540 return Internal_Android_JNI_FileClose(ctx,
SDL_TRUE);
1546 jstring
string = (*env)->NewStringUTF(env, text);
1547 (*env)->CallStaticVoidMethod(env, mActivityClass, midClipboardSetText,
string);
1548 (*env)->DeleteLocalRef(env,
string);
1558 string = (*env)->CallStaticObjectMethod(env, mActivityClass, midClipboardGetText);
1560 const char* utf = (*env)->GetStringUTFChars(env,
string, 0);
1563 (*env)->ReleaseStringUTFChars(env,
string, utf);
1565 (*env)->DeleteLocalRef(env,
string);
1574 jboolean retval = (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText);
1584 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1596 if (!LocalReferenceHolder_Init(&refs, env)) {
1597 LocalReferenceHolder_Cleanup(&refs);
1603 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1605 action = (*env)->NewStringUTF(env,
"android.intent.action.BATTERY_CHANGED");
1607 cls = (*env)->FindClass(env,
"android/content/IntentFilter");
1609 mid = (*env)->GetMethodID(env, cls,
"<init>",
"(Ljava/lang/String;)V");
1610 filter = (*env)->NewObject(env, cls, mid, action);
1612 (*env)->DeleteLocalRef(env, action);
1614 mid = (*env)->GetMethodID(env, mActivityClass,
"registerReceiver",
"(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
1615 intent = (*env)->CallObjectMethod(env, context, mid,
NULL, filter);
1617 (*env)->DeleteLocalRef(env, filter);
1619 cls = (*env)->GetObjectClass(env, intent);
1621 imid = (*env)->GetMethodID(env, cls,
"getIntExtra",
"(Ljava/lang/String;I)I");
1624 #define GET_INT_EXTRA(var, key) \ 1626 iname = (*env)->NewStringUTF(env, key); \ 1627 var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \ 1628 (*env)->DeleteLocalRef(env, iname); 1630 bmid = (*env)->GetMethodID(env, cls,
"getBooleanExtra",
"(Ljava/lang/String;Z)Z");
1633 #define GET_BOOL_EXTRA(var, key) \ 1635 bname = (*env)->NewStringUTF(env, key); \ 1636 var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \ 1637 (*env)->DeleteLocalRef(env, bname); 1641 GET_INT_EXTRA(plug,
"plugged")
1643 LocalReferenceHolder_Cleanup(&refs);
1648 *plugged = (0 < plug) ? 1 : 0;
1653 GET_INT_EXTRA(status,
"status")
1655 LocalReferenceHolder_Cleanup(&refs);
1659 *charged = (status == 5) ? 1 : 0;
1663 GET_BOOL_EXTRA(present,
"present")
1664 *battery = present ? 1 : 0;
1677 GET_INT_EXTRA(level_temp,
"level")
1682 GET_INT_EXTRA(scale_temp,
"scale")
1686 if ((level == -1) || (scale == -1)) {
1687 LocalReferenceHolder_Cleanup(&refs);
1690 *percent = level * 100 /
scale;
1693 (*env)->DeleteLocalRef(env, intent);
1695 LocalReferenceHolder_Cleanup(&refs);
1703 jintArray
array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, midInputGetInputDeviceIds, sources);
1707 number = (int) (*env)->GetArrayLength(env, array);
1709 jint* elements = (*env)->GetIntArrayElements(env, array,
NULL);
1713 for (i = 0; i < number; ++
i) {
1714 (*ids)[
i] = elements[
i];
1716 (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
1719 (*env)->DeleteLocalRef(env, array);
1728 (*env)->SetStaticBooleanField(env, mActivityClass, fidSeparateMouseAndTouch, new_value ? JNI_TRUE : JNI_FALSE);
1734 (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollInputDevices);
1740 (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollHapticDevices);
1746 (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, length);
1751 #define COMMAND_SET_KEEP_SCREEN_ON 5 1758 success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midSendMessage, command, param);
1759 return success ? 0 : -1;
1770 (*env)->CallStaticBooleanMethod(env, mActivityClass, midShowTextInput,
1780 const int COMMAND_TEXTEDIT_HIDE = 3;
1787 jboolean is_shown = 0;
1788 is_shown = (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midIsScreenKeyboardShown);
1801 jintArray button_flags;
1802 jintArray button_ids;
1803 jobjectArray button_texts;
1813 clazz = (*env)->FindClass(env,
"java/lang/String");
1815 title = (*env)->NewStringUTF(env, messageboxdata->
title);
1816 message = (*env)->NewStringUTF(env, messageboxdata->
message);
1818 button_flags = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1819 button_ids = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1820 button_texts = (*env)->NewObjectArray(env, messageboxdata->
numbuttons,
1822 for (i = 0; i < messageboxdata->
numbuttons; ++
i) {
1824 (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
1826 (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
1827 text = (*env)->NewStringUTF(env, messageboxdata->
buttons[i].
text);
1828 (*env)->SetObjectArrayElement(env, button_texts, i, text);
1829 (*env)->DeleteLocalRef(env, text);
1835 temp = (0xFF << 24) |
1839 (*env)->SetIntArrayRegion(env, colors, i, 1, &temp);
1845 (*env)->DeleteLocalRef(env, clazz);
1848 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1850 clazz = (*env)->GetObjectClass(env, context);
1852 mid = (*env)->GetMethodID(env, clazz,
1853 "messageboxShowMessageBox",
"(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
1854 *buttonid = (*env)->CallIntMethod(env, context, mid,
1855 messageboxdata->
flags,
1863 (*env)->DeleteLocalRef(env, context);
1864 (*env)->DeleteLocalRef(env, clazz);
1868 (*env)->DeleteLocalRef(env, title);
1869 (*env)->DeleteLocalRef(env, message);
1870 (*env)->DeleteLocalRef(env, button_flags);
1871 (*env)->DeleteLocalRef(env, button_ids);
1872 (*env)->DeleteLocalRef(env, button_texts);
1873 (*env)->DeleteLocalRef(env, colors);
1881 // Functions exposed to SDL applications in SDL_system.h
1900 return (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1905 static char *s_AndroidInternalFilesPath =
NULL;
1907 if (!s_AndroidInternalFilesPath) {
1908 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1916 if (!LocalReferenceHolder_Init(&refs, env)) {
1917 LocalReferenceHolder_Cleanup(&refs);
1922 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1925 LocalReferenceHolder_Cleanup(&refs);
1930 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1931 "getFilesDir",
"()Ljava/io/File;");
1932 fileObject = (*env)->CallObjectMethod(env, context, mid);
1935 LocalReferenceHolder_Cleanup(&refs);
1940 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1941 "getAbsolutePath",
"()Ljava/lang/String;");
1942 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1944 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
1945 s_AndroidInternalFilesPath =
SDL_strdup(path);
1946 (*env)->ReleaseStringUTFChars(env, pathString, path);
1948 LocalReferenceHolder_Cleanup(&refs);
1950 return s_AndroidInternalFilesPath;
1955 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1958 jstring stateString;
1963 if (!LocalReferenceHolder_Init(&refs, env)) {
1964 LocalReferenceHolder_Cleanup(&refs);
1968 cls = (*env)->FindClass(env,
"android/os/Environment");
1969 mid = (*env)->GetStaticMethodID(env, cls,
1970 "getExternalStorageState",
"()Ljava/lang/String;");
1971 stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
1973 state = (*env)->GetStringUTFChars(env, stateString,
NULL);
1976 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"external storage state: %s", state);
1979 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
1980 SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
1981 }
else if (
SDL_strcmp(state,
"mounted_ro") == 0) {
1982 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
1986 (*env)->ReleaseStringUTFChars(env, stateString, state);
1988 LocalReferenceHolder_Cleanup(&refs);
1994 static char *s_AndroidExternalFilesPath =
NULL;
1996 if (!s_AndroidExternalFilesPath) {
1997 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
2005 if (!LocalReferenceHolder_Init(&refs, env)) {
2006 LocalReferenceHolder_Cleanup(&refs);
2011 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
2014 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
2015 "getExternalFilesDir",
"(Ljava/lang/String;)Ljava/io/File;");
2016 fileObject = (*env)->CallObjectMethod(env, context, mid,
NULL);
2019 LocalReferenceHolder_Cleanup(&refs);
2024 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
2025 "getAbsolutePath",
"()Ljava/lang/String;");
2026 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
2028 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
2029 s_AndroidExternalFilesPath =
SDL_strdup(path);
2030 (*env)->ReleaseStringUTFChars(env, pathString, path);
2032 LocalReferenceHolder_Cleanup(&refs);
2034 return s_AndroidExternalFilesPath;
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_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)
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
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)
union SDL_RWops::@10 hidden
static char text[MAX_TEXT_LENGTH]
C_LINKAGE int SDL_main(int argc, char *argv[])
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)
int Android_JNI_SetClipboardText(const char *text)
#define SDL_AndroidGetExternalStorageState
SDL_VideoDevice * SDL_GetVideoDevice(void)
SDL_bool Android_JNI_IsScreenKeyboardShown(void)
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)
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)