diff --git a/src/main/java/de/blau/android/dialogs/Layers.java b/src/main/java/de/blau/android/dialogs/Layers.java index a4f9e0c6ba..dcab5d029f 100644 --- a/src/main/java/de/blau/android/dialogs/Layers.java +++ b/src/main/java/de/blau/android/dialogs/Layers.java @@ -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(); @@ -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 fileUris) { + for (Uri fileUri : fileUris) { + addStyleableLayerFromUri(activity, prefs, map, type, fileUri, false); + } + } + }, true); } /** @@ -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) { @@ -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(); diff --git a/src/main/java/de/blau/android/util/ReadFile.java b/src/main/java/de/blau/android/util/ReadFile.java index 2bded092cd..4b715d73e2 100644 --- a/src/main/java/de/blau/android/util/ReadFile.java +++ b/src/main/java/de/blau/android/util/ReadFile.java @@ -4,6 +4,7 @@ import java.util.List; import android.net.Uri; +import androidx.annotation.NonNull; public abstract class ReadFile implements Serializable { /** @@ -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 uris) { + public void read(@NonNull List uris) { // empty } } diff --git a/src/main/java/de/blau/android/util/SelectFile.java b/src/main/java/de/blau/android/util/SelectFile.java index ae01df1407..5eeaeda63f 100644 --- a/src/main/java/de/blau/android/util/SelectFile.java +++ b/src/main/java/de/blau/android/util/SelectFile.java @@ -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; @@ -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); } @@ -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); } @@ -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") @@ -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 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())); } }