Skip to content

Commit

Permalink
Support multiple file selection for creating stylable layers
Browse files Browse the repository at this point in the history
Fixes #2184
  • Loading branch information
simonpoole committed Dec 8, 2023
1 parent 310a21a commit 104a78e
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 30 deletions.
20 changes: 15 additions & 5 deletions src/main/java/de/blau/android/dialogs/Layers.java
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ protected Uri doInBackground(Void input) throws Exception {
@Override
protected void onPostExecute(Uri result) {
if (result != null) {
addStyleableLayerFromUri(activity, prefs, map, LayerType.GPX, result);
addStyleableLayerFromUri(activity, prefs, map, LayerType.GPX, result, true);
}
}
}.execute();
Expand Down Expand Up @@ -411,10 +411,17 @@ private void addStyleableLayerFromFile(final FragmentActivity activity, final Pr

@Override
public boolean read(Uri fileUri) {
addStyleableLayerFromUri(activity, prefs, map, type, fileUri);
addStyleableLayerFromUri(activity, prefs, map, type, fileUri, true);
return true;
}
});

@Override
public void read(List<Uri> fileUris) {
for (Uri fileUri : fileUris) {
addStyleableLayerFromUri(activity, prefs, map, type, fileUri, false);
}
}
}, true);
}

/**
Expand All @@ -425,9 +432,10 @@ public boolean read(Uri fileUri) {
* @param map current Map
* @param type the layer type
* @param fileUri the file uri
* @param showDialog show the style dialog if true
*/
private void addStyleableLayerFromUri(@NonNull final FragmentActivity activity, @NonNull final Preferences prefs, @NonNull final Map map,
@NonNull LayerType type, @NonNull Uri fileUri) {
@NonNull LayerType type, @NonNull Uri fileUri, boolean showDialog) {
final String uriString = fileUri.toString();
de.blau.android.layer.StyleableLayer layer = (de.blau.android.layer.StyleableLayer) map.getLayer(type, uriString);
if (layer == null) {
Expand All @@ -436,7 +444,9 @@ private void addStyleableLayerFromUri(@NonNull final FragmentActivity activity,
map.setUpLayers(activity);
layer = (de.blau.android.layer.StyleableLayer) map.getLayer(type, uriString);
if (layer != null) { // if null setUpLayers will have toasted
LayerStyle.showDialog(activity, layer.getIndex());
if (showDialog) {
LayerStyle.showDialog(activity, layer.getIndex());
}
SelectFile.savePref(prefs, R.string.config_osmPreferredDir_key, fileUri);
layer.invalidate();
tl.removeAllViews();
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/de/blau/android/util/ReadFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.List;

import android.net.Uri;
import androidx.annotation.NonNull;

public abstract class ReadFile implements Serializable {
/**
Expand All @@ -17,14 +18,14 @@ public abstract class ReadFile implements Serializable {
* @param fileUri Uri of the file to read
* @return true if sucessful
*/
public abstract boolean read(Uri fileUri);
public abstract boolean read(@NonNull Uri fileUri);

/**
* Read multiple files, empty default implementation
*
* @param uris List of Uri to read
*/
public void read(List<Uri> uris) {
public void read(@NonNull List<Uri> uris) {
// empty
}
}
99 changes: 76 additions & 23 deletions src/main/java/de/blau/android/util/SelectFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.nononsenseapps.filepicker.AbstractFilePickerActivity;

import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
Expand Down Expand Up @@ -79,7 +81,7 @@ public static void save(@NonNull FragmentActivity activity, int directoryPrefKey
}
String path = App.getPreferences(activity).getString(directoryPrefKey);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
startFileSelector(activity, Intent.ACTION_CREATE_DOCUMENT, SAVE_FILE, path);
startFileSelector(activity, Intent.ACTION_CREATE_DOCUMENT, SAVE_FILE, path, false);
} else {
startFilePickerActivity(activity, SAVE_FILE, path);
}
Expand All @@ -92,13 +94,24 @@ public static void save(@NonNull FragmentActivity activity, int directoryPrefKey
* {@link #savePref(Preferences, int, Uri)}
*/
public static void read(@NonNull FragmentActivity activity, int directoryPrefKey, @NonNull ReadFile readFile) {
read(activity, directoryPrefKey, readFile, false);
}

/**
* @param activity activity activity that called us
* @param directoryPrefKey string resources for shared preferences for preferred (last) directory
* @param readFile callback callback that does the actual saving, should call
* {@link #savePref(Preferences, int, Uri)}
* @param allowMultiple if true support selecting multiple files
*/
public static void read(@NonNull FragmentActivity activity, int directoryPrefKey, @NonNull ReadFile readFile, boolean allowMultiple) {
synchronized (readCallbackLock) {
readCallback = readFile;
SelectFile.activity = activity;
}
String path = App.getPreferences(activity).getString(directoryPrefKey);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
startFileSelector(activity, Intent.ACTION_OPEN_DOCUMENT, READ_FILE, path);
startFileSelector(activity, Intent.ACTION_OPEN_DOCUMENT, READ_FILE, path, allowMultiple);
} else {
startFilePickerActivity(activity, READ_FILE, path);
}
Expand Down Expand Up @@ -144,12 +157,16 @@ private static void startFilePickerActivity(@NonNull Activity activity, int requ
* @param intentRequestCode the request code
* @param path a directory path to try to start with
*/
private static void startFileSelector(@NonNull FragmentActivity activity, @NonNull String intentAction, int intentRequestCode, @Nullable String path) {
private static void startFileSelector(@NonNull FragmentActivity activity, @NonNull String intentAction, int intentRequestCode, @Nullable String path,
boolean allowMultiple) {
Intent i = new Intent(intentAction);
i.setType("*/*");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && path != null) {
i.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Uri.parse(path));
}
if (intentRequestCode == READ_FILE && allowMultiple) {
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
final PackageManager pm = activity.getPackageManager();

@SuppressWarnings("deprecation")
Expand Down Expand Up @@ -236,34 +253,70 @@ public static void handleResult(int code, @NonNull Intent data) {
ContentResolverUtil.persistPermissions(activity, data.getFlags(), uri);
try {
if (code == SAVE_FILE) {
File file = new File(uri.getPath());
if (file.exists()) {
ScreenMessage.barWarning(activity, activity.getResources().getString(R.string.toast_file_exists, file.getName()), R.string.overwrite, v -> {
synchronized (saveCallbackLock) {
if (saveCallback != null) {
saveCallback.save(uri);
}
}
});
return;
}
callSaveCallback(uri);
} else if (code == READ_FILE) {
callReadCallback(data, uri);
}
} catch (NetworkOnMainThreadException nex) {
Log.e(DEBUG_TAG, "Got exception for " + " uri " + nex.getMessage());
ScreenMessage.toastTopError(activity, activity.getString(R.string.toast_network_file_not_supported, nex.getMessage()));
}
}

/**
* Call the callback for saving to a file
*
* @param uri the file Uri
*/
private static void callSaveCallback(@Nullable Uri uri) {
if (uri == null) {
Log.e(DEBUG_TAG, "callSaveCallback called with null uri");
return;
}
File file = new File(uri.getPath());
if (file.exists()) {
ScreenMessage.barWarning(activity, activity.getResources().getString(R.string.toast_file_exists, file.getName()), R.string.overwrite, v -> {
synchronized (saveCallbackLock) {
if (saveCallback != null) {
Log.d(DEBUG_TAG, "saving to " + uri);
saveCallback.save(uri);
}
}
} else if (code == READ_FILE) {
synchronized (readCallbackLock) {
if (readCallback != null) {
Log.d(DEBUG_TAG, "reading " + uri);
readCallback.read(uri);
});
return;
}
synchronized (saveCallbackLock) {
if (saveCallback != null) {
Log.d(DEBUG_TAG, "saving to " + uri);
saveCallback.save(uri);
}
}
}

/**
* Call the callback for reading an or multiple files
*
* @param data the Intent
* @param uri the file Uri
*/
private static void callReadCallback(@NonNull Intent data, @Nullable Uri uri) {
synchronized (readCallbackLock) {
if (readCallback != null) {
Log.d(DEBUG_TAG, "reading " + uri);
if (uri == null) {
ClipData clipData = data.getClipData();
List<Uri> uris = new ArrayList<>();
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
Uri u = item.getUri();
if (u != null) {
uris.add(u);
}
}
readCallback.read(uris);
return;
}
readCallback.read(uri);
}
} catch (NetworkOnMainThreadException nex) {
Log.e(DEBUG_TAG, "Got exception for " + " uri " + nex.getMessage());
ScreenMessage.toastTopError(activity, activity.getString(R.string.toast_network_file_not_supported, nex.getMessage()));
}
}

Expand Down

0 comments on commit 104a78e

Please sign in to comment.