diff --git a/lib/src/main/java/ch/poole/openinghoursfragment/templates/TemplateMangementDialog.java b/lib/src/main/java/ch/poole/openinghoursfragment/templates/TemplateMangementDialog.java index d12eb89..5c40f8f 100644 --- a/lib/src/main/java/ch/poole/openinghoursfragment/templates/TemplateMangementDialog.java +++ b/lib/src/main/java/ch/poole/openinghoursfragment/templates/TemplateMangementDialog.java @@ -7,6 +7,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import android.annotation.SuppressLint; +import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -17,6 +18,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.provider.MediaStore; import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; @@ -39,7 +41,7 @@ import ch.poole.openinghoursfragment.ValueWithDescription; public class TemplateMangementDialog extends CancelableDialogFragment implements UpdateCursorListener { - public static final String DEBUG_TAG = "TemplateMangementDialog"; + public static final String DEBUG_TAG = TemplateMangementDialog.class.getSimpleName(); private static final String MANAGE_KEY = "manage"; private static final String KEY_KEY = "key"; @@ -53,6 +55,8 @@ public class TemplateMangementDialog extends CancelableDialogFragment implements private static final int READ_REPLACE_CODE = 34567; private static final int WRITE_CODE = 24679; + private static final String INVALID_FILE = "(invalid)"; + /** * Template database related methods and fields */ @@ -62,7 +66,7 @@ public class TemplateMangementDialog extends CancelableDialogFragment implements private ValueWithDescription key; private String current; - private UpdateTextListener updateListener; + private UpdateTextListener updateListener; private SQLiteDatabase readableDb; @@ -124,8 +128,8 @@ public AppCompatDialog onCreateDialog(Bundle savedInstanceState) { String object = getArguments().getString(OBJECT_KEY); current = getArguments().getString(CURRENT_KEY); - updateListener = getParentFragment() instanceof UpdateTextListener ? (UpdateTextListener) getParentFragment() : null; - if (!manage && updateListener == null) { + updateListener = getParentFragment() instanceof UpdateTextListener ? (UpdateTextListener) getParentFragment() : null; + if (!manage && updateListener == null) { throw new IllegalStateException("parent must implement UpdateTextListener"); } @@ -271,7 +275,7 @@ public void bindView(final View view, final Context context, Cursor cursor) { }); } else { view.setOnClickListener(v -> { - updateListener.updateText(template); + updateListener.updateText(template); TemplateMangementDialog.this.dismissAllowingStateLoss(); }); } @@ -310,27 +314,59 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { return; } Uri uri = data.getData(); - if (uri != null) { - if (requestCode == WRITE_CODE) { - try (SQLiteDatabase db = new TemplateDatabaseHelper(getContext()).getReadableDatabase()) { - TemplateDatabase.writeJSON(db, getActivity().getContentResolver().openOutputStream(uri)); - } catch (FileNotFoundException e) { - Log.e(DEBUG_TAG, "Uri " + uri + " not found for writing"); - } - } else if (requestCode == READ_CODE || requestCode == READ_REPLACE_CODE) { - boolean worked = false; - try (SQLiteDatabase writeableDb = new TemplateDatabaseHelper(getContext()).getWritableDatabase()) { - worked = TemplateDatabase.loadJson(writeableDb, getActivity().getContentResolver().openInputStream(uri), requestCode == READ_REPLACE_CODE); - } catch (FileNotFoundException e) { - Log.e(DEBUG_TAG, "Uri " + uri + " not found for reading"); - } finally { - newCursor(readableDb); - } - if (!worked) { - Util.toastTop(getContext(), R.string.spd_ohf_toast_file_read_failure); - } + if (uri == null) { + Log.w(DEBUG_TAG, "Null uri"); + return; + } + if (requestCode == WRITE_CODE) { + ContentResolver resolver = getActivity().getContentResolver(); + String displayName = getDisplayName(resolver, uri); + Log.e(DEBUG_TAG, "Display name " + displayName); + if (displayName == null || displayName.contains(INVALID_FILE)) { + // it would be nice if we could delete here but it doesn't seem to work + Util.toastTop(getContext(), R.string.spd_ohf_toast_no_file_selected); + return; + } + try (SQLiteDatabase db = new TemplateDatabaseHelper(getContext()).getReadableDatabase()) { + TemplateDatabase.writeJSON(db, resolver.openOutputStream(uri)); + } catch (FileNotFoundException e) { + Log.e(DEBUG_TAG, "Uri " + uri + " not found for writing"); + } + } else if (requestCode == READ_CODE || requestCode == READ_REPLACE_CODE) { + boolean worked = false; + try (SQLiteDatabase writeableDb = new TemplateDatabaseHelper(getContext()).getWritableDatabase()) { + worked = TemplateDatabase.loadJson(writeableDb, getActivity().getContentResolver().openInputStream(uri), requestCode == READ_REPLACE_CODE); + } catch (FileNotFoundException e) { + Log.e(DEBUG_TAG, "Uri " + uri + " not found for reading"); + } finally { + newCursor(readableDb); + } + if (!worked) { + Util.toastTop(getContext(), R.string.spd_ohf_toast_file_read_failure); + } + } + } + + /** + * Get the value of a column for this Uri. This is useful for MediaStore Uris, and other file-based + * ContentProviders. + * + * @param resolver a ContentResolver + * @param uri The Uri to query. + * @return The value of the column or null + */ + @Nullable + private static String getDisplayName(@NonNull ContentResolver resolver, @NonNull Uri uri) { + final String[] projection = { MediaStore.MediaColumns.DISPLAY_NAME }; + try (Cursor cursor = resolver.query(uri, projection, null, null, null)) { + if (cursor != null && cursor.moveToFirst()) { + final int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME); + return cursor.getString(column_index); } + } catch (Exception ex) { + Log.e(DEBUG_TAG, ex.getMessage()); } + return null; } @Override diff --git a/lib/src/main/res/values/strings.xml b/lib/src/main/res/values/strings.xml index 3361e2a..9264f8f 100644 --- a/lib/src/main/res/values/strings.xml +++ b/lib/src/main/res/values/strings.xml @@ -24,6 +24,7 @@ Save to file Load from file Load from file (replace) + No target file selected! Yes No Start