From 31c06457ba879f3358fc77cb0a245d42636b4213 Mon Sep 17 00:00:00 2001 From: EmmanuelMess Date: Sun, 6 Mar 2022 16:39:28 -0300 Subject: [PATCH] wip --- .../asynctasks/CountItemsOrAndSizeTask.java | 32 ++++++++----- .../asynctasks/GenerateHashesTask.java | 15 +++--- .../filemanager/filesystem/HybridFile.java | 1 + .../ui/dialogs/GeneralDialogCreation.java | 47 ++++++++++--------- .../filesystem/filetypes/AmazeFile.kt | 26 ++++++++-- 5 files changed, 77 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/CountItemsOrAndSizeTask.java b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/CountItemsOrAndSizeTask.java index 21b8f2e4cb..216f355d03 100644 --- a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/CountItemsOrAndSizeTask.java +++ b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/CountItemsOrAndSizeTask.java @@ -21,10 +21,11 @@ package com.amaze.filemanager.asynchronous.asynctasks; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import com.amaze.filemanager.R; +import com.amaze.filemanager.file_operations.filesystem.filetypes.AmazeFile; import com.amaze.filemanager.filesystem.HybridFileParcelable; -import com.amaze.filemanager.filesystem.files.FileUtils; import android.content.Context; import android.os.AsyncTask; @@ -33,16 +34,20 @@ import androidx.core.util.Pair; +import kotlin.Unit; + /** @author Emmanuel on 12/5/2017, at 19:40. */ public class CountItemsOrAndSizeTask extends AsyncTask, String> { + private static final String TAG = CountItemsOrAndSizeTask.class.getSimpleName(); + private Context context; private TextView itemsText; - private HybridFileParcelable file; + private AmazeFile file; private boolean isStorage; public CountItemsOrAndSizeTask( - Context c, TextView itemsText, HybridFileParcelable f, boolean storage) { + Context c, TextView itemsText, AmazeFile f, boolean storage) { this.context = c; this.itemsText = itemsText; file = f; @@ -52,23 +57,28 @@ public CountItemsOrAndSizeTask( @Override protected String doInBackground(Void[] params) { String items = ""; - long fileLength = file.length(context); - if (file.isDirectory(context)) { + if (file.isDirectory(() -> context)) { final AtomicInteger x = new AtomicInteger(0); - file.forEachChildrenFile(context, false, file -> x.incrementAndGet()); + file.forFiles(null, () -> context, file -> { x.incrementAndGet(); return Unit.INSTANCE; }); final int folderLength = x.intValue(); - long folderSize; + AtomicLong folderSize = new AtomicLong(); if (isStorage) { - folderSize = file.getUsableSpace(); + folderSize.set(file.getUsableSpace()); } else { - folderSize = - FileUtils.folderSize(file, data -> publishProgress(new Pair<>(folderLength, data))); + file.forFiles(null, () -> context, file -> { + long fileLength = file.safeLength(() -> context); + publishProgress(new Pair<>(folderLength, fileLength)); + folderSize.addAndGet(fileLength); + return Unit.INSTANCE; + }); } - items = getText(folderLength, folderSize, false); + items = getText(folderLength, folderSize.get(), false); } else { + long fileLength = file.safeLength(() -> context); + items = Formatter.formatFileSize(context, fileLength) + (" (" diff --git a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/GenerateHashesTask.java b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/GenerateHashesTask.java index dc5d4ae88b..b7212aca6d 100644 --- a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/GenerateHashesTask.java +++ b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/GenerateHashesTask.java @@ -26,6 +26,7 @@ import java.security.NoSuchAlgorithmException; import com.amaze.filemanager.R; +import com.amaze.filemanager.file_operations.filesystem.filetypes.AmazeFile; import com.amaze.filemanager.filesystem.HybridFileParcelable; import com.amaze.filemanager.filesystem.files.FileUtils; import com.amaze.filemanager.filesystem.files.GenericCopyUtil; @@ -49,15 +50,15 @@ */ public class GenerateHashesTask extends AsyncTask { - private HybridFileParcelable file; + private AmazeFile file; private Context context; private TextView md5HashText; private TextView sha256Text; private LinearLayout mMD5LinearLayout, mSHA256LinearLayout; - public GenerateHashesTask(HybridFileParcelable f, final Context c, final View view) { + public GenerateHashesTask(AmazeFile file, final Context c, final View view) { this.context = c; - this.file = f; + this.file = file; md5HashText = view.findViewById(R.id.t9); sha256Text = view.findViewById(R.id.t10); @@ -110,7 +111,7 @@ public String execute(Session session) throws IOException { } } }); - } else if (!file.isDirectory(context)) { + } else if (!file.isDirectory(() -> context)) { md5 = getMD5Checksum(); sha256 = getSHA256Checksum(); } @@ -124,7 +125,7 @@ public String execute(Session session) throws IOException { @Override protected void onPostExecute(final String[] hashes) { super.onPostExecute(hashes); - if (!file.isDirectory() && file.getSize() != 0) { + if (!file.isDirectory(() -> context) && file.safeLength(() -> context) != 0) { md5HashText.setText(hashes[0]); sha256Text.setText(hashes[1]); @@ -174,7 +175,7 @@ private String getSHA256Checksum() throws NoSuchAlgorithmException, IOException MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); byte[] input = new byte[GenericCopyUtil.DEFAULT_BUFFER_SIZE]; int length; - InputStream inputStream = file.getInputStream(context); + InputStream inputStream = file.getInputStream(() -> context); while ((length = inputStream.read(input)) != -1) { if (length > 0) messageDigest.update(input, 0, length); } @@ -194,7 +195,7 @@ private String getSHA256Checksum() throws NoSuchAlgorithmException, IOException } private byte[] createChecksum() throws Exception { - InputStream fis = file.getInputStream(context); + InputStream fis = file.getInputStream(() -> context); byte[] buffer = new byte[8192]; MessageDigest complete = MessageDigest.getInstance("MD5"); diff --git a/app/src/main/java/com/amaze/filemanager/filesystem/HybridFile.java b/app/src/main/java/com/amaze/filemanager/filesystem/HybridFile.java index ffb09190f7..15fe4163c6 100644 --- a/app/src/main/java/com/amaze/filemanager/filesystem/HybridFile.java +++ b/app/src/main/java/com/amaze/filemanager/filesystem/HybridFile.java @@ -574,6 +574,7 @@ public Boolean execute(SFTPClient client) { } break; case OTG: + new AmazeFile(path).forFiles(null, () -> context, ); OTGUtil.getDocumentFiles(path, context, onFileFound); break; case DOCUMENT_FILE: diff --git a/app/src/main/java/com/amaze/filemanager/ui/dialogs/GeneralDialogCreation.java b/app/src/main/java/com/amaze/filemanager/ui/dialogs/GeneralDialogCreation.java index b662ef2008..bed4dab5b6 100644 --- a/app/src/main/java/com/amaze/filemanager/ui/dialogs/GeneralDialogCreation.java +++ b/app/src/main/java/com/amaze/filemanager/ui/dialogs/GeneralDialogCreation.java @@ -54,6 +54,7 @@ import com.amaze.filemanager.databinding.DialogSigninWithGoogleBinding; import com.amaze.filemanager.file_operations.exceptions.ShellNotRunningException; import com.amaze.filemanager.file_operations.filesystem.OpenMode; +import com.amaze.filemanager.file_operations.filesystem.filetypes.AmazeFile; import com.amaze.filemanager.filesystem.FileProperties; import com.amaze.filemanager.filesystem.HybridFile; import com.amaze.filemanager.filesystem.HybridFileParcelable; @@ -395,32 +396,32 @@ private void updateViews( } public static void showPropertiesDialogWithPermissions( - @NonNull HybridFileParcelable baseFile, + @NonNull AmazeFile file, @Nullable final String permissions, @NonNull MainActivity themedActivity, @NonNull MainFragment mainFragment, boolean isRoot, @NonNull AppTheme appTheme) { showPropertiesDialog( - baseFile, themedActivity, mainFragment, permissions, isRoot, appTheme, false); + file, themedActivity, mainFragment, permissions, isRoot, appTheme, false); } public static void showPropertiesDialogWithoutPermissions( - @NonNull final HybridFileParcelable f, + @NonNull final AmazeFile file, @NonNull ThemedActivity themedActivity, @NonNull AppTheme appTheme) { - showPropertiesDialog(f, themedActivity, null, null, false, appTheme, false); + showPropertiesDialog(file, themedActivity, null, null, false, appTheme, false); } public static void showPropertiesDialogForStorage( - @NonNull final HybridFileParcelable f, + @NonNull final AmazeFile file, @NonNull MainActivity themedActivity, @NonNull AppTheme appTheme) { - showPropertiesDialog(f, themedActivity, null, null, false, appTheme, true); + showPropertiesDialog(file, themedActivity, null, null, false, appTheme, true); } private static void showPropertiesDialog( - @NonNull final HybridFileParcelable baseFile, + @NonNull final AmazeFile file, @NonNull ThemedActivity themedActivity, @Nullable MainFragment mainFragment, @Nullable final String permissions, @@ -430,14 +431,14 @@ private static void showPropertiesDialog( final ExecutorService executor = Executors.newFixedThreadPool(3); final Context c = themedActivity.getApplicationContext(); int accentColor = themedActivity.getAccent(); - long last = baseFile.getDate(); + long last = file.lastModified(); final String date = Utils.getDate(themedActivity, last), items = c.getString(R.string.calculating), - name = baseFile.getName(c), - parent = baseFile.getReadablePath(baseFile.getParent(c)); + name = file.getName(), + parent = file.getHumanRedablePath(); File nomediaFile = - baseFile.isDirectory() ? new File(baseFile.getPath() + "/" + FileUtils.NOMEDIA_FILE) : null; + file.isDirectory(() -> c) ? new File(file.getPath() + "/" + FileUtils.NOMEDIA_FILE) : null; MaterialDialog.Builder builder = new MaterialDialog.Builder(themedActivity); builder.title(c.getString(R.string.properties)); @@ -472,7 +473,7 @@ private static void showPropertiesDialog( itemsText.setText(items); ((TextView) v.findViewById(R.id.t8)).setText(date); - if (baseFile.isDirectory() && baseFile.isLocal()) { + if (file.isDirectory(() -> c) && file.isInDevice()) { nomediaCheckBox.setVisibility(View.VISIBLE); if (nomediaFile != null) { nomediaCheckBox.setChecked(nomediaFile.exists()); @@ -536,10 +537,10 @@ private static void showPropertiesDialog( } CountItemsOrAndSizeTask countItemsOrAndSizeTask = - new CountItemsOrAndSizeTask(c, itemsText, baseFile, forStorage); + new CountItemsOrAndSizeTask(c, itemsText, file, forStorage); countItemsOrAndSizeTask.executeOnExecutor(executor); - GenerateHashesTask hashGen = new GenerateHashesTask(baseFile, c, v); + GenerateHashesTask hashGen = new GenerateHashesTask(file, c, v); hashGen.executeOnExecutor(executor); /*Chart creation and data loading*/ @@ -572,8 +573,8 @@ private static void showPropertiesDialog( Utils.getColor(c, R.color.piechart_red), Utils.getColor(c, R.color.piechart_green) }; - long totalSpace = baseFile.getTotal(c), - freeSpace = baseFile.getUsableSpace(), + long totalSpace = file.getTotalSpace(() -> c), + freeSpace = file.getUsableSpace(), usedSpace = totalSpace - freeSpace; List entries = new ArrayList<>(); @@ -600,7 +601,7 @@ private static void showPropertiesDialog( chart.setData(pieData); } else { LoadFolderSpaceDataTask loadFolderSpaceDataTask = - new LoadFolderSpaceDataTask(c, appTheme, chart, baseFile); + new LoadFolderSpaceDataTask(c, appTheme, chart, file); loadFolderSpaceDataTask.executeOnExecutor(executor); } @@ -621,7 +622,7 @@ private static void showPropertiesDialog( permissionsTable.setVisibility(View.VISIBLE); button.setVisibility(View.VISIBLE); setPermissionsDialog( - permissionsTable, button, baseFile, permissions, c, mainFragment); + permissionsTable, button, file, permissions, c, mainFragment); } else { button.setVisibility(View.GONE); permissionsTable.setVisibility(View.GONE); @@ -636,13 +637,13 @@ private static void showPropertiesDialog( builder.dismissListener(dialog -> executor.shutdown()); builder.onPositive( (dialog, which) -> { - if (baseFile.isDirectory() && nomediaFile != null) { + if (file.isDirectory(() -> c) && nomediaFile != null) { if (nomediaCheckBox.isChecked()) { // checkbox is checked, create .nomedia try { if (!nomediaFile.createNewFile()) { // failed operation - Log.w(TAG, "'.nomedia' file creation in " + baseFile.getPath() + " failed!"); + Log.w(TAG, "'.nomedia' file creation in " + file.getPath() + " failed!"); } } catch (IOException e) { Log.e(TAG, "Error creating file", e); @@ -651,7 +652,7 @@ private static void showPropertiesDialog( // checkbox is unchecked, delete .nomedia if (!nomediaFile.delete()) { // failed operation - Log.w(TAG, "'.nomedia' file deletion in " + baseFile.getPath() + " failed!"); + Log.w(TAG, "'.nomedia' file deletion in " + file.getPath() + " failed!"); } } } @@ -1253,7 +1254,7 @@ private static void onSortTypeSelected( public static void setPermissionsDialog( final View v, View but, - final HybridFile file, + final AmazeFile file, final String f, final Context context, final MainFragment mainFrag) { @@ -1304,7 +1305,7 @@ public static void setPermissionsDialog( ChangeFilePermissionsCommand.INSTANCE.changeFilePermissions( file.getPath(), perms, - file.isDirectory(context), + file.isDirectory(() -> context), isSuccess -> { if (isSuccess) { Toast.makeText(context, mainFrag.getString(R.string.done), Toast.LENGTH_LONG) diff --git a/file_operations/src/main/java/com/amaze/filemanager/file_operations/filesystem/filetypes/AmazeFile.kt b/file_operations/src/main/java/com/amaze/filemanager/file_operations/filesystem/filetypes/AmazeFile.kt index c9a368fa56..6762fb8201 100644 --- a/file_operations/src/main/java/com/amaze/filemanager/file_operations/filesystem/filetypes/AmazeFile.kt +++ b/file_operations/src/main/java/com/amaze/filemanager/file_operations/filesystem/filetypes/AmazeFile.kt @@ -635,9 +635,7 @@ class AmazeFile : Comparable { } /** - * Returns the length of the file denoted by this abstract pathname. The return value is - * unspecified if this pathname denotes a directory. - * + * Returns the length of the file or directory denoted by this abstract pathname. * * Where it is required to distinguish an I/O exception from the case that `0L` is * returned, or where several attributes of the same file are required at the same time, then the @@ -654,6 +652,28 @@ class AmazeFile : Comparable { 0L } else fs.getLength(this, contextProvider) } + + /** + * Returns the length of the file or directory denoted by this abstract pathname. + * + * Where it is required to distinguish an I/O exception from the case that `0L` is + * returned, or where several attributes of the same file are required at the same time, then the + * [Files.readAttributes][java.nio.file.Files.readAttributes] method + * may be used. + * + * @return The length, in bytes, of the file denoted by this abstract pathname, or `0L` + * if the file does not exist. Some operating systems may return `0L` for pathnames + * denoting system-dependent entities such as devices or pipes. + */ + fun safeLength(contextProvider: ContextProvider): Long { + return try { + length(contextProvider) + } catch (e: IOException) { + Log.e(TAG, "Error getting file size", e) + 0L + } + } + /* -- File operations -- */ /** * Atomically creates a new, empty file named by this abstract pathname if and only if a file with