mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-06-02 18:07:40 +00:00
Android: Implement open and save file dialog.
This commit is contained in:
parent
ea1904eda1
commit
86fada6faa
7 changed files with 312 additions and 3 deletions
|
@ -30,6 +30,8 @@ LOCAL_SRC_FILES := \
|
||||||
$(wildcard $(LOCAL_PATH)/src/core/*.c) \
|
$(wildcard $(LOCAL_PATH)/src/core/*.c) \
|
||||||
$(wildcard $(LOCAL_PATH)/src/core/android/*.c) \
|
$(wildcard $(LOCAL_PATH)/src/core/android/*.c) \
|
||||||
$(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \
|
$(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \
|
||||||
|
$(LOCAL_PATH)/src/dialog/SDL_dialog_utils.c \
|
||||||
|
$(LOCAL_PATH)/src/dialog/android/SDL_androiddialog.c \
|
||||||
$(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \
|
$(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \
|
||||||
$(wildcard $(LOCAL_PATH)/src/events/*.c) \
|
$(wildcard $(LOCAL_PATH)/src/events/*.c) \
|
||||||
$(wildcard $(LOCAL_PATH)/src/file/*.c) \
|
$(wildcard $(LOCAL_PATH)/src/file/*.c) \
|
||||||
|
|
|
@ -2874,7 +2874,10 @@ endif()
|
||||||
|
|
||||||
if (SDL_DIALOG)
|
if (SDL_DIALOG)
|
||||||
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/SDL_dialog_utils.c)
|
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/SDL_dialog_utils.c)
|
||||||
if(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
if(ANDROID)
|
||||||
|
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/android/SDL_androiddialog.c)
|
||||||
|
set(HAVE_SDL_DIALOG TRUE)
|
||||||
|
elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
||||||
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_unixdialog.c)
|
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_unixdialog.c)
|
||||||
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_portaldialog.c)
|
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_portaldialog.c)
|
||||||
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_zenitydialog.c)
|
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_zenitydialog.c)
|
||||||
|
|
2
android-project/app/proguard-rules.pro
vendored
2
android-project/app/proguard-rules.pro
vendored
|
@ -49,6 +49,8 @@
|
||||||
int showToast(java.lang.String, int, int, int, int);
|
int showToast(java.lang.String, int, int, int, int);
|
||||||
native java.lang.String nativeGetHint(java.lang.String);
|
native java.lang.String nativeGetHint(java.lang.String);
|
||||||
int openFileDescriptor(java.lang.String, java.lang.String);
|
int openFileDescriptor(java.lang.String, java.lang.String);
|
||||||
|
boolean showFileDialog(java.lang.String[], boolean, boolean, int);
|
||||||
|
native void onNativeFileDialog(int, java.lang.String[], int);
|
||||||
}
|
}
|
||||||
|
|
||||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager {
|
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.UiModeManager;
|
import android.app.UiModeManager;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -39,6 +40,7 @@ import android.view.Window;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
@ -46,6 +48,7 @@ import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@ -227,6 +230,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
protected static Thread mSDLThread;
|
protected static Thread mSDLThread;
|
||||||
protected static boolean mSDLMainFinished = false;
|
protected static boolean mSDLMainFinished = false;
|
||||||
protected static boolean mActivityCreated = false;
|
protected static boolean mActivityCreated = false;
|
||||||
|
private static SDLFileDialogState mFileDialogState = null;
|
||||||
|
|
||||||
protected static SDLGenericMotionListener_API12 getMotionListener() {
|
protected static SDLGenericMotionListener_API12 getMotionListener() {
|
||||||
if (mMotionListener == null) {
|
if (mMotionListener == null) {
|
||||||
|
@ -719,6 +723,43 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
|
if (mFileDialogState != null && mFileDialogState.requestCode == requestCode) {
|
||||||
|
/* This is our file dialog */
|
||||||
|
String[] filelist = null;
|
||||||
|
|
||||||
|
if (data != null) {
|
||||||
|
Uri singleFileUri = data.getData();
|
||||||
|
|
||||||
|
if (singleFileUri == null) {
|
||||||
|
/* Use Intent.getClipData to get multiple choices */
|
||||||
|
ClipData clipData = data.getClipData();
|
||||||
|
assert clipData != null;
|
||||||
|
|
||||||
|
filelist = new String[clipData.getItemCount()];
|
||||||
|
|
||||||
|
for (int i = 0; i < filelist.length; i++) {
|
||||||
|
String uri = clipData.getItemAt(i).getUri().toString();
|
||||||
|
filelist[i] = uri;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Only one file is selected. */
|
||||||
|
filelist = new String[]{singleFileUri.toString()};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* User cancelled the request. */
|
||||||
|
filelist = new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Detect the file MIME type and pass the filter value accordingly.
|
||||||
|
SDLActivity.onNativeFileDialog(requestCode, filelist, -1);
|
||||||
|
mFileDialogState = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Called by JNI from SDL.
|
// Called by JNI from SDL.
|
||||||
public static void manualBackButton() {
|
public static void manualBackButton() {
|
||||||
mSingleton.pressBackButton();
|
mSingleton.pressBackButton();
|
||||||
|
@ -1021,6 +1062,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
public static native void onNativeDarkModeChanged(boolean enabled);
|
public static native void onNativeDarkModeChanged(boolean enabled);
|
||||||
public static native boolean nativeAllowRecreateActivity();
|
public static native boolean nativeAllowRecreateActivity();
|
||||||
public static native int nativeCheckSDLThreadCounter();
|
public static native int nativeCheckSDLThreadCounter();
|
||||||
|
public static native void onNativeFileDialog(int requestCode, String[] filelist, int filter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called by SDL using JNI.
|
* This method is called by SDL using JNI.
|
||||||
|
@ -1957,6 +1999,75 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called by SDL using JNI.
|
||||||
|
*/
|
||||||
|
public static boolean showFileDialog(String[] filters, boolean allowMultiple, boolean forWrite, int requestCode) {
|
||||||
|
if (mSingleton == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forWrite) {
|
||||||
|
allowMultiple = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert string list of extensions to their respective MIME types */
|
||||||
|
ArrayList<String> mimes = new ArrayList<>();
|
||||||
|
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
||||||
|
if (filters != null) {
|
||||||
|
for (String pattern : filters) {
|
||||||
|
String[] extensions = pattern.split(";");
|
||||||
|
|
||||||
|
if (extensions.length == 1 && extensions[0].equals("*")) {
|
||||||
|
/* Handle "*" special case */
|
||||||
|
mimes.add("*/*");
|
||||||
|
} else {
|
||||||
|
for (String ext : extensions) {
|
||||||
|
String mime = mimeTypeMap.getMimeTypeFromExtension(ext);
|
||||||
|
if (mime != null) {
|
||||||
|
mimes.add(mime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display the file dialog */
|
||||||
|
Intent intent = new Intent(forWrite ? Intent.ACTION_CREATE_DOCUMENT : Intent.ACTION_OPEN_DOCUMENT);
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, allowMultiple);
|
||||||
|
switch (mimes.size()) {
|
||||||
|
case 0:
|
||||||
|
intent.setType("*/*");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
intent.setType(mimes.get(0));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
intent.setType("*/*");
|
||||||
|
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimes.toArray(new String[]{}));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mSingleton.startActivityForResult(intent, requestCode);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Log.e(TAG, "Unable to open file dialog.", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save current dialog state */
|
||||||
|
mFileDialogState = new SDLFileDialogState();
|
||||||
|
mFileDialogState.requestCode = requestCode;
|
||||||
|
mFileDialogState.multipleChoice = allowMultiple;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Internal class used to track active open file dialog */
|
||||||
|
static class SDLFileDialogState {
|
||||||
|
int requestCode;
|
||||||
|
boolean multipleChoice;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -177,6 +177,10 @@ JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(nativeAllowRecreateActivity)(
|
||||||
JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
|
JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
|
||||||
JNIEnv *env, jclass jcls);
|
JNIEnv *env, jclass jcls);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeFileDialog)(
|
||||||
|
JNIEnv *env, jclass jcls,
|
||||||
|
jint requestCode, jobjectArray fileList, jint filter);
|
||||||
|
|
||||||
static JNINativeMethod SDLActivity_tab[] = {
|
static JNINativeMethod SDLActivity_tab[] = {
|
||||||
{ "nativeGetVersion", "()Ljava/lang/String;", SDL_JAVA_INTERFACE(nativeGetVersion) },
|
{ "nativeGetVersion", "()Ljava/lang/String;", SDL_JAVA_INTERFACE(nativeGetVersion) },
|
||||||
{ "nativeSetupJNI", "()I", SDL_JAVA_INTERFACE(nativeSetupJNI) },
|
{ "nativeSetupJNI", "()I", SDL_JAVA_INTERFACE(nativeSetupJNI) },
|
||||||
|
@ -211,7 +215,8 @@ static JNINativeMethod SDLActivity_tab[] = {
|
||||||
{ "nativeAddTouch", "(ILjava/lang/String;)V", SDL_JAVA_INTERFACE(nativeAddTouch) },
|
{ "nativeAddTouch", "(ILjava/lang/String;)V", SDL_JAVA_INTERFACE(nativeAddTouch) },
|
||||||
{ "nativePermissionResult", "(IZ)V", SDL_JAVA_INTERFACE(nativePermissionResult) },
|
{ "nativePermissionResult", "(IZ)V", SDL_JAVA_INTERFACE(nativePermissionResult) },
|
||||||
{ "nativeAllowRecreateActivity", "()Z", SDL_JAVA_INTERFACE(nativeAllowRecreateActivity) },
|
{ "nativeAllowRecreateActivity", "()Z", SDL_JAVA_INTERFACE(nativeAllowRecreateActivity) },
|
||||||
{ "nativeCheckSDLThreadCounter", "()I", SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter) }
|
{ "nativeCheckSDLThreadCounter", "()I", SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter) },
|
||||||
|
{ "onNativeFileDialog", "(I[Ljava/lang/String;I)V", SDL_JAVA_INTERFACE(onNativeFileDialog) }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Java class SDLInputConnection */
|
/* Java class SDLInputConnection */
|
||||||
|
@ -346,6 +351,7 @@ static jmethodID midShouldMinimizeOnFocusLoss;
|
||||||
static jmethodID midShowTextInput;
|
static jmethodID midShowTextInput;
|
||||||
static jmethodID midSupportsRelativeMouse;
|
static jmethodID midSupportsRelativeMouse;
|
||||||
static jmethodID midOpenFileDescriptor;
|
static jmethodID midOpenFileDescriptor;
|
||||||
|
static jmethodID midShowFileDialog;
|
||||||
|
|
||||||
/* audio manager */
|
/* audio manager */
|
||||||
static jclass mAudioManagerClass;
|
static jclass mAudioManagerClass;
|
||||||
|
@ -640,6 +646,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
|
||||||
midShowTextInput = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
|
midShowTextInput = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
|
||||||
midSupportsRelativeMouse = (*env)->GetStaticMethodID(env, mActivityClass, "supportsRelativeMouse", "()Z");
|
midSupportsRelativeMouse = (*env)->GetStaticMethodID(env, mActivityClass, "supportsRelativeMouse", "()Z");
|
||||||
midOpenFileDescriptor = (*env)->GetStaticMethodID(env, mActivityClass, "openFileDescriptor", "(Ljava/lang/String;Ljava/lang/String;)I");
|
midOpenFileDescriptor = (*env)->GetStaticMethodID(env, mActivityClass, "openFileDescriptor", "(Ljava/lang/String;Ljava/lang/String;)I");
|
||||||
|
midShowFileDialog = (*env)->GetStaticMethodID(env, mActivityClass, "showFileDialog", "([Ljava/lang/String;ZZI)Z");
|
||||||
|
|
||||||
if (!midClipboardGetText ||
|
if (!midClipboardGetText ||
|
||||||
!midClipboardHasText ||
|
!midClipboardHasText ||
|
||||||
|
@ -670,7 +677,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
|
||||||
!midShouldMinimizeOnFocusLoss ||
|
!midShouldMinimizeOnFocusLoss ||
|
||||||
!midShowTextInput ||
|
!midShowTextInput ||
|
||||||
!midSupportsRelativeMouse ||
|
!midSupportsRelativeMouse ||
|
||||||
!midOpenFileDescriptor) {
|
!midOpenFileDescriptor ||
|
||||||
|
!midShowFileDialog) {
|
||||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
|
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2823,4 +2831,138 @@ int Android_JNI_OpenFileDescriptor(const char *uri, const char *mode)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct AndroidFileDialog
|
||||||
|
{
|
||||||
|
int request_code;
|
||||||
|
SDL_DialogFileCallback callback;
|
||||||
|
void *userdata;
|
||||||
|
} mAndroidFileDialogData;
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeFileDialog)(
|
||||||
|
JNIEnv *env, jclass jcls,
|
||||||
|
jint requestCode, jobjectArray fileList, jint filter)
|
||||||
|
{
|
||||||
|
if (mAndroidFileDialogData.callback != NULL && mAndroidFileDialogData.request_code == requestCode) {
|
||||||
|
if (fileList == NULL) {
|
||||||
|
SDL_SetError("Unspecified error in JNI");
|
||||||
|
mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, NULL, -1);
|
||||||
|
mAndroidFileDialogData.callback = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert fileList to string */
|
||||||
|
size_t count = (*env)->GetArrayLength(env, fileList);
|
||||||
|
char **charFileList = SDL_calloc(sizeof(char*), count + 1);
|
||||||
|
|
||||||
|
if (charFileList == NULL) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, NULL, -1);
|
||||||
|
mAndroidFileDialogData.callback = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to UTF-8 */
|
||||||
|
/* TODO: Fix modified UTF-8 to classic UTF-8 */
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
jstring string = (*env)->GetObjectArrayElement(env, fileList, i);
|
||||||
|
if (!string) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *utf8string = (*env)->GetStringUTFChars(env, string, NULL);
|
||||||
|
if (!utf8string) {
|
||||||
|
(*env)->DeleteLocalRef(env, string);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *newFile = SDL_strdup(utf8string);
|
||||||
|
if (!newFile) {
|
||||||
|
(*env)->ReleaseStringUTFChars(env, string, utf8string);
|
||||||
|
(*env)->DeleteLocalRef(env, string);
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, NULL, -1);
|
||||||
|
mAndroidFileDialogData.callback = NULL;
|
||||||
|
|
||||||
|
/* Cleanup memory */
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
SDL_free(charFileList[j]);
|
||||||
|
}
|
||||||
|
SDL_free(charFileList);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
charFileList[i] = newFile;
|
||||||
|
(*env)->ReleaseStringUTFChars(env, string, utf8string);
|
||||||
|
(*env)->DeleteLocalRef(env, string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call user-provided callback */
|
||||||
|
SDL_ClearError();
|
||||||
|
mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, (const char *const *) charFileList, filter);
|
||||||
|
mAndroidFileDialogData.callback = NULL;
|
||||||
|
|
||||||
|
/* Cleanup memory */
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
SDL_free(charFileList[i]);
|
||||||
|
}
|
||||||
|
SDL_free(charFileList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_bool Android_JNI_OpenFileDialog(
|
||||||
|
SDL_DialogFileCallback callback, void* userdata,
|
||||||
|
const SDL_DialogFileFilter *filters, SDL_bool forwrite, SDL_bool multiple)
|
||||||
|
{
|
||||||
|
if (mAndroidFileDialogData.callback != NULL) {
|
||||||
|
SDL_SetError("Only one file dialog can be run at a time.");
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forwrite) {
|
||||||
|
multiple = SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEnv *env = Android_JNI_GetEnv();
|
||||||
|
|
||||||
|
/* Setup filters */
|
||||||
|
jobjectArray filtersArray = NULL;
|
||||||
|
if (filters) {
|
||||||
|
/* Count how many filters */
|
||||||
|
int count = 0;
|
||||||
|
for (const SDL_DialogFileFilter *f = filters; f->name != NULL && f->pattern != NULL; f++) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass stringClass = (*env)->FindClass(env, "java/lang/String");
|
||||||
|
filtersArray = (*env)->NewObjectArray(env, count, stringClass, NULL);
|
||||||
|
|
||||||
|
/* Convert to string */
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
jstring str = (*env)->NewStringUTF(env, filters[i].pattern);
|
||||||
|
(*env)->SetObjectArrayElement(env, filtersArray, i, str);
|
||||||
|
(*env)->DeleteLocalRef(env, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup data */
|
||||||
|
static SDL_AtomicInt next_request_code;
|
||||||
|
mAndroidFileDialogData.request_code = SDL_AtomicAdd(&next_request_code, 1);
|
||||||
|
mAndroidFileDialogData.userdata = userdata;
|
||||||
|
mAndroidFileDialogData.callback = callback;
|
||||||
|
|
||||||
|
/* Invoke JNI */
|
||||||
|
jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass,
|
||||||
|
midShowFileDialog, filtersArray, (jboolean) multiple, (jboolean) forwrite, mAndroidFileDialogData.request_code);
|
||||||
|
(*env)->DeleteLocalRef(env, filtersArray);
|
||||||
|
if (!success) {
|
||||||
|
mAndroidFileDialogData.callback = NULL;
|
||||||
|
SDL_AtomicAdd(&next_request_code, -1);
|
||||||
|
SDL_SetError("Unspecified error in JNI");
|
||||||
|
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* SDL_PLATFORM_ANDROID */
|
#endif /* SDL_PLATFORM_ANDROID */
|
||||||
|
|
|
@ -142,6 +142,10 @@ void Android_ActivityMutex_Lock(void);
|
||||||
void Android_ActivityMutex_Unlock(void);
|
void Android_ActivityMutex_Unlock(void);
|
||||||
void Android_ActivityMutex_Lock_Running(void);
|
void Android_ActivityMutex_Lock_Running(void);
|
||||||
|
|
||||||
|
/* File Dialogs */
|
||||||
|
SDL_bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void* userdata,
|
||||||
|
const SDL_DialogFileFilter *filters, SDL_bool forwrite, SDL_bool multiple);
|
||||||
|
|
||||||
/* Ends C function definitions when using C++ */
|
/* Ends C function definitions when using C++ */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
|
|
45
src/dialog/android/SDL_androiddialog.c
Normal file
45
src/dialog/android/SDL_androiddialog.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
#include "../../core/android/SDL_android.h"
|
||||||
|
|
||||||
|
void SDLCALL SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, const char *default_location, SDL_bool allow_many)
|
||||||
|
{
|
||||||
|
if (!Android_JNI_OpenFileDialog(callback, userdata, filters, SDL_FALSE, allow_many)) {
|
||||||
|
/* SDL_SetError is already called when it fails */
|
||||||
|
callback(userdata, NULL, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLCALL SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, const char *default_location)
|
||||||
|
{
|
||||||
|
if (!Android_JNI_OpenFileDialog(callback, userdata, filters, SDL_TRUE, SDL_FALSE)) {
|
||||||
|
/* SDL_SetError is already called when it fails */
|
||||||
|
callback(userdata, NULL, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLCALL SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char *default_location, SDL_bool allow_many)
|
||||||
|
{
|
||||||
|
SDL_Unsupported();
|
||||||
|
callback(userdata, NULL, -1);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue