diff --git a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/DeleteTask.java b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/DeleteTask.java index 15ec67cace..c63bbe3ef6 100644 --- a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/DeleteTask.java +++ b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/DeleteTask.java @@ -38,7 +38,7 @@ import com.amaze.filemanager.filesystem.SafRootHolder; import com.amaze.filemanager.filesystem.cloud.CloudUtil; import com.amaze.filemanager.filesystem.files.CryptUtil; -import com.amaze.filemanager.filesystem.files.FileUtils; +import com.amaze.filemanager.filesystem.files.MediaConnectionUtils; import com.amaze.filemanager.ui.activities.MainActivity; import com.amaze.filemanager.ui.fragments.CompressedExplorerFragment; import com.amaze.filemanager.ui.fragments.preferencefragments.PreferencesConstants; @@ -48,12 +48,9 @@ import com.cloudrail.si.interfaces.CloudStorage; import android.app.NotificationManager; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.net.Uri; import android.os.AsyncTask; -import android.provider.MediaStore; import android.widget.Toast; import androidx.annotation.NonNull; @@ -112,13 +109,9 @@ protected final AsyncTaskResult doInBackground( } // delete file from media database - if (!file.isSmb()) { - try { - deleteFromMediaDatabase(applicationContext, file.getPath()); - } catch (Exception e) { - FileUtils.scanFile(applicationContext, files.toArray(new HybridFile[files.size()])); - } - } + if (!file.isSmb()) + MediaConnectionUtils.scanFile( + applicationContext, files.toArray(new HybridFile[files.size()])); // delete file entry from encrypted database if (file.getName(applicationContext).endsWith(CryptUtil.CRYPT_EXTENSION)) { @@ -194,13 +187,4 @@ private boolean doDeleteFile(@NonNull HybridFileParcelable file) throws Exceptio } } } - - private void deleteFromMediaDatabase(final Context context, final String file) { - final String where = MediaStore.MediaColumns.DATA + "=?"; - final String[] selectionArgs = new String[] {file}; - final ContentResolver contentResolver = context.getContentResolver(); - final Uri filesUri = MediaStore.Files.getContentUri("external"); - // Delete the entry from the media database. This will actually delete media files. - contentResolver.delete(filesUri, where, selectionArgs); - } } diff --git a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/movecopy/MoveFilesTask.kt b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/movecopy/MoveFilesTask.kt index 196f05d668..988cfb8bde 100644 --- a/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/movecopy/MoveFilesTask.kt +++ b/app/src/main/java/com/amaze/filemanager/asynchronous/asynctasks/movecopy/MoveFilesTask.kt @@ -34,7 +34,7 @@ import com.amaze.filemanager.fileoperations.filesystem.OpenMode import com.amaze.filemanager.filesystem.HybridFile import com.amaze.filemanager.filesystem.HybridFileParcelable import com.amaze.filemanager.filesystem.files.CryptUtil -import com.amaze.filemanager.filesystem.files.FileUtils +import com.amaze.filemanager.filesystem.files.MediaConnectionUtils import com.amaze.filemanager.ui.activities.MainActivity import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -106,8 +106,8 @@ class MoveFilesTask( for (hybridFileParcelables in files) { sourcesFiles.addAll(hybridFileParcelables) } - FileUtils.scanFile(applicationContext, sourcesFiles.toTypedArray()) - FileUtils.scanFile(applicationContext, targetFiles.toTypedArray()) + MediaConnectionUtils.scanFile(applicationContext, sourcesFiles.toTypedArray()) + MediaConnectionUtils.scanFile(applicationContext, targetFiles.toTypedArray()) } // updating encrypted db entry if any encrypted file was moved diff --git a/app/src/main/java/com/amaze/filemanager/asynchronous/services/CopyService.java b/app/src/main/java/com/amaze/filemanager/asynchronous/services/CopyService.java index fbb0ae012a..2ddfca97e3 100644 --- a/app/src/main/java/com/amaze/filemanager/asynchronous/services/CopyService.java +++ b/app/src/main/java/com/amaze/filemanager/asynchronous/services/CopyService.java @@ -43,6 +43,7 @@ import com.amaze.filemanager.filesystem.files.CryptUtil; import com.amaze.filemanager.filesystem.files.FileUtils; import com.amaze.filemanager.filesystem.files.GenericCopyUtil; +import com.amaze.filemanager.filesystem.files.MediaConnectionUtils; import com.amaze.filemanager.filesystem.root.CopyFilesCommand; import com.amaze.filemanager.filesystem.root.MoveFileCommand; import com.amaze.filemanager.ui.activities.MainActivity; @@ -461,7 +462,7 @@ void copyRoot(HybridFileParcelable sourceFile, HybridFile targetFile, boolean mo e); failedFOps.add(sourceFile); } - FileUtils.scanFile(c, new HybridFile[] {targetFile}); + MediaConnectionUtils.scanFile(c, new HybridFile[] {targetFile}); } private void copyFiles( diff --git a/app/src/main/java/com/amaze/filemanager/filesystem/Operations.java b/app/src/main/java/com/amaze/filemanager/filesystem/Operations.java index 4125f726eb..6786b1efa2 100644 --- a/app/src/main/java/com/amaze/filemanager/filesystem/Operations.java +++ b/app/src/main/java/com/amaze/filemanager/filesystem/Operations.java @@ -41,6 +41,7 @@ import com.amaze.filemanager.fileoperations.filesystem.OpenMode; import com.amaze.filemanager.filesystem.cloud.CloudUtil; import com.amaze.filemanager.filesystem.files.FileUtils; +import com.amaze.filemanager.filesystem.files.MediaConnectionUtils; import com.amaze.filemanager.filesystem.ftp.FtpClientTemplate; import com.amaze.filemanager.filesystem.ftp.NetCopyClientUtils; import com.amaze.filemanager.filesystem.root.MakeDirectoryCommand; @@ -715,7 +716,7 @@ protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); if (newFile != null && oldFile != null) { HybridFile[] hybridFiles = {newFile, oldFile}; - FileUtils.scanFile(context, hybridFiles); + MediaConnectionUtils.scanFile(context, hybridFiles); } } }.executeOnExecutor(executor); diff --git a/app/src/main/java/com/amaze/filemanager/filesystem/files/FileUtils.java b/app/src/main/java/com/amaze/filemanager/filesystem/files/FileUtils.java index d55e7f09b3..4fcf97cb81 100644 --- a/app/src/main/java/com/amaze/filemanager/filesystem/files/FileUtils.java +++ b/app/src/main/java/com/amaze/filemanager/filesystem/files/FileUtils.java @@ -30,7 +30,6 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; @@ -42,7 +41,6 @@ import com.amaze.filemanager.application.AppConfig; import com.amaze.filemanager.fileoperations.filesystem.OpenMode; import com.amaze.filemanager.fileoperations.filesystem.smbstreamer.Streamer; -import com.amaze.filemanager.filesystem.ExternalSdCardOperation; import com.amaze.filemanager.filesystem.HybridFile; import com.amaze.filemanager.filesystem.HybridFileParcelable; import com.amaze.filemanager.filesystem.Operations; @@ -71,7 +69,6 @@ import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.annotation.SuppressLint; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; @@ -79,7 +76,6 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.media.MediaScannerConnection; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -92,8 +88,6 @@ import androidx.core.util.Pair; import androidx.documentfile.provider.DocumentFile; -import io.reactivex.Flowable; -import io.reactivex.schedulers.Schedulers; import jcifs.smb.SmbFile; import kotlin.collections.ArraysKt; import net.schmizz.sshj.sftp.RemoteResourceInfo; @@ -217,76 +211,6 @@ public static long getBaseFileSize(HybridFileParcelable baseFile, Context contex } } - /** - * Triggers media scanner for multiple paths. The paths must all belong to same filesystem. It's - * upto the caller to call the mediastore scan on multiple files or only one source/target - * directory. Don't use filesystem API directly as files might not be present anymore (eg. - * move/rename) which may lead to {@link java.io.FileNotFoundException} - * - * @param hybridFiles - * @param context - */ - @SuppressLint("CheckResult") - public static void scanFile(@NonNull Context context, @NonNull HybridFile[] hybridFiles) { - Flowable.fromCallable( - (Callable) - () -> { - if (hybridFiles[0].exists(context) && hybridFiles[0].isLocal()) { - String[] paths = new String[hybridFiles.length]; - for (int i = 0; i < hybridFiles.length; i++) { - HybridFile hybridFile = hybridFiles[i]; - paths[i] = hybridFile.getPath(); - } - MediaScannerConnection.scanFile(context, paths, null, null); - } - for (HybridFile hybridFile : hybridFiles) { - scanFile(hybridFile, context); - } - return null; - }) - .subscribeOn(Schedulers.io()); - } - - /** - * Triggers media store for the file path - * - * @param hybridFile the file which was changed (directory not supported) - * @param context given context - */ - private static void scanFile(@NonNull HybridFile hybridFile, Context context) { - - if ((hybridFile.isLocal() || hybridFile.isOtgFile()) && hybridFile.exists(context)) { - - Uri uri = null; - if (Build.VERSION.SDK_INT >= 19) { - DocumentFile documentFile = - ExternalSdCardOperation.getDocumentFile( - hybridFile.getFile(), hybridFile.isDirectory(context), context); - // If FileUtil.getDocumentFile() returns null, fall back to DocumentFile.fromFile() - if (documentFile == null) documentFile = DocumentFile.fromFile(hybridFile.getFile()); - uri = documentFile.getUri(); - } else { - if (hybridFile.isLocal()) { - uri = Uri.fromFile(hybridFile.getFile()); - } - } - if (uri != null) { - FileUtils.scanFile(uri, context); - } - } - } - - /** - * Triggers {@link Intent#ACTION_MEDIA_SCANNER_SCAN_FILE} intent to refresh the media store. - * - * @param uri File's {@link Uri} - * @param c {@link Context} - */ - private static void scanFile(@NonNull Uri uri, @NonNull Context c) { - Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri); - c.sendBroadcast(mediaScanIntent); - } - public static void crossfade(View buttons, final View pathbar) { // Set the content view to 0% opacity but visible, so that it is visible // (but fully transparent) during the animation. diff --git a/app/src/main/java/com/amaze/filemanager/filesystem/files/GenericCopyUtil.java b/app/src/main/java/com/amaze/filemanager/filesystem/files/GenericCopyUtil.java index 068d6a95fe..0f09d9cc49 100644 --- a/app/src/main/java/com/amaze/filemanager/filesystem/files/GenericCopyUtil.java +++ b/app/src/main/java/com/amaze/filemanager/filesystem/files/GenericCopyUtil.java @@ -271,7 +271,7 @@ private void startCopy( // If target file is copied onto the device and copy was successful, trigger media store // rescan if (mTargetFile != null) { - FileUtils.scanFile(mContext, new HybridFile[] {mTargetFile}); + MediaConnectionUtils.scanFile(mContext, new HybridFile[] {mTargetFile}); } } } diff --git a/app/src/main/java/com/amaze/filemanager/filesystem/files/MediaConnectionUtils.kt b/app/src/main/java/com/amaze/filemanager/filesystem/files/MediaConnectionUtils.kt new file mode 100644 index 0000000000..577c33199d --- /dev/null +++ b/app/src/main/java/com/amaze/filemanager/filesystem/files/MediaConnectionUtils.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014-2022 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Manager. + * + * Amaze File Manager is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.amaze.filemanager.filesystem.files + +import android.content.Context +import android.media.MediaScannerConnection +import android.net.Uri +import com.amaze.filemanager.filesystem.HybridFile +import org.slf4j.LoggerFactory + +object MediaConnectionUtils { + + private val LOG = LoggerFactory.getLogger(MediaConnectionUtils::class.java) + + /** + * Invokes MediaScannerConnection#scanFile for the given files + * + * @param context the context + * @param hybridFiles files to be scanned + */ + @JvmStatic + fun scanFile(context: Context, hybridFiles: Array) { + val paths = arrayOfNulls(hybridFiles.size) + + for (i in hybridFiles.indices) paths[i] = hybridFiles[i].path + + MediaScannerConnection.scanFile( + context, + paths, + null + ) { path: String, _: Uri? -> + LOG.info("MediaConnectionUtils#scanFile finished scanning path$path") + } + } +} diff --git a/app/src/main/java/com/amaze/filemanager/ui/fragments/MainFragment.java b/app/src/main/java/com/amaze/filemanager/ui/fragments/MainFragment.java index c8a11f114b..13f2cb06a5 100644 --- a/app/src/main/java/com/amaze/filemanager/ui/fragments/MainFragment.java +++ b/app/src/main/java/com/amaze/filemanager/ui/fragments/MainFragment.java @@ -63,6 +63,7 @@ import com.amaze.filemanager.filesystem.files.EncryptDecryptUtils; import com.amaze.filemanager.filesystem.files.FileListSorter; import com.amaze.filemanager.filesystem.files.FileUtils; +import com.amaze.filemanager.filesystem.files.MediaConnectionUtils; import com.amaze.filemanager.ui.ExtensionsKt; import com.amaze.filemanager.ui.activities.MainActivity; import com.amaze.filemanager.ui.activities.MainActivityViewModel; @@ -1403,7 +1404,7 @@ public void hide(String path) { LOG.warn("failure when hiding file", e); } } - FileUtils.scanFile( + MediaConnectionUtils.scanFile( requireMainActivity(), new HybridFile[] {new HybridFile(OpenMode.FILE, path)}); } }