implement file chooser using GtkFileChooserNative

This commit is contained in:
Julian Winkler
2024-03-16 18:14:46 +01:00
parent 276b5ca7ef
commit 6513195b9e
7 changed files with 136 additions and 13 deletions

View File

@@ -8,6 +8,7 @@ import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.XmlResourceParser;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -26,6 +27,7 @@ import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Activity extends ContextWrapper implements Window.Callback {
@@ -254,8 +256,20 @@ public class Activity extends ContextWrapper implements Window.Callback {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {}
// the order must match GtkFileChooserAction enum
private static final List<String> FILE_CHOOSER_ACTIONS = Arrays.asList(
"android.intent.action.OPEN_DOCUMENT", // (0) GTK_FILE_CHOOSER_ACTION_OPEN
"android.intent.action.CREATE_DOCUMENT", // (1) GTK_FILE_CHOOSER_ACTION_SAVE
"android.intent.action.OPEN_DOCUMENT_TREE" // (2) GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
);
// callback from native code
protected void fileChooserResultCallback(int requestCode, int resultCode, int action, String uri) {
onActivityResult(requestCode, resultCode, new Intent(FILE_CHOOSER_ACTIONS.get(action), uri != null ? Uri.parse(uri) : null));
}
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
System.out.println("startActivityForResult(" + intent + ", " + requestCode + ") called, but we don't currently support multiple activities");
System.out.println("startActivityForResult(" + intent + ", " + requestCode + ") called");
if (intent.getComponent() != null) {
try {
Class<? extends Activity> cls = Class.forName(intent.getComponent().getClassName()).asSubclass(Activity.class);
@@ -272,12 +286,14 @@ public class Activity extends ContextWrapper implements Window.Callback {
}
});
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
onActivityResult(requestCode, 0 /*RESULT_CANCELED*/, new Intent()); // RESULT_CANCELED is the only pre-defined return value, so hopefully it works out for us
onActivityResult(requestCode, 0 /*RESULT_CANCELED*/, new Intent());
}
} else if (FILE_CHOOSER_ACTIONS.contains(intent.getAction())) {
nativeFileChooser(FILE_CHOOSER_ACTIONS.indexOf(intent.getAction()), intent.getType(), intent.getStringExtra("android.intent.extra.TITLE"), requestCode);
}
else {
System.out.println("startActivityForResult: intent was not handled. Calling onActivityResult(RESULT_CANCELED).");
onActivityResult(requestCode, 0 /*RESULT_CANCELED*/, new Intent()); // RESULT_CANCELED is the only pre-defined return value, so hopefully it works out for us
onActivityResult(requestCode, 0 /*RESULT_CANCELED*/, new Intent());
}
}
public void startActivityForResult(Intent intent, int requestCode) {
@@ -426,4 +442,5 @@ public class Activity extends ContextWrapper implements Window.Callback {
public static native void nativeRecreateActivity(Activity activity);
public static native void nativeStartActivity(Activity activity);
public static native void nativeOpenURI(String uri);
public native void nativeFileChooser(int action, String type, String title, int requestCode);
}

View File

@@ -1,7 +1,11 @@
package android.content;
import java.io.File;
import java.io.FileNotFoundException;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
public class ContentResolver {
public final void registerContentObserver(Uri uri, boolean notifyForDescendants, ContentObserver observer) {
@@ -15,4 +19,8 @@ public class ContentResolver {
}
public final void registerContentObserver(Uri uri, boolean notifyForDescendants, ContentObserver observer, int userHandle) {
}
public ParcelFileDescriptor openFileDescriptor(Uri uri, String mode) throws FileNotFoundException {
return ParcelFileDescriptor.open(new File(uri.uri), ParcelFileDescriptor.parseMode(mode));
}
}

View File

@@ -290,4 +290,8 @@ public class Intent {
public Parcelable[] getParcelableArrayExtra(String name) {
return extras.getParcelableArray(name);
}
public String getType() {
return type;
}
}

View File

@@ -13,7 +13,7 @@ public class Uri implements Parcelable {
public static final Uri EMPTY = new Uri();
private URI uri;
public URI uri;
public static Uri parse(String s) {
Uri ret = new Uri();
@@ -160,6 +160,10 @@ public class Uri implements Parcelable {
return uri.getPath();
}
public String getAuthority() {
return uri.getAuthority();
}
@Override
public String toString() {
return String.valueOf(uri);

View File

@@ -17,10 +17,21 @@
package android.os;
import static android.system.OsConstants.AF_UNIX;
import static android.system.OsConstants.O_APPEND;
import static android.system.OsConstants.O_CLOEXEC;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_RDWR;
import static android.system.OsConstants.O_TRUNC;
import static android.system.OsConstants.O_WRONLY;
import static android.system.OsConstants.SEEK_SET;
import static android.system.OsConstants.SOCK_STREAM;
import static android.system.OsConstants.S_IROTH;
import static android.system.OsConstants.S_IRWXG;
import static android.system.OsConstants.S_IRWXU;
import static android.system.OsConstants.S_ISLNK;
import static android.system.OsConstants.S_ISREG;
import static android.system.OsConstants.S_IWOTH;
import android.system.ErrnoException;
import android.system.OsConstants;
@@ -246,15 +257,30 @@ public class ParcelFileDescriptor implements Closeable {
return pfd;
}
private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException { /*
if ((mode & MODE_READ_WRITE) == 0) {
throw new IllegalArgumentException(
"Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
}
final String path = file.getPath();
return Parcel.openFileDescriptor(path, mode);*/
return null;
private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException {
int flags = O_CLOEXEC;
if ((mode & MODE_READ_WRITE) == MODE_READ_WRITE)
flags |= O_RDWR;
else if ((mode & MODE_WRITE_ONLY) == MODE_WRITE_ONLY)
flags |= O_WRONLY;
else if ((mode & MODE_READ_ONLY) == MODE_READ_ONLY)
flags |= O_RDONLY;
else
throw new IllegalArgumentException("Bad mode: " + mode);
if ((mode & MODE_CREATE) == MODE_CREATE)
flags |= O_CREAT;
if ((mode & MODE_TRUNCATE) == MODE_TRUNCATE)
flags |= O_TRUNC;
if ((mode & MODE_APPEND) == MODE_APPEND)
flags |= O_APPEND;
int realMode = S_IRWXU | S_IRWXG;
if ((mode & MODE_WORLD_READABLE) != 0) realMode |= S_IROTH;
if ((mode & MODE_WORLD_WRITEABLE) != 0) realMode |= S_IWOTH;
try {
return android.system.Os.open(file.getPath(), flags, realMode);
} catch (ErrnoException e) {
throw new FileNotFoundException(e.getMessage());
}
}
/**