21 #include "../../SDL_internal.h" 33 #include "../../events/SDL_events_c.h" 34 #include "../../video/android/SDL_androidkeyboard.h" 35 #include "../../video/android/SDL_androidmouse.h" 36 #include "../../video/android/SDL_androidtouch.h" 37 #include "../../video/android/SDL_androidvideo.h" 38 #include "../../video/android/SDL_androidwindow.h" 39 #include "../../joystick/android/SDL_sysjoystick_c.h" 41 #include <android/log.h> 43 #include <sys/types.h> 45 #define LOG_TAG "SDL_android" 48 #define LOGI(...) do {} while (0) 49 #define LOGE(...) do {} while (0) 54 static void Android_JNI_ThreadDestroyed(
void*);
60 #include <android/log.h> 66 static pthread_key_t mThreadKey;
67 static JavaVM* mJavaVM;
70 static jclass mActivityClass;
73 static jmethodID midGetNativeSurface;
74 static jmethodID midAudioOpen;
75 static jmethodID midAudioWriteShortBuffer;
76 static jmethodID midAudioWriteByteBuffer;
77 static jmethodID midAudioClose;
78 static jmethodID midCaptureOpen;
79 static jmethodID midCaptureReadShortBuffer;
80 static jmethodID midCaptureReadByteBuffer;
81 static jmethodID midCaptureClose;
82 static jmethodID midPollInputDevices;
85 static float fLastAccelerometer[3];
93 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,
void* reserved)
97 LOGI(
"JNI_OnLoad called");
98 if ((*mJavaVM)->GetEnv(mJavaVM, (
void**) &env, JNI_VERSION_1_4) != JNI_OK) {
99 LOGE(
"Failed to get the environment using GetEnv()");
106 if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed) != 0) {
107 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"Error initializing pthread key");
111 return JNI_VERSION_1_4;
115 JNIEXPORT
void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls)
117 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"SDL_Android_Init()");
121 mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
123 midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
124 "getNativeSurface",
"()Landroid/view/Surface;");
125 midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
126 "audioOpen",
"(IZZI)I");
127 midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
128 "audioWriteShortBuffer",
"([S)V");
129 midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
130 "audioWriteByteBuffer",
"([B)V");
131 midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
132 "audioClose",
"()V");
133 midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
134 "captureOpen",
"(IZZI)I");
135 midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
136 "captureReadShortBuffer",
"([SZ)I");
137 midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
138 "captureReadByteBuffer",
"([BZ)I");
139 midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
140 "captureClose",
"()V");
141 midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
142 "pollInputDevices",
"()V");
146 if (!midGetNativeSurface ||
147 !midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
148 !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose ||
149 !midPollInputDevices) {
150 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
152 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"SDL_Android_Init() finished!");
156 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeDropFile(
157 JNIEnv* env, jclass jcls,
160 const char *
path = (*env)->GetStringUTFChars(env, filename,
NULL);
162 (*env)->ReleaseStringUTFChars(env, filename, path);
167 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeResize(
168 JNIEnv* env, jclass jcls,
175 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_onNativePadDown(
176 JNIEnv* env, jclass jcls,
177 jint device_id, jint keycode)
179 return Android_OnPadDown(device_id, keycode);
183 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_onNativePadUp(
184 JNIEnv* env, jclass jcls,
185 jint device_id, jint keycode)
187 return Android_OnPadUp(device_id, keycode);
191 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeJoy(
192 JNIEnv* env, jclass jcls,
195 Android_OnJoy(device_id, axis, value);
199 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeHat(
200 JNIEnv* env, jclass jcls,
201 jint device_id, jint hat_id, jint
x, jint
y)
203 Android_OnHat(device_id, hat_id, x, y);
207 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
208 JNIEnv* env, jclass jcls,
209 jint device_id, jstring device_name, jint is_accelerometer,
210 jint nbuttons, jint naxes, jint nhats, jint nballs)
213 const char *
name = (*env)->GetStringUTFChars(env, device_name,
NULL);
215 retval = Android_AddJoystick(device_id, name, (
SDL_bool) is_accelerometer, nbuttons, naxes, nhats, nballs);
217 (*env)->ReleaseStringUTFChars(env, device_name, name);
222 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_nativeRemoveJoystick(
223 JNIEnv* env, jclass jcls, jint device_id)
225 return Android_RemoveJoystick(device_id);
230 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
256 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclass jcls)
273 SDL_EGL_MakeCurrent(_this,
NULL,
NULL);
283 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
284 JNIEnv* env, jclass jcls, jint keycode)
290 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
291 JNIEnv* env, jclass jcls, jint keycode)
297 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
298 JNIEnv* env, jclass jcls)
306 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeTouch(
307 JNIEnv* env, jclass jcls,
308 jint touch_device_id_in, jint pointer_finger_id_in,
309 jint action, jfloat
x, jfloat
y, jfloat
p)
311 Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
315 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse(
316 JNIEnv* env, jclass jcls,
317 jint
button, jint action, jfloat
x, jfloat
y)
323 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel(
324 JNIEnv* env, jclass jcls,
325 jfloat
x, jfloat
y, jfloat
z)
327 fLastAccelerometer[0] =
x;
328 fLastAccelerometer[1] =
y;
329 fLastAccelerometer[2] =
z;
334 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativeLowMemory(
335 JNIEnv* env, jclass cls)
341 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativeQuit(
342 JNIEnv* env, jclass cls)
357 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativePause(
358 JNIEnv* env, jclass cls)
360 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativePause()");
374 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativeResume(
375 JNIEnv* env, jclass cls)
377 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeResume()");
392 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
393 JNIEnv* env, jclass cls,
394 jstring
text, jint newCursorPosition)
396 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
400 (*env)->ReleaseStringUTFChars(env, text, utftext);
403 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
404 JNIEnv* env, jclass cls,
405 jstring text, jint newCursorPosition)
407 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
411 (*env)->ReleaseStringUTFChars(env, text, utftext);
414 JNIEXPORT jstring JNICALL Java_org_libsdl_app_SDLActivity_nativeGetHint(JNIEnv* env, jclass cls, jstring name) {
415 const char *utfname = (*env)->GetStringUTFChars(env, name,
NULL);
418 jstring
result = (*env)->NewStringUTF(env, hint);
419 (*env)->ReleaseStringUTFChars(env, name, utfname);
428 static int s_active = 0;
429 struct LocalReferenceHolder
435 static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *
func)
437 struct LocalReferenceHolder refholder;
438 refholder.m_env =
NULL;
439 refholder.m_func =
func;
446 static SDL_bool LocalReferenceHolder_Init(
struct LocalReferenceHolder *refholder, JNIEnv *env)
448 const int capacity = 16;
449 if ((*env)->PushLocalFrame(env, capacity) < 0) {
450 SDL_SetError(
"Failed to allocate enough JVM local references");
454 refholder->m_env = env;
458 static void LocalReferenceHolder_Cleanup(
struct LocalReferenceHolder *refholder)
461 SDL_Log(
"Leaving function %s", refholder->m_func);
463 if (refholder->m_env) {
464 JNIEnv* env = refholder->m_env;
465 (*env)->PopLocalFrame(env,
NULL);
470 static SDL_bool LocalReferenceHolder_IsActive(
void)
481 s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
482 anw = ANativeWindow_fromSurface(env, s);
483 (*env)->DeleteLocalRef(env, s);
492 mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"setActivityTitle",
"(Ljava/lang/String;)Z");
494 jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
495 (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, mid, jtitle);
496 (*mEnv)->DeleteLocalRef(mEnv, jtitle);
506 for (i = 0; i < 3; ++
i) {
507 values[
i] = fLastAccelerometer[
i];
516 static void Android_JNI_ThreadDestroyed(
void*
value)
519 JNIEnv *env = (JNIEnv*) value;
521 (*mJavaVM)->DetachCurrentThread(mJavaVM);
522 pthread_setspecific(mThreadKey,
NULL);
541 int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env,
NULL);
543 LOGE(
"failed to attach current thread");
556 pthread_setspecific(mThreadKey, (
void*) env);
570 static jboolean audioBuffer16Bit = JNI_FALSE;
571 static jobject audioBuffer =
NULL;
572 static void* audioBufferPinned =
NULL;
573 static jboolean captureBuffer16Bit = JNI_FALSE;
574 static jobject captureBuffer =
NULL;
578 jboolean audioBufferStereo;
579 int audioBufferFrames;
580 jobject jbufobj =
NULL;
586 LOGE(
"callback_handler: failed to attach current thread");
590 audioBufferStereo = channelCount > 1;
593 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for capture");
594 captureBuffer16Bit = is16Bit;
595 if ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
597 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioRecord initialization!");
601 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for output");
602 audioBuffer16Bit = is16Bit;
603 if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
605 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioTrack initialization!");
614 jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
615 if (audioBufferLocal) {
616 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
617 (*env)->DeleteLocalRef(env, audioBufferLocal);
621 jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
622 if (audioBufferLocal) {
623 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
624 (*env)->DeleteLocalRef(env, audioBufferLocal);
628 if (jbufobj ==
NULL) {
629 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: could not allocate an audio buffer!");
634 captureBuffer = jbufobj;
636 audioBuffer = jbufobj;
643 audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
645 audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
648 audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
650 audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
653 if (audioBufferStereo) {
654 audioBufferFrames /= 2;
657 return audioBufferFrames;
662 return audioBufferPinned;
669 if (audioBuffer16Bit) {
670 (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
671 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
673 (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
674 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
683 jboolean isCopy = JNI_FALSE;
686 if (captureBuffer16Bit) {
687 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
688 br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
690 jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
693 (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
696 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
697 br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
699 jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
701 (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
712 if (captureBuffer16Bit) {
713 const jint
len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
714 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) ==
len) { }
716 const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
717 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) ==
len) { }
720 if (captureBuffer16Bit) {
721 (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
723 (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
733 (*env)->CallStaticVoidMethod(env, mActivityClass, midCaptureClose);
735 (*env)->DeleteGlobalRef(env, captureBuffer);
736 captureBuffer =
NULL;
739 (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioClose);
741 (*env)->DeleteGlobalRef(env, audioBuffer);
743 audioBufferPinned =
NULL;
753 jthrowable exception;
757 exception = (*mEnv)->ExceptionOccurred(mEnv);
758 if (exception !=
NULL) {
762 (*mEnv)->ExceptionClear(mEnv);
765 jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
766 jclass classClass = (*mEnv)->FindClass(mEnv,
"java/lang/Class");
767 jstring exceptionName;
768 const char* exceptionNameUTF8;
769 jstring exceptionMessage;
771 mid = (*mEnv)->GetMethodID(mEnv, classClass,
"getName",
"()Ljava/lang/String;");
772 exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
773 exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
775 mid = (*mEnv)->GetMethodID(mEnv, exceptionClass,
"getMessage",
"()Ljava/lang/String;");
776 exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
778 if (exceptionMessage !=
NULL) {
779 const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
780 SDL_SetError(
"%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
781 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
786 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
795 static int Internal_Android_JNI_FileOpen(
SDL_RWops* ctx)
797 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
803 jobject assetManager;
806 jobject readableByteChannel;
807 jstring fileNameJString;
813 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
817 fileNameJString = (jstring)ctx->
hidden.androidio.fileNameRef;
818 ctx->
hidden.androidio.position = 0;
821 mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
822 "getContext",
"()Landroid/content/Context;");
823 context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
827 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
828 "getAssets",
"()Landroid/content/res/AssetManager;");
829 assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
834 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
"openFd",
"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
835 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
836 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
840 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getStartOffset",
"()J");
841 ctx->
hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
842 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
846 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getDeclaredLength",
"()J");
847 ctx->
hidden.androidio.
size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
848 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
852 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getFileDescriptor",
"()Ljava/io/FileDescriptor;");
853 fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
854 fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
855 descriptor = (*mEnv)->GetFieldID(mEnv, fdCls,
"descriptor",
"I");
856 ctx->
hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
857 ctx->
hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
860 lseek(ctx->
hidden.androidio.fd, (off_t)ctx->
hidden.androidio.offset, SEEK_SET);
868 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
871 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
872 "open",
"(Ljava/lang/String;I)Ljava/io/InputStream;");
873 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 );
874 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
876 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
877 "openAPKExpansionInputStream",
"(Ljava/lang/String;)Ljava/io/InputStream;");
879 SDL_SetError(
"No openAPKExpansionInputStream() in Java class");
882 inputStream = (*mEnv)->CallObjectMethod(mEnv, context, mid, fileNameJString);
887 if (Android_JNI_ExceptionOccurred(
SDL_FALSE) || !inputStream) {
892 ctx->
hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
902 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
904 ctx->
hidden.androidio.
size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
905 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
910 channels = (*mEnv)->FindClass(mEnv,
"java/nio/channels/Channels");
911 mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
913 "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
914 readableByteChannel = (*mEnv)->CallStaticObjectMethod(
915 mEnv, channels, mid, inputStream);
916 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
920 ctx->
hidden.androidio.readableByteChannelRef =
921 (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
924 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
925 "read",
"(Ljava/nio/ByteBuffer;)I");
926 ctx->
hidden.androidio.readMethod = mid;
933 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
935 if(ctx->
hidden.androidio.inputStreamRef !=
NULL) {
936 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
939 if(ctx->
hidden.androidio.readableByteChannelRef !=
NULL) {
940 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
943 if(ctx->
hidden.androidio.assetFileDescriptorRef !=
NULL) {
944 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
949 LocalReferenceHolder_Cleanup(&refs);
954 const char* fileName,
const char*
mode)
956 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
959 jstring fileNameJString;
961 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
962 LocalReferenceHolder_Cleanup(&refs);
967 LocalReferenceHolder_Cleanup(&refs);
971 fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
972 ctx->
hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
974 ctx->
hidden.androidio.readableByteChannelRef =
NULL;
976 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
978 retval = Internal_Android_JNI_FileOpen(ctx);
979 LocalReferenceHolder_Cleanup(&refs);
984 size_t size,
size_t maxnum)
986 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
988 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
989 size_t bytesMax = size * maxnum;
994 result = read(ctx->
hidden.androidio.fd, buffer, bytesMax );
997 LocalReferenceHolder_Cleanup(&refs);
998 return result /
size;
1000 LocalReferenceHolder_Cleanup(&refs);
1003 jlong bytesRemaining = (jlong) (size * maxnum);
1004 jlong bytesMax = (jlong) (ctx->
hidden.androidio.
size - ctx->
hidden.androidio.position);
1007 jobject readableByteChannel;
1008 jmethodID readMethod;
1012 if (bytesRemaining > bytesMax) bytesRemaining = bytesMax;
1015 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1016 LocalReferenceHolder_Cleanup(&refs);
1020 readableByteChannel = (jobject)ctx->
hidden.androidio.readableByteChannelRef;
1021 readMethod = (jmethodID)ctx->
hidden.androidio.readMethod;
1022 byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
1024 while (bytesRemaining > 0) {
1026 int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
1028 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1029 LocalReferenceHolder_Cleanup(&refs);
1037 bytesRemaining -=
result;
1041 LocalReferenceHolder_Cleanup(&refs);
1042 return bytesRead /
size;
1047 size_t size,
size_t num)
1049 SDL_SetError(
"Cannot write to Android package filesystem");
1055 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1060 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1061 LocalReferenceHolder_Cleanup(&refs);
1062 return SDL_SetError(
"Failed to allocate enough JVM local references");
1067 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1070 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1071 jobject inputStream = (jobject)ctx->
hidden.androidio.assetFileDescriptorRef;
1072 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1074 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1075 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1076 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1081 jobject inputStream = (jobject)ctx->
hidden.androidio.inputStreamRef;
1084 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1086 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1087 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1088 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1089 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1099 LocalReferenceHolder_Cleanup(&refs);
1111 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1116 offset += ctx->
hidden.androidio.offset;
1119 offset += ctx->
hidden.androidio.position;
1121 offset += ctx->
hidden.androidio.offset;
1131 ret = lseek(ctx->
hidden.androidio.fd, (off_t)offset, SEEK_SET);
1132 if (ret == -1)
return -1;
1133 ctx->
hidden.androidio.position = ret - ctx->
hidden.androidio.offset;
1153 if (newPosition < 0) {
1156 if (newPosition > ctx->
hidden.androidio.
size) {
1160 movement = newPosition - ctx->
hidden.androidio.position;
1162 unsigned char buffer[4096];
1165 while (movement > 0) {
1168 if (amount > movement) {
1180 }
else if (movement < 0) {
1183 Internal_Android_JNI_FileClose(ctx,
SDL_FALSE);
1184 Internal_Android_JNI_FileOpen(ctx);
1189 return ctx->
hidden.androidio.position;
1195 return Internal_Android_JNI_FileClose(ctx,
SDL_TRUE);
1199 static jobject Android_JNI_GetSystemServiceObject(
const char* name)
1201 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1203 jobject retval =
NULL;
1209 if (!LocalReferenceHolder_Init(&refs, env)) {
1210 LocalReferenceHolder_Cleanup(&refs);
1214 service = (*env)->NewStringUTF(env, name);
1216 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"getContext",
"()Landroid/content/Context;");
1217 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1219 mid = (*env)->GetMethodID(env, mActivityClass,
"getSystemServiceFromUiThread",
"(Ljava/lang/String;)Ljava/lang/Object;");
1220 manager = (*env)->CallObjectMethod(env, context, mid, service);
1222 (*env)->DeleteLocalRef(env, service);
1224 retval = manager ? (*env)->NewGlobalRef(env, manager) :
NULL;
1225 LocalReferenceHolder_Cleanup(&refs);
1229 #define SETUP_CLIPBOARD(error) \ 1230 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \ 1231 JNIEnv* env = Android_JNI_GetEnv(); \ 1232 jobject clipboard; \ 1233 if (!LocalReferenceHolder_Init(&refs, env)) { \ 1234 LocalReferenceHolder_Cleanup(&refs); \ 1237 clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \ 1239 LocalReferenceHolder_Cleanup(&refs); \ 1243 #define CLEANUP_CLIPBOARD() \ 1244 LocalReferenceHolder_Cleanup(&refs); 1253 jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard),
"setText",
"(Ljava/lang/CharSequence;)V");
1254 jstring
string = (*env)->NewStringUTF(env, text);
1255 (*env)->CallVoidMethod(env, clipboard, mid,
string);
1256 (*env)->DeleteGlobalRef(env, clipboard);
1257 (*env)->DeleteLocalRef(env,
string);
1259 CLEANUP_CLIPBOARD();
1271 jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard),
"getText",
"()Ljava/lang/CharSequence;");
1272 jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
1273 (*env)->DeleteGlobalRef(env, clipboard);
1277 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence),
"toString",
"()Ljava/lang/String;");
1278 string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
1279 utf = (*env)->GetStringUTFChars(env,
string, 0);
1282 (*env)->ReleaseStringUTFChars(env,
string, utf);
1284 CLEANUP_CLIPBOARD();
1290 CLEANUP_CLIPBOARD();
1302 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard),
"hasText",
"()Z");
1303 has = (*env)->CallBooleanMethod(env, clipboard, mid);
1304 (*env)->DeleteGlobalRef(env, clipboard);
1306 CLEANUP_CLIPBOARD();
1318 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1330 if (!LocalReferenceHolder_Init(&refs, env)) {
1331 LocalReferenceHolder_Cleanup(&refs);
1336 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"getContext",
"()Landroid/content/Context;");
1337 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1339 action = (*env)->NewStringUTF(env,
"android.intent.action.BATTERY_CHANGED");
1341 cls = (*env)->FindClass(env,
"android/content/IntentFilter");
1343 mid = (*env)->GetMethodID(env, cls,
"<init>",
"(Ljava/lang/String;)V");
1344 filter = (*env)->NewObject(env, cls, mid, action);
1346 (*env)->DeleteLocalRef(env, action);
1348 mid = (*env)->GetMethodID(env, mActivityClass,
"registerReceiver",
"(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
1349 intent = (*env)->CallObjectMethod(env, context, mid,
NULL, filter);
1351 (*env)->DeleteLocalRef(env, filter);
1353 cls = (*env)->GetObjectClass(env, intent);
1355 imid = (*env)->GetMethodID(env, cls,
"getIntExtra",
"(Ljava/lang/String;I)I");
1358 #define GET_INT_EXTRA(var, key) \ 1360 iname = (*env)->NewStringUTF(env, key); \ 1361 var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \ 1362 (*env)->DeleteLocalRef(env, iname); 1364 bmid = (*env)->GetMethodID(env, cls,
"getBooleanExtra",
"(Ljava/lang/String;Z)Z");
1367 #define GET_BOOL_EXTRA(var, key) \ 1369 bname = (*env)->NewStringUTF(env, key); \ 1370 var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \ 1371 (*env)->DeleteLocalRef(env, bname); 1375 GET_INT_EXTRA(plug,
"plugged")
1377 LocalReferenceHolder_Cleanup(&refs);
1382 *plugged = (0 < plug) ? 1 : 0;
1387 GET_INT_EXTRA(status,
"status")
1389 LocalReferenceHolder_Cleanup(&refs);
1393 *charged = (status == 5) ? 1 : 0;
1397 GET_BOOL_EXTRA(present,
"present")
1398 *battery = present ? 1 : 0;
1411 GET_INT_EXTRA(level_temp,
"level")
1416 GET_INT_EXTRA(scale_temp,
"scale")
1420 if ((level == -1) || (scale == -1)) {
1421 LocalReferenceHolder_Cleanup(&refs);
1424 *percent = level * 100 /
scale;
1427 (*env)->DeleteLocalRef(env, intent);
1429 LocalReferenceHolder_Cleanup(&refs);
1437 jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass,
"inputGetInputDeviceIds",
"(I)[I");
1438 jintArray
array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
1442 number = (int) (*env)->GetArrayLength(env, array);
1444 jint* elements = (*env)->GetIntArrayElements(env, array,
NULL);
1448 for (i = 0; i < number; ++
i) {
1449 (*ids)[
i] = elements[
i];
1451 (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
1454 (*env)->DeleteLocalRef(env, array);
1462 (*env)->CallStaticVoidMethod(env, mActivityClass, midPollInputDevices);
1466 #define COMMAND_SET_KEEP_SCREEN_ON 5 1477 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"sendMessage",
"(II)Z");
1481 success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
1482 return success ? 0 : -1;
1498 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"showTextInput",
"(IIII)Z");
1502 (*env)->CallStaticBooleanMethod(env, mActivityClass, mid,
1512 const int COMMAND_TEXTEDIT_HIDE = 3;
1516 int Android_JNI_ShowMessageBox(
const SDL_MessageBoxData *messageboxdata,
int *buttonid)
1524 jintArray button_flags;
1525 jintArray button_ids;
1526 jobjectArray button_texts;
1536 clazz = (*env)->FindClass(env,
"java/lang/String");
1538 title = (*env)->NewStringUTF(env, messageboxdata->
title);
1539 message = (*env)->NewStringUTF(env, messageboxdata->
message);
1541 button_flags = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1542 button_ids = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1543 button_texts = (*env)->NewObjectArray(env, messageboxdata->
numbuttons,
1545 for (i = 0; i < messageboxdata->
numbuttons; ++
i) {
1547 (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
1549 (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
1550 text = (*env)->NewStringUTF(env, messageboxdata->
buttons[i].
text);
1551 (*env)->SetObjectArrayElement(env, button_texts, i, text);
1552 (*env)->DeleteLocalRef(env, text);
1558 temp = (0xFF << 24) |
1562 (*env)->SetIntArrayRegion(env, colors, i, 1, &temp);
1568 (*env)->DeleteLocalRef(env, clazz);
1572 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"getContext",
"()Landroid/content/Context;");
1574 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1576 clazz = (*env)->GetObjectClass(env, context);
1578 mid = (*env)->GetMethodID(env, clazz,
1579 "messageboxShowMessageBox",
"(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
1580 *buttonid = (*env)->CallIntMethod(env, context, mid,
1581 messageboxdata->
flags,
1589 (*env)->DeleteLocalRef(env, context);
1590 (*env)->DeleteLocalRef(env, clazz);
1594 (*env)->DeleteLocalRef(env, title);
1595 (*env)->DeleteLocalRef(env, message);
1596 (*env)->DeleteLocalRef(env, button_flags);
1597 (*env)->DeleteLocalRef(env, button_ids);
1598 (*env)->DeleteLocalRef(env, button_texts);
1599 (*env)->DeleteLocalRef(env, colors);
1607 // Functions exposed to SDL applications in SDL_system.h
1630 mid = (*env)->GetStaticMethodID(env, mActivityClass,
1631 "getContext",
"()Landroid/content/Context;");
1632 return (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1637 static char *s_AndroidInternalFilesPath =
NULL;
1639 if (!s_AndroidInternalFilesPath) {
1640 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1648 if (!LocalReferenceHolder_Init(&refs, env)) {
1649 LocalReferenceHolder_Cleanup(&refs);
1654 mid = (*env)->GetStaticMethodID(env, mActivityClass,
1655 "getContext",
"()Landroid/content/Context;");
1656 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1659 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1660 "getFilesDir",
"()Ljava/io/File;");
1661 fileObject = (*env)->CallObjectMethod(env, context, mid);
1664 LocalReferenceHolder_Cleanup(&refs);
1669 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1670 "getAbsolutePath",
"()Ljava/lang/String;");
1671 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1673 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
1674 s_AndroidInternalFilesPath =
SDL_strdup(path);
1675 (*env)->ReleaseStringUTFChars(env, pathString, path);
1677 LocalReferenceHolder_Cleanup(&refs);
1679 return s_AndroidInternalFilesPath;
1684 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1687 jstring stateString;
1692 if (!LocalReferenceHolder_Init(&refs, env)) {
1693 LocalReferenceHolder_Cleanup(&refs);
1697 cls = (*env)->FindClass(env,
"android/os/Environment");
1698 mid = (*env)->GetStaticMethodID(env, cls,
1699 "getExternalStorageState",
"()Ljava/lang/String;");
1700 stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
1702 state = (*env)->GetStringUTFChars(env, stateString,
NULL);
1705 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"external storage state: %s", state);
1708 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
1709 SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
1710 }
else if (
SDL_strcmp(state,
"mounted_ro") == 0) {
1711 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
1715 (*env)->ReleaseStringUTFChars(env, stateString, state);
1717 LocalReferenceHolder_Cleanup(&refs);
1723 static char *s_AndroidExternalFilesPath =
NULL;
1725 if (!s_AndroidExternalFilesPath) {
1726 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1734 if (!LocalReferenceHolder_Init(&refs, env)) {
1735 LocalReferenceHolder_Cleanup(&refs);
1740 mid = (*env)->GetStaticMethodID(env, mActivityClass,
1741 "getContext",
"()Landroid/content/Context;");
1742 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1745 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1746 "getExternalFilesDir",
"(Ljava/lang/String;)Ljava/io/File;");
1747 fileObject = (*env)->CallObjectMethod(env, context, mid,
NULL);
1750 LocalReferenceHolder_Cleanup(&refs);
1755 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1756 "getAbsolutePath",
"()Ljava/lang/String;");
1757 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1759 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
1760 s_AndroidExternalFilesPath =
SDL_strdup(path);
1761 (*env)->ReleaseStringUTFChars(env, pathString, path);
1763 LocalReferenceHolder_Cleanup(&refs);
1765 return s_AndroidExternalFilesPath;
1770 return mActivityClass;
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
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
int Android_JNI_FileClose(SDL_RWops *ctx)
int Android_OnKeyUp(int keycode)
int Android_JNI_SendMessage(int command, int param)
void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
GLint GLint GLsizei width
void Android_JNI_WriteAudioBuffer(void)
GLsizei const GLchar *const * string
GLuint GLsizei const GLchar * message
GLint GLint GLint GLint GLint x
SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
int SDL_SendDropFile(SDL_Window *window, const char *file)
#define SDL_AndroidGetExternalStoragePath
void Android_JNI_SetActivityTitle(const char *title)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
char * Android_JNI_GetClipboardText(void)
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)
GLuint const GLchar * name
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
GLint GLint GLsizei GLsizei height
int Android_JNI_FileOpen(SDL_RWops *ctx, const char *fileName, const char *mode)
int SDL_SendDropComplete(SDL_Window *window)
SDL_sem * Android_PauseSem
int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
static SDL_VideoDevice * _this
int Android_JNI_SetupThread(void)
void Android_JNI_FlushCapturedAudio(void)
#define SDL_StopTextInput
GLenum GLsizei const void * pathString
GLint GLint GLint GLint GLint GLint y
GLsizei const GLfloat * value
int SDL_SendKeyboardText(const char *text)
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
void * Android_JNI_GetAudioBuffer(void)
GLenum GLsizei GLsizei GLint * values
void Android_JNI_SuspendScreenSaver(SDL_bool suspend)
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)
jclass Android_JNI_GetActivityClass(void)
union SDL_RWops::@10 hidden
static char text[MAX_TEXT_LENGTH]
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)
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_AndroidGetJNIEnv
ANativeWindow * native_window
int Android_JNI_GetTouchDeviceIds(int **ids)
const SDL_MessageBoxColorScheme * colorScheme
SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX]
#define SDL_AndroidGetInternalStoragePath
JNIEnv * Android_JNI_GetEnv(void)
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)