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_INTERFACE_INPUT_CONNECTION(function) CONCAT1(SDL_JAVA_PREFIX, SDLInputConnection, function) 63 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(
64 JNIEnv* mEnv, jclass cls);
66 JNIEXPORT
int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(
67 JNIEnv* env, jclass cls,
68 jstring library, jstring
function, jobject
array);
70 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
71 JNIEnv* env, jclass jcls,
74 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
75 JNIEnv* env, jclass jcls,
78 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadDown)(
79 JNIEnv* env, jclass jcls,
80 jint device_id, jint keycode);
82 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadUp)(
83 JNIEnv* env, jclass jcls,
84 jint device_id, jint keycode);
86 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeJoy)(
87 JNIEnv* env, jclass jcls,
90 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeHat)(
91 JNIEnv* env, jclass jcls,
92 jint device_id, jint hat_id, jint
x, jint
y);
94 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddJoystick)(
95 JNIEnv* env, jclass jcls,
96 jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
97 jint nbuttons, jint naxes, jint nhats, jint nballs);
99 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveJoystick)(
100 JNIEnv* env, jclass jcls,
103 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddHaptic)(
104 JNIEnv* env, jclass jcls,
105 jint device_id, jstring device_name);
107 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveHaptic)(
108 JNIEnv* env, jclass jcls,
111 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
112 JNIEnv* env, jclass jcls);
114 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(
115 JNIEnv* env, jclass jcls);
117 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)(
118 JNIEnv* env, jclass jcls,
121 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)(
122 JNIEnv* env, jclass jcls,
125 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)(
126 JNIEnv* env, jclass jcls);
128 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
129 JNIEnv* env, jclass jcls,
130 jint touch_device_id_in, jint pointer_finger_id_in,
131 jint action, jfloat
x, jfloat
y, jfloat
p);
133 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
134 JNIEnv* env, jclass jcls,
135 jint
button, jint action, jfloat
x, jfloat
y);
137 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
138 JNIEnv* env, jclass jcls,
139 jfloat
x, jfloat
y, jfloat
z);
141 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeClipboardChanged)(
142 JNIEnv* env, jclass jcls);
144 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeLowMemory)(
145 JNIEnv* env, jclass cls);
147 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
148 JNIEnv* env, jclass cls);
150 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativePause)(
151 JNIEnv* env, jclass cls);
153 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
154 JNIEnv* env, jclass cls);
156 JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
157 JNIEnv* env, jclass cls,
161 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
162 JNIEnv* env, jclass cls,
163 jstring
text, jint newCursorPosition);
165 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
166 JNIEnv* env, jclass cls,
167 jstring
text, jint newCursorPosition);
173 static void Android_JNI_ThreadDestroyed(
void*);
184 static pthread_key_t mThreadKey;
185 static JavaVM* mJavaVM;
188 static jclass mActivityClass;
191 static jmethodID midGetNativeSurface;
192 static jmethodID midAudioOpen;
193 static jmethodID midAudioWriteShortBuffer;
194 static jmethodID midAudioWriteByteBuffer;
195 static jmethodID midAudioClose;
196 static jmethodID midCaptureOpen;
197 static jmethodID midCaptureReadShortBuffer;
198 static jmethodID midCaptureReadByteBuffer;
199 static jmethodID midCaptureClose;
200 static jmethodID midPollInputDevices;
201 static jmethodID midPollHapticDevices;
202 static jmethodID midHapticRun;
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;
216 static jfieldID fidSeparateMouseAndTouch;
219 static float fLastAccelerometer[3];
227 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,
void* reserved)
231 LOGI(
"JNI_OnLoad called");
232 if ((*mJavaVM)->GetEnv(mJavaVM, (
void**) &env, JNI_VERSION_1_4) != JNI_OK) {
233 LOGE(
"Failed to get the environment using GetEnv()");
240 if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed) != 0) {
241 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"Error initializing pthread key");
245 return JNI_VERSION_1_4;
249 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
251 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeSetupJNI()");
255 mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
257 midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
258 "getNativeSurface",
"()Landroid/view/Surface;");
259 midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
260 "audioOpen",
"(IZZI)I");
261 midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
262 "audioWriteShortBuffer",
"([S)V");
263 midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
264 "audioWriteByteBuffer",
"([B)V");
265 midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
266 "audioClose",
"()V");
267 midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
268 "captureOpen",
"(IZZI)I");
269 midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
270 "captureReadShortBuffer",
"([SZ)I");
271 midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
272 "captureReadByteBuffer",
"([BZ)I");
273 midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
274 "captureClose",
"()V");
275 midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
276 "pollInputDevices",
"()V");
277 midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
278 "pollHapticDevices",
"()V");
279 midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
280 "hapticRun",
"(II)V");
281 midSetActivityTitle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
282 "setActivityTitle",
"(Ljava/lang/String;)Z");
283 midSetOrientation = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
284 "setOrientation",
"(IIZLjava/lang/String;)V");
285 midGetContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
286 "getContext",
"()Landroid/content/Context;");
287 midInputGetInputDeviceIds = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
288 "inputGetInputDeviceIds",
"(I)[I");
289 midSendMessage = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
290 "sendMessage",
"(II)Z");
291 midShowTextInput = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
292 "showTextInput",
"(IIII)Z");
293 midIsScreenKeyboardShown = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
294 "isScreenKeyboardShown",
"()Z");
295 midClipboardSetText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
296 "clipboardSetText",
"(Ljava/lang/String;)V");
297 midClipboardGetText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
298 "clipboardGetText",
"()Ljava/lang/String;");
299 midClipboardHasText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
300 "clipboardHasText",
"()Z");
304 if (!midGetNativeSurface ||
305 !midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
306 !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose ||
307 !midPollInputDevices || !midPollHapticDevices || !midHapticRun ||
308 !midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
309 !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
310 !midClipboardSetText || !midClipboardGetText || !midClipboardHasText) {
311 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
314 fidSeparateMouseAndTouch = (*mEnv)->GetStaticFieldID(mEnv, mActivityClass,
"mSeparateMouseAndTouch",
"Z");
316 if (!fidSeparateMouseAndTouch) {
317 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"Missing some Java static fields, do you have the latest version of SDLActivity.java?");
324 typedef int (*SDL_main_func)(
int argc,
char *argv[]);
327 JNIEXPORT
int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv* env, jclass cls, jstring library, jstring
function, jobject
array)
330 const char *library_file;
331 void *library_handle;
333 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeRunMain()");
335 library_file = (*env)->GetStringUTFChars(env, library,
NULL);
336 library_handle = dlopen(library_file, RTLD_GLOBAL);
337 if (library_handle) {
338 const char *function_name;
341 function_name = (*env)->GetStringUTFChars(env,
function,
NULL);
342 SDL_main = (SDL_main_func)dlsym(library_handle, function_name);
350 len = (*env)->GetArrayLength(env,
array);
357 for (i = 0; i <
len; ++
i) {
360 jstring
string = (*env)->GetObjectArrayElement(env,
array, i);
362 utf = (*env)->GetStringUTFChars(env,
string, 0);
365 (*env)->ReleaseStringUTFChars(env,
string, utf);
367 (*env)->DeleteLocalRef(env,
string);
381 for (i = 0; i < argc; ++
i) {
387 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"nativeRunMain(): Couldn't find function %s in library %s", function_name, library_file);
389 (*env)->ReleaseStringUTFChars(env,
function, function_name);
391 dlclose(library_handle);
394 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"nativeRunMain(): Couldn't load library %s", library_file);
396 (*env)->ReleaseStringUTFChars(env, library, library_file);
405 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
406 JNIEnv* env, jclass jcls,
411 (*env)->ReleaseStringUTFChars(env,
filename, path);
416 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
417 JNIEnv* env, jclass jcls,
424 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadDown)(
425 JNIEnv* env, jclass jcls,
426 jint device_id, jint keycode)
428 return Android_OnPadDown(device_id, keycode);
432 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadUp)(
433 JNIEnv* env, jclass jcls,
434 jint device_id, jint keycode)
436 return Android_OnPadUp(device_id, keycode);
440 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeJoy)(
441 JNIEnv* env, jclass jcls,
444 Android_OnJoy(device_id, axis,
value);
448 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeHat)(
449 JNIEnv* env, jclass jcls,
450 jint device_id, jint hat_id, jint
x, jint
y)
452 Android_OnHat(device_id, hat_id, x,
y);
456 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddJoystick)(
457 JNIEnv* env, jclass jcls,
458 jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
459 jint nbuttons, jint naxes, jint nhats, jint nballs)
462 const char *
name = (*env)->GetStringUTFChars(env, device_name,
NULL);
463 const char *desc = (*env)->GetStringUTFChars(env, device_desc,
NULL);
465 retval = Android_AddJoystick(device_id, name, desc, (
SDL_bool) is_accelerometer, nbuttons, naxes, nhats, nballs);
467 (*env)->ReleaseStringUTFChars(env, device_name, name);
468 (*env)->ReleaseStringUTFChars(env, device_desc, desc);
473 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveJoystick)(
474 JNIEnv* env, jclass jcls,
477 return Android_RemoveJoystick(device_id);
480 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddHaptic)(
481 JNIEnv* env, jclass jcls, jint device_id, jstring device_name)
484 const char *name = (*env)->GetStringUTFChars(env, device_name,
NULL);
486 retval = Android_AddHaptic(device_id, name);
488 (*env)->ReleaseStringUTFChars(env, device_name, name);
493 JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveHaptic)(
494 JNIEnv* env, jclass jcls, jint device_id)
496 return Android_RemoveHaptic(device_id);
501 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv* env, jclass jcls)
527 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv* env, jclass jcls)
544 SDL_EGL_MakeCurrent(_this,
NULL,
NULL);
554 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)(
555 JNIEnv* env, jclass jcls,
562 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)(
563 JNIEnv* env, jclass jcls,
570 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)(
571 JNIEnv* env, jclass jcls)
579 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
580 JNIEnv* env, jclass jcls,
581 jint touch_device_id_in, jint pointer_finger_id_in,
582 jint action, jfloat
x, jfloat
y, jfloat
p)
588 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
589 JNIEnv* env, jclass jcls,
590 jint
button, jint action, jfloat
x, jfloat
y)
596 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
597 JNIEnv* env, jclass jcls,
598 jfloat
x, jfloat
y, jfloat
z)
600 fLastAccelerometer[0] =
x;
601 fLastAccelerometer[1] =
y;
602 fLastAccelerometer[2] =
z;
607 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(onNativeClipboardChanged)(
608 JNIEnv* env, jclass jcls)
614 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeLowMemory)(
615 JNIEnv* env, jclass cls)
621 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
622 JNIEnv* env, jclass cls)
637 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativePause)(
638 JNIEnv* env, jclass cls)
640 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativePause()");
655 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
656 JNIEnv* env, jclass cls)
658 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeResume()");
673 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
674 JNIEnv* env, jclass cls,
675 jstring
text, jint newCursorPosition)
677 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
681 (*env)->ReleaseStringUTFChars(env, text, utftext);
684 JNIEXPORT
void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
685 JNIEnv* env, jclass cls,
686 jstring
text, jint newCursorPosition)
688 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
692 (*env)->ReleaseStringUTFChars(env, text, utftext);
695 JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
696 JNIEnv* env, jclass cls,
699 const char *utfname = (*env)->GetStringUTFChars(env, name,
NULL);
702 jstring
result = (*env)->NewStringUTF(env, hint);
703 (*env)->ReleaseStringUTFChars(env, name, utfname);
712 static int s_active = 0;
713 struct LocalReferenceHolder
719 static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *
func)
721 struct LocalReferenceHolder refholder;
722 refholder.m_env =
NULL;
723 refholder.m_func =
func;
730 static SDL_bool LocalReferenceHolder_Init(
struct LocalReferenceHolder *refholder, JNIEnv *env)
732 const int capacity = 16;
733 if ((*env)->PushLocalFrame(env, capacity) < 0) {
734 SDL_SetError(
"Failed to allocate enough JVM local references");
738 refholder->m_env = env;
742 static void LocalReferenceHolder_Cleanup(
struct LocalReferenceHolder *refholder)
745 SDL_Log(
"Leaving function %s", refholder->m_func);
747 if (refholder->m_env) {
748 JNIEnv* env = refholder->m_env;
749 (*env)->PopLocalFrame(env,
NULL);
754 static SDL_bool LocalReferenceHolder_IsActive(
void)
765 s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
766 anw = ANativeWindow_fromSurface(env, s);
767 (*env)->DeleteLocalRef(env, s);
776 jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
777 (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midSetActivityTitle, jtitle);
778 (*mEnv)->DeleteLocalRef(mEnv, jtitle);
785 jstring jhint = (jstring)((*mEnv)->NewStringUTF(mEnv, (hint ? hint :
"")));
786 (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midSetOrientation, w, h, (resizable? 1 : 0), jhint);
787 (*mEnv)->DeleteLocalRef(mEnv, jhint);
796 for (i = 0; i < 3; ++
i) {
797 values[
i] = fLastAccelerometer[
i];
806 static void Android_JNI_ThreadDestroyed(
void*
value)
809 JNIEnv *env = (JNIEnv*) value;
811 (*mJavaVM)->DetachCurrentThread(mJavaVM);
812 pthread_setspecific(mThreadKey,
NULL);
831 int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env,
NULL);
833 LOGE(
"failed to attach current thread");
846 pthread_setspecific(mThreadKey, (
void*) env);
860 static jboolean audioBuffer16Bit = JNI_FALSE;
861 static jobject audioBuffer =
NULL;
862 static void* audioBufferPinned =
NULL;
863 static jboolean captureBuffer16Bit = JNI_FALSE;
864 static jobject captureBuffer =
NULL;
868 jboolean audioBufferStereo;
869 int audioBufferFrames;
870 jobject jbufobj =
NULL;
876 LOGE(
"callback_handler: failed to attach current thread");
880 audioBufferStereo = channelCount > 1;
883 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for capture");
884 captureBuffer16Bit = is16Bit;
885 if ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
887 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioRecord initialization!");
891 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for output");
892 audioBuffer16Bit = is16Bit;
893 if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
895 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioTrack initialization!");
904 jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
905 if (audioBufferLocal) {
906 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
907 (*env)->DeleteLocalRef(env, audioBufferLocal);
911 jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
912 if (audioBufferLocal) {
913 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
914 (*env)->DeleteLocalRef(env, audioBufferLocal);
918 if (jbufobj ==
NULL) {
919 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: could not allocate an audio buffer!");
924 captureBuffer = jbufobj;
926 audioBuffer = jbufobj;
933 audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
935 audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
938 audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
940 audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
943 if (audioBufferStereo) {
944 audioBufferFrames /= 2;
947 return audioBufferFrames;
952 return audioBufferPinned;
959 if (audioBuffer16Bit) {
960 (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
961 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
963 (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
964 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
973 jboolean isCopy = JNI_FALSE;
976 if (captureBuffer16Bit) {
977 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
978 br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
980 jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
983 (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
986 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
987 br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
989 jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
991 (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
1002 if (captureBuffer16Bit) {
1003 const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
1004 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) ==
len) { }
1006 const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
1007 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) ==
len) { }
1010 if (captureBuffer16Bit) {
1011 (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
1013 (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
1023 (*env)->CallStaticVoidMethod(env, mActivityClass, midCaptureClose);
1024 if (captureBuffer) {
1025 (*env)->DeleteGlobalRef(env, captureBuffer);
1026 captureBuffer =
NULL;
1029 (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioClose);
1031 (*env)->DeleteGlobalRef(env, audioBuffer);
1033 audioBufferPinned =
NULL;
1043 jthrowable exception;
1047 exception = (*mEnv)->ExceptionOccurred(mEnv);
1048 if (exception !=
NULL) {
1052 (*mEnv)->ExceptionClear(mEnv);
1055 jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
1056 jclass classClass = (*mEnv)->FindClass(mEnv,
"java/lang/Class");
1057 jstring exceptionName;
1058 const char* exceptionNameUTF8;
1059 jstring exceptionMessage;
1061 mid = (*mEnv)->GetMethodID(mEnv, classClass,
"getName",
"()Ljava/lang/String;");
1062 exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
1063 exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
1065 mid = (*mEnv)->GetMethodID(mEnv, exceptionClass,
"getMessage",
"()Ljava/lang/String;");
1066 exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
1068 if (exceptionMessage !=
NULL) {
1069 const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
1070 SDL_SetError(
"%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
1071 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
1076 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
1085 static int Internal_Android_JNI_FileOpen(
SDL_RWops*
ctx)
1087 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1093 jobject assetManager;
1094 jobject inputStream;
1096 jobject readableByteChannel;
1097 jstring fileNameJString;
1100 jfieldID descriptor;
1103 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1107 fileNameJString = (jstring)ctx->
hidden.androidio.fileNameRef;
1108 ctx->
hidden.androidio.position = 0;
1111 context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, midGetContext);
1114 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
1115 "getAssets",
"()Landroid/content/res/AssetManager;");
1116 assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
1121 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
"openFd",
"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
1122 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
1123 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1127 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getStartOffset",
"()J");
1128 ctx->
hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
1129 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1133 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getDeclaredLength",
"()J");
1134 ctx->
hidden.androidio.
size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
1135 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
1139 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getFileDescriptor",
"()Ljava/io/FileDescriptor;");
1140 fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
1141 fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
1142 descriptor = (*mEnv)->GetFieldID(mEnv, fdCls,
"descriptor",
"I");
1143 ctx->
hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
1144 ctx->
hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
1147 lseek(ctx->
hidden.androidio.fd, (off_t)ctx->
hidden.androidio.offset, SEEK_SET);
1155 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
1158 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
1159 "open",
"(Ljava/lang/String;I)Ljava/io/InputStream;");
1160 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 );
1161 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1163 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
1164 "openAPKExpansionInputStream",
"(Ljava/lang/String;)Ljava/io/InputStream;");
1166 SDL_SetError(
"No openAPKExpansionInputStream() in Java class");
1169 inputStream = (*mEnv)->CallObjectMethod(mEnv, context, mid, fileNameJString);
1174 if (Android_JNI_ExceptionOccurred(
SDL_FALSE) || !inputStream) {
1179 ctx->
hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
1189 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1190 "available",
"()I");
1191 ctx->
hidden.androidio.
size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
1192 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1197 channels = (*mEnv)->FindClass(mEnv,
"java/nio/channels/Channels");
1198 mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
1200 "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
1201 readableByteChannel = (*mEnv)->CallStaticObjectMethod(
1202 mEnv, channels, mid, inputStream);
1203 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1207 ctx->
hidden.androidio.readableByteChannelRef =
1208 (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
1211 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
1212 "read",
"(Ljava/nio/ByteBuffer;)I");
1213 ctx->
hidden.androidio.readMethod = mid;
1220 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1222 if(ctx->
hidden.androidio.inputStreamRef !=
NULL) {
1223 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1226 if(ctx->
hidden.androidio.readableByteChannelRef !=
NULL) {
1227 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1230 if(ctx->
hidden.androidio.assetFileDescriptorRef !=
NULL) {
1231 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1236 LocalReferenceHolder_Cleanup(&refs);
1241 const char* fileName,
const char*
mode)
1243 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1246 jstring fileNameJString;
1248 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1249 LocalReferenceHolder_Cleanup(&refs);
1254 LocalReferenceHolder_Cleanup(&refs);
1258 fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
1259 ctx->
hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
1261 ctx->
hidden.androidio.readableByteChannelRef =
NULL;
1263 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
1265 retval = Internal_Android_JNI_FileOpen(ctx);
1266 LocalReferenceHolder_Cleanup(&refs);
1271 size_t size,
size_t maxnum)
1273 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1275 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1276 size_t bytesMax = size * maxnum;
1281 result = read(ctx->
hidden.androidio.fd, buffer, bytesMax );
1284 LocalReferenceHolder_Cleanup(&refs);
1285 return result /
size;
1287 LocalReferenceHolder_Cleanup(&refs);
1290 jlong bytesRemaining = (jlong) (size * maxnum);
1291 jlong bytesMax = (jlong) (ctx->
hidden.androidio.
size - ctx->
hidden.androidio.position);
1294 jobject readableByteChannel;
1295 jmethodID readMethod;
1299 if (bytesRemaining > bytesMax) bytesRemaining = bytesMax;
1302 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1303 LocalReferenceHolder_Cleanup(&refs);
1307 readableByteChannel = (jobject)ctx->
hidden.androidio.readableByteChannelRef;
1308 readMethod = (jmethodID)ctx->
hidden.androidio.readMethod;
1309 byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
1311 while (bytesRemaining > 0) {
1313 int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
1315 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1316 LocalReferenceHolder_Cleanup(&refs);
1324 bytesRemaining -=
result;
1328 LocalReferenceHolder_Cleanup(&refs);
1329 return bytesRead /
size;
1334 size_t size,
size_t num)
1336 SDL_SetError(
"Cannot write to Android package filesystem");
1342 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1347 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1348 LocalReferenceHolder_Cleanup(&refs);
1349 return SDL_SetError(
"Failed to allocate enough JVM local references");
1354 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1357 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1358 jobject inputStream = (jobject)ctx->
hidden.androidio.assetFileDescriptorRef;
1359 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1361 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1362 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1363 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1368 jobject inputStream = (jobject)ctx->
hidden.androidio.inputStreamRef;
1371 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1373 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1374 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1375 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1376 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1386 LocalReferenceHolder_Cleanup(&refs);
1398 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1403 offset += ctx->
hidden.androidio.offset;
1406 offset += ctx->
hidden.androidio.position;
1408 offset += ctx->
hidden.androidio.offset;
1418 ret = lseek(ctx->
hidden.androidio.fd, (off_t)offset, SEEK_SET);
1419 if (ret == -1)
return -1;
1420 ctx->
hidden.androidio.position = ret - ctx->
hidden.androidio.offset;
1440 if (newPosition < 0) {
1443 if (newPosition > ctx->
hidden.androidio.
size) {
1447 movement = newPosition - ctx->
hidden.androidio.position;
1449 unsigned char buffer[4096];
1452 while (movement > 0) {
1455 if (amount > movement) {
1467 }
else if (movement < 0) {
1470 Internal_Android_JNI_FileClose(ctx,
SDL_FALSE);
1471 Internal_Android_JNI_FileOpen(ctx);
1476 return ctx->
hidden.androidio.position;
1482 return Internal_Android_JNI_FileClose(ctx,
SDL_TRUE);
1488 jstring
string = (*env)->NewStringUTF(env, text);
1489 (*env)->CallStaticVoidMethod(env, mActivityClass, midClipboardSetText,
string);
1490 (*env)->DeleteLocalRef(env,
string);
1500 string = (*env)->CallStaticObjectMethod(env, mActivityClass, midClipboardGetText);
1502 const char* utf = (*env)->GetStringUTFChars(env,
string, 0);
1505 (*env)->ReleaseStringUTFChars(env,
string, utf);
1507 (*env)->DeleteLocalRef(env,
string);
1516 jboolean retval = (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText);
1526 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1538 if (!LocalReferenceHolder_Init(&refs, env)) {
1539 LocalReferenceHolder_Cleanup(&refs);
1545 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1547 action = (*env)->NewStringUTF(env,
"android.intent.action.BATTERY_CHANGED");
1549 cls = (*env)->FindClass(env,
"android/content/IntentFilter");
1551 mid = (*env)->GetMethodID(env, cls,
"<init>",
"(Ljava/lang/String;)V");
1552 filter = (*env)->NewObject(env, cls, mid, action);
1554 (*env)->DeleteLocalRef(env, action);
1556 mid = (*env)->GetMethodID(env, mActivityClass,
"registerReceiver",
"(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
1557 intent = (*env)->CallObjectMethod(env, context, mid,
NULL, filter);
1559 (*env)->DeleteLocalRef(env, filter);
1561 cls = (*env)->GetObjectClass(env, intent);
1563 imid = (*env)->GetMethodID(env, cls,
"getIntExtra",
"(Ljava/lang/String;I)I");
1566 #define GET_INT_EXTRA(var, key) \ 1568 iname = (*env)->NewStringUTF(env, key); \ 1569 var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \ 1570 (*env)->DeleteLocalRef(env, iname); 1572 bmid = (*env)->GetMethodID(env, cls,
"getBooleanExtra",
"(Ljava/lang/String;Z)Z");
1575 #define GET_BOOL_EXTRA(var, key) \ 1577 bname = (*env)->NewStringUTF(env, key); \ 1578 var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \ 1579 (*env)->DeleteLocalRef(env, bname); 1583 GET_INT_EXTRA(plug,
"plugged")
1585 LocalReferenceHolder_Cleanup(&refs);
1590 *plugged = (0 < plug) ? 1 : 0;
1595 GET_INT_EXTRA(status,
"status")
1597 LocalReferenceHolder_Cleanup(&refs);
1601 *charged = (status == 5) ? 1 : 0;
1605 GET_BOOL_EXTRA(present,
"present")
1606 *battery = present ? 1 : 0;
1619 GET_INT_EXTRA(level_temp,
"level")
1624 GET_INT_EXTRA(scale_temp,
"scale")
1628 if ((level == -1) || (scale == -1)) {
1629 LocalReferenceHolder_Cleanup(&refs);
1632 *percent = level * 100 /
scale;
1635 (*env)->DeleteLocalRef(env, intent);
1637 LocalReferenceHolder_Cleanup(&refs);
1645 jintArray
array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, midInputGetInputDeviceIds, sources);
1649 number = (int) (*env)->GetArrayLength(env, array);
1651 jint* elements = (*env)->GetIntArrayElements(env, array,
NULL);
1655 for (i = 0; i < number; ++
i) {
1656 (*ids)[
i] = elements[
i];
1658 (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
1661 (*env)->DeleteLocalRef(env, array);
1670 (*env)->SetStaticBooleanField(env, mActivityClass, fidSeparateMouseAndTouch, new_value ? JNI_TRUE : JNI_FALSE);
1676 (*env)->CallStaticVoidMethod(env, mActivityClass, midPollInputDevices);
1682 (*env)->CallStaticVoidMethod(env, mActivityClass, midPollHapticDevices);
1688 (*env)->CallStaticVoidMethod(env, mActivityClass, midHapticRun, device_id, length);
1693 #define COMMAND_SET_KEEP_SCREEN_ON 5 1700 success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midSendMessage, command, param);
1701 return success ? 0 : -1;
1712 (*env)->CallStaticBooleanMethod(env, mActivityClass, midShowTextInput,
1722 const int COMMAND_TEXTEDIT_HIDE = 3;
1729 jboolean is_shown = 0;
1730 is_shown = (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midIsScreenKeyboardShown);
1743 jintArray button_flags;
1744 jintArray button_ids;
1745 jobjectArray button_texts;
1755 clazz = (*env)->FindClass(env,
"java/lang/String");
1757 title = (*env)->NewStringUTF(env, messageboxdata->
title);
1758 message = (*env)->NewStringUTF(env, messageboxdata->
message);
1760 button_flags = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1761 button_ids = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1762 button_texts = (*env)->NewObjectArray(env, messageboxdata->
numbuttons,
1764 for (i = 0; i < messageboxdata->
numbuttons; ++
i) {
1766 (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
1768 (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
1769 text = (*env)->NewStringUTF(env, messageboxdata->
buttons[i].
text);
1770 (*env)->SetObjectArrayElement(env, button_texts, i, text);
1771 (*env)->DeleteLocalRef(env, text);
1777 temp = (0xFF << 24) |
1781 (*env)->SetIntArrayRegion(env, colors, i, 1, &temp);
1787 (*env)->DeleteLocalRef(env, clazz);
1790 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1792 clazz = (*env)->GetObjectClass(env, context);
1794 mid = (*env)->GetMethodID(env, clazz,
1795 "messageboxShowMessageBox",
"(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
1796 *buttonid = (*env)->CallIntMethod(env, context, mid,
1797 messageboxdata->
flags,
1805 (*env)->DeleteLocalRef(env, context);
1806 (*env)->DeleteLocalRef(env, clazz);
1810 (*env)->DeleteLocalRef(env, title);
1811 (*env)->DeleteLocalRef(env, message);
1812 (*env)->DeleteLocalRef(env, button_flags);
1813 (*env)->DeleteLocalRef(env, button_ids);
1814 (*env)->DeleteLocalRef(env, button_texts);
1815 (*env)->DeleteLocalRef(env, colors);
1823 // Functions exposed to SDL applications in SDL_system.h
1842 return (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1847 static char *s_AndroidInternalFilesPath =
NULL;
1849 if (!s_AndroidInternalFilesPath) {
1850 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1858 if (!LocalReferenceHolder_Init(&refs, env)) {
1859 LocalReferenceHolder_Cleanup(&refs);
1864 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1867 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1868 "getFilesDir",
"()Ljava/io/File;");
1869 fileObject = (*env)->CallObjectMethod(env, context, mid);
1872 LocalReferenceHolder_Cleanup(&refs);
1877 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1878 "getAbsolutePath",
"()Ljava/lang/String;");
1879 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1881 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
1882 s_AndroidInternalFilesPath =
SDL_strdup(path);
1883 (*env)->ReleaseStringUTFChars(env, pathString, path);
1885 LocalReferenceHolder_Cleanup(&refs);
1887 return s_AndroidInternalFilesPath;
1892 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1895 jstring stateString;
1900 if (!LocalReferenceHolder_Init(&refs, env)) {
1901 LocalReferenceHolder_Cleanup(&refs);
1905 cls = (*env)->FindClass(env,
"android/os/Environment");
1906 mid = (*env)->GetStaticMethodID(env, cls,
1907 "getExternalStorageState",
"()Ljava/lang/String;");
1908 stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
1910 state = (*env)->GetStringUTFChars(env, stateString,
NULL);
1913 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"external storage state: %s", state);
1916 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
1917 SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
1918 }
else if (
SDL_strcmp(state,
"mounted_ro") == 0) {
1919 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
1923 (*env)->ReleaseStringUTFChars(env, stateString, state);
1925 LocalReferenceHolder_Cleanup(&refs);
1931 static char *s_AndroidExternalFilesPath =
NULL;
1933 if (!s_AndroidExternalFilesPath) {
1934 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1942 if (!LocalReferenceHolder_Init(&refs, env)) {
1943 LocalReferenceHolder_Cleanup(&refs);
1948 context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
1951 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1952 "getExternalFilesDir",
"(Ljava/lang/String;)Ljava/io/File;");
1953 fileObject = (*env)->CallObjectMethod(env, context, mid,
NULL);
1956 LocalReferenceHolder_Cleanup(&refs);
1961 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1962 "getAbsolutePath",
"()Ljava/lang/String;");
1963 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1965 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
1966 s_AndroidExternalFilesPath =
SDL_strdup(path);
1967 (*env)->ReleaseStringUTFChars(env, pathString, path);
1969 LocalReferenceHolder_Cleanup(&refs);
1971 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)
int64_t Sint64
A signed 64-bit integer type.
#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)