Skip to content

Commit

Permalink
#169: delete via SAF (SD-Card)
Browse files Browse the repository at this point in the history
  • Loading branch information
k3b committed Apr 12, 2020
1 parent 1705127 commit 015eaf9
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@
import de.k3b.android.androFotoFinder.queries.MediaDBRepository;
import de.k3b.android.androFotoFinder.queries.MergedMediaRepository;
import de.k3b.android.osmdroid.forge.MapsForgeSupport;
import de.k3b.android.util.DocumentFileTranslator;
import de.k3b.android.util.LogCat;
import de.k3b.android.util.PhotoChangeNotifyer;
import de.k3b.android.widget.ActivityWithCallContext;
import de.k3b.android.widget.FilePermissionActivity;
import de.k3b.android.widget.LocalizedActivity;
import de.k3b.database.QueryParameter;
import de.k3b.io.FileApi;
Expand Down Expand Up @@ -149,6 +151,7 @@ public static RefWatcher getRefWatcher(Context context) {
FotoSqlBase.init();

super.onCreate();
FilePermissionActivity.init(this);

LibGlobal.appName = getString(R.string.app_name);
LibGlobal.appVersion = GuiUtil.getAppVersionName(this);
Expand All @@ -171,7 +174,8 @@ public static RefWatcher getRefWatcher(Context context) {
ExifInterface.LOG_TAG, PhotoPropertiesImageReader.LOG_TAG,
FotoSql.LOG_TAG,
MediaDBRepository.LOG_TAG, FileApi.TAG,
MediaContentproviderRepositoryImpl.LOG_TAG) {
MediaContentproviderRepositoryImpl.LOG_TAG,
DocumentFileTranslator.TAG, DocumentFileTranslator.TAG_DOCFILE) {

@Override
public void uncaughtException(Thread thread, Throwable ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ public void invalidateDirectories(String why) {
public void onDirectoryCancel(int queryTypeId) {closeDialogIfNeeded();}

@Override
protected void closeDialogIfNeeded() {
public void closeDialogIfNeeded() {
super.closeDialogIfNeeded();
mDirPicker = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
import de.k3b.android.util.ResourceUtils;
import de.k3b.android.widget.AboutDialogPreference;
import de.k3b.android.widget.Dialogs;
import de.k3b.android.widget.FilePermissionActivity;
import de.k3b.android.widget.UpdateTask;
import de.k3b.database.QueryParameter;
import de.k3b.geo.api.GeoPointDto;
Expand Down Expand Up @@ -859,7 +860,9 @@ public boolean onOptionsItemSelected(MenuItem menuItem) {
AndroidFileCommands fileCommands = mFileCommands;

final SelectedFiles selectedFiles = this.mAdapter.createSelectedFiles(getActivity(), this.mSelectedItems);
if ((mSelectedItems != null) && (fileCommands.onOptionsItemSelected(getActivity(), menuItem, selectedFiles, this))) {
if ((mSelectedItems != null)
&& (fileCommands.onOptionsItemSelected(
(FilePermissionActivity) getActivity(), menuItem, selectedFiles, this))) {
return true;
}
switch (menuItem.getItemId()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -708,9 +708,8 @@ private boolean osRenameTo(final CharSequence title, final File dest, final Sele
// close rename dialog to allow messagebox that prepares to ask
closeDialogIfNeeded();
File missingRoot = getMissingRootDirFileOrNull(currentFoto.getFiles());
if (missingRoot == null) {
return mFileCommands.setContext(this).rename(currentFoto, dest, null);
} else {
if (missingRoot != null) {
// ask for needed permissions
requestRootUriDialog(missingRoot, title,
new IOnDirectoryPermissionGrantedHandler() {
@Override
Expand All @@ -720,6 +719,9 @@ public void afterGrant(FilePermissionActivity activity) {
});
return false;
}

// needed permissions available: Go on
return mFileCommands.setContext(this).rename(currentFoto, dest, null);
}

@Override
Expand Down
57 changes: 44 additions & 13 deletions app/src/main/java/de/k3b/android/util/AndroidFileApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,17 @@ private DocumentFileTranslator getDocumentFileTranslator() {
}

protected boolean osRenameTo(File dest, File source) {
final String context = this.getClass().getSimpleName() +
String context = this.getClass().getSimpleName() +
".osRenameTo(" + dest + " <== " + source + ")";
if ((source != null) && (dest != null)) {
if (dest.getParentFile().equals(source.getParentFile())) {
Boolean result = null;
try {
DocumentFile documentFile = DocumentFile.fromFile(source);
if (!documentFile.canWrite()) {
if (source.isDirectory()) {
documentFile = getOrCreateDirectory(source);
} else {
DocumentFile dir = getOrCreateDirectory(source.getParentFile());
DocumentFile found = dir.findFile(source.getName());
if (found != null) {
documentFile = found;
}
}
DocumentFile documentFile = geWritabletDocumentFile(source);
context += FastDocumentFileTranslator.toUriDebugString(documentFile);
if (documentFile != null) {
result = documentFile.renameTo(dest.getName());
}
result = documentFile.renameTo(dest.getName());
return result;
} finally {
if (Global.debugEnabled) {
Expand All @@ -89,4 +81,43 @@ protected boolean osRenameTo(File dest, File source) {
Log.w(TAG, context + " move between different directories is not implemented yet");
return super.osRenameTo(dest, source);
}

protected boolean osDeleteFile(File file) {
String context = this.getClass().getSimpleName() +
".osDeleteFile(" + file + ")";
if (file != null) {
Boolean result = null;
try {
DocumentFile documentFile = geWritabletDocumentFile(file);
context += FastDocumentFileTranslator.toUriDebugString(documentFile);
if (documentFile != null) {
result = documentFile.delete();
}
return result;
} finally {
if (Global.debugEnabled) {
Log.d(TAG, context + " ==> " + result);
}
}
}

return super.osDeleteFile(file);
}

private DocumentFile geWritabletDocumentFile(File file) {
DocumentFile documentFile = DocumentFile.fromFile(file);
if (!documentFile.canWrite()) {
if (file.isDirectory()) {
documentFile = getOrCreateDirectory(file);
} else {
DocumentFile dir = getOrCreateDirectory(file.getParentFile());
DocumentFile found = dir.findFile(file.getName());
if (found != null) {
documentFile = found;
}
}
}
return documentFile;
}

}
30 changes: 23 additions & 7 deletions app/src/main/java/de/k3b/android/util/AndroidFileCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import de.k3b.android.androFotoFinder.queries.FotoSql;
import de.k3b.android.androFotoFinder.tagDB.TagSql;
import de.k3b.android.androFotoFinder.transactionlog.TransactionLogSql;
import de.k3b.android.widget.FilePermissionActivity;
import de.k3b.database.QueryParameter;
import de.k3b.io.DirectoryFormatter;
import de.k3b.io.FileCommands;
Expand Down Expand Up @@ -174,12 +175,12 @@ private static int getResourceId(int opCode) {

}

public boolean onOptionsItemSelected(Activity activity, final MenuItem item, final SelectedFiles selectedFileNames, PhotoChangeNotifyer.PhotoChangedListener photoChangedListener) {
public boolean onOptionsItemSelected(FilePermissionActivity activity, final MenuItem item, final SelectedFiles selectedFileNames, PhotoChangeNotifyer.PhotoChangedListener photoChangedListener) {
if ((selectedFileNames != null) && (selectedFileNames.size() > 0)) {
// Handle item selection
switch (item.getItemId()) {
case R.id.cmd_delete:
return cmdDeleteFileWithQuestion(activity, selectedFileNames, photoChangedListener);
return cmdDeleteFileWithQuestion(item.getTitle(), activity, selectedFileNames, photoChangedListener);
default:break;
}
}
Expand Down Expand Up @@ -277,10 +278,25 @@ private void setLastCopyToPath(String copyToPath) {
edit.apply();
}

public boolean cmdDeleteFileWithQuestion(Activity activity, final SelectedFiles fotos,
final PhotoChangeNotifyer.PhotoChangedListener photoChangedListener) {
private boolean cmdDeleteFileWithQuestion(final CharSequence title, FilePermissionActivity activity, final SelectedFiles fotos,
final PhotoChangeNotifyer.PhotoChangedListener photoChangedListener) {
String[] pathNames = fotos.getFileNames();
String errorMessage = checkWriteProtected(R.string.delete_menu_title, SelectedFiles.getFiles(pathNames));
activity.closeDialogIfNeeded();
File missingRoot = activity.getMissingRootDirFileOrNull(fotos.getFiles());
if (missingRoot != null) {
activity.requestRootUriDialog(missingRoot, title,
new FilePermissionActivity.IOnDirectoryPermissionGrantedHandler() {
@Override
public void afterGrant(FilePermissionActivity activity) {
cmdDeleteFileWithQuestion(title, activity, fotos, photoChangedListener);
}
});
return false;
}

//!!! how to distinguish between sd writeprotected and file writeprotected
// String errorMessage = checkWriteProtected(R.string.delete_menu_title, SelectedFiles.getFiles(pathNames));
String errorMessage = null;

if (errorMessage != null) {
if (!isInBackground) {
Expand All @@ -295,10 +311,10 @@ public boolean cmdDeleteFileWithQuestion(Activity activity, final SelectedFiles
.getString(R.string.delete_question_message_format, names.toString());

final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final String title = mContext.getText(R.string.delete_question_title)
final String titleQuestion = mContext.getText(R.string.delete_question_title)
.toString();

builder.setTitle(title + pathNames.length);
builder.setTitle(titleQuestion + pathNames.length);
builder.setMessage(message)
.setCancelable(false)
.setPositiveButton(android.R.string.yes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
*/
public class DocumentFileTranslator {
public static final String TAG = "k3b.DocFileUtils";

// used by android.support.v4.provider.DocumentFile
public static final String TAG_DOCFILE = "DocumentFile";

private static final String SAFROOTPREF_KEY_SAF_ROOT_PREFIX = "safroot-";
private static DocumentFileTranslator rootsettings = null;
private final Context context;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public abstract class ActivityWithAutoCloseDialogs extends LocalizedActivity {
private Closeable mCloseable;
private DialogInterface mCurrentDialog;

protected void closeDialogIfNeeded() {
public void closeDialogIfNeeded() {
// close dialog. else crash in onResume
if (mCurrentDialog != null) mCurrentDialog.dismiss();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ public void onDirectoryCancel(int queryTypeId) {
}

@Override
protected void closeDialogIfNeeded() {
public void closeDialogIfNeeded() {
super.closeDialogIfNeeded();
getFolderApi().mDirPicker = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import android.Manifest;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
Expand Down Expand Up @@ -55,6 +56,8 @@ public abstract class FilePermissionActivity extends ActivityWithAutoCloseDialog
private static File currentRootFileRequest = null;
private DocumentFileTranslator documentFileTranslator = null;

public static void init(Context context) {
}
// workflow onCreate() => requestPermission(PERMISSION_WRITE_EXTERNAL_STORAGE) => onRequestPermissionsResult() => abstract onCreateEx()
@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -134,7 +137,7 @@ private static void execRequestRootUri(
* @return null if all permissions are granted or
* the root file that has not permissions yet.
*/
protected File getMissingRootDirFileOrNull(File... dirs) {
public File getMissingRootDirFileOrNull(File... dirs) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
for (int i = dirs.length - 1; i >= 0; i--) {
if (null == getOrCreateDirectory(dirs[i])) {
Expand Down Expand Up @@ -178,7 +181,7 @@ public DocumentFileTranslator getDocumentFileTranslator() {

// ... -> requestRootUriDialog -> execRequestRootUri
// -> onActivityResult -> onRootUriResult -> IOnDirectoryPermissionGrantedHandler.afterGrant()
protected void requestRootUriDialog(File root, final CharSequence title, IOnDirectoryPermissionGrantedHandler permissionGrantedHandler) {
public void requestRootUriDialog(File root, final CharSequence title, IOnDirectoryPermissionGrantedHandler permissionGrantedHandler) {
requestRootUriDialog(this, root,
title,
getString(R.string.select_folder_root_rationale),
Expand Down
4 changes: 4 additions & 0 deletions fotolib2/src/main/java/de/k3b/io/FileApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ protected boolean osRenameTo(File dest, File source) {
return (source != null) && (dest != null) && source.renameTo(dest);
}

protected boolean osDeleteFile(File file) {
return (file != null) && (file.canWrite()) && file.delete();
}

}
3 changes: 1 addition & 2 deletions fotolib2/src/main/java/de/k3b/io/FileCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -528,9 +528,8 @@ private static boolean _osFileCopy(File targetFullPath, File sourceFullPath, Fil
return result;
}

/** to be replaced by mock/stub in unittests */
protected boolean osDeleteFile(File file) {
final boolean result = file.delete();
final boolean result = fileApi.osDeleteFile(file);
if (LibGlobal.debugEnabledJpg) logger.info("osDeleteFile '" + file + "' success=" + result);
return result;
}
Expand Down

0 comments on commit 015eaf9

Please sign in to comment.