diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 573a4d6..32d1582 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -59,6 +59,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/devs/org/calculator/activities/PreviewActivity.kt b/app/src/main/java/devs/org/calculator/activities/PreviewActivity.kt index 9fd04e2..e06d347 100644 --- a/app/src/main/java/devs/org/calculator/activities/PreviewActivity.kt +++ b/app/src/main/java/devs/org/calculator/activities/PreviewActivity.kt @@ -73,7 +73,7 @@ class PreviewActivity : AppCompatActivity() { private fun clickListeners() { binding.delete.setOnClickListener { - val fileUri = FileManager.FileManager().getContentUri(this, files[binding.viewPager.currentItem], filetype) + val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype) if (fileUri != null) { MaterialAlertDialogBuilder(this) .setTitle("Delete File") @@ -93,7 +93,7 @@ class PreviewActivity : AppCompatActivity() { } binding.unHide.setOnClickListener { - val fileUri = FileManager.FileManager().getContentUri(this, files[binding.viewPager.currentItem], filetype) + val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype) if (fileUri != null) { MaterialAlertDialogBuilder(this) .setTitle("Unhide File") diff --git a/app/src/main/java/devs/org/calculator/adapters/FileAdapter.kt b/app/src/main/java/devs/org/calculator/adapters/FileAdapter.kt index 0f50725..ab69c51 100644 --- a/app/src/main/java/devs/org/calculator/adapters/FileAdapter.kt +++ b/app/src/main/java/devs/org/calculator/adapters/FileAdapter.kt @@ -2,7 +2,6 @@ package devs.org.calculator.adapters import android.content.Context import android.content.Intent -import android.net.Uri import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -16,19 +15,21 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.google.android.material.dialog.MaterialAlertDialogBuilder import devs.org.calculator.R -import devs.org.calculator.activities.BaseGalleryActivity import devs.org.calculator.activities.PreviewActivity -import devs.org.calculator.utils.DialogUtil import devs.org.calculator.utils.FileManager import kotlinx.coroutines.launch import java.io.File -import kotlin.collections.remove -class FileAdapter(private val fileType: FileManager.FileType, var context: Context, private var lifecycleOwner: LifecycleOwner) : +class FileAdapter( + private val fileType: FileManager.FileType, + var context: Context, + private var lifecycleOwner: LifecycleOwner +) : ListAdapter(FileDiffCallback()) { private val selectedItems = mutableSetOf() private var isSelectionMode = false + private var fileName = "Unknown File" inner class FileViewHolder(view: View) : RecyclerView.ViewHolder(view) { private val imageView: ImageView = view.findViewById(R.id.imageView) @@ -42,6 +43,7 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte .centerCrop() .into(imageView) } + FileManager.FileType.VIDEO -> { Glide.with(imageView) .asBitmap() @@ -49,6 +51,7 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte .centerCrop() .into(imageView) } + else -> { val resourceId = when (fileType) { FileManager.FileType.AUDIO -> R.drawable.ic_audio @@ -61,17 +64,20 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte itemView.setOnClickListener { - var fileTypes = when(fileType){ + var fileTypes = when (fileType) { FileManager.FileType.IMAGE -> { "IMAGE" } + FileManager.FileType.VIDEO -> { "VIDEO" } + FileManager.FileType.AUDIO -> { "AUDIO" } + else -> "DOCUMENT" } @@ -83,20 +89,27 @@ class FileAdapter(private val fileType: FileManager.FileType, var context: Conte } itemView.setOnLongClickListener { - val fileUri = FileManager.FileManager().getContentUri(context, file, fileType) - if (fileUri == null) { - Toast.makeText(context, "Unable to access file: $file", Toast.LENGTH_SHORT).show() - return@setOnLongClickListener true - } - val fileName = FileManager.FileName(context).getFileNameFromUri(fileUri)?.toString() ?: "Unknown File" + val fileUri = FileManager.FileManager().getContentUriImage(context, file, fileType) + if (fileUri == null) { + Toast.makeText(context, "Unable to access file: $file", Toast.LENGTH_SHORT) + .show() + + return@setOnLongClickListener true + + } + fileName = FileManager.FileName(context).getFileNameFromUri(fileUri)?.toString() + ?: "Unknown File" + MaterialAlertDialogBuilder(context) .setTitle("Details") - .setMessage("File Name: $fileName\n\nYou can delete or unhide this file.") + .setMessage("File Name: $fileName\n\nFile Path: $file\n\nYou can delete or unhide this file.") .setPositiveButton("Delete") { dialog, _ -> lifecycleOwner.lifecycleScope.launch { - FileManager(context, lifecycleOwner).deletePhotoFromExternalStorage(fileUri) + FileManager(context, lifecycleOwner).deletePhotoFromExternalStorage( + fileUri + ) } val currentList = currentList.toMutableList() currentList.remove(file) diff --git a/app/src/main/java/devs/org/calculator/utils/FileManager.kt b/app/src/main/java/devs/org/calculator/utils/FileManager.kt index e30e49c..19892ae 100644 --- a/app/src/main/java/devs/org/calculator/utils/FileManager.kt +++ b/app/src/main/java/devs/org/calculator/utils/FileManager.kt @@ -24,6 +24,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File import android.Manifest +import androidx.core.content.FileProvider class FileManager(private val context: Context, private val lifecycleOwner: LifecycleOwner) { private lateinit var intentSenderLauncher: ActivityResultLauncher @@ -224,69 +225,29 @@ class FileManager(private val context: Context, private val lifecycleOwner: Life } class FileManager(){ - fun getContentUri(context: Context, file: File, fileType: FileType): Uri? { - when(fileType){ - FileType.IMAGE -> { - val projection = arrayOf(MediaStore.MediaColumns._ID) - val selection = "${MediaStore.MediaColumns.DATA} = ?" - val selectionArgs = arrayOf(file.absolutePath) - val queryUri = MediaStore.Files.getContentUri("external") + fun getContentUriImage(context: Context, file: File, fileType: FileType): Uri? { - context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor -> - if (cursor.moveToFirst()) { - val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)) - return Uri.withAppendedPath(queryUri, id.toString()) - } - } - return null - } + // Query MediaStore for the file + val projection = arrayOf(MediaStore.MediaColumns._ID) + val selection = "${MediaStore.MediaColumns.DATA} = ?" + val selectionArgs = arrayOf(file.absolutePath) + val queryUri = MediaStore.Files.getContentUri("external") - FileType.VIDEO -> { - val projection = arrayOf(MediaStore.Video.Media._ID) - val selection = "${MediaStore.Video.Media.DATA} = ?" - val selectionArgs = arrayOf(file.absolutePath) - val queryUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI - - context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor -> - if (cursor.moveToFirst()) { - val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)) - return Uri.withAppendedPath(queryUri, id.toString()) - } - } - return null - } - FileType.AUDIO -> { - val projection = arrayOf(MediaStore.Audio.Media._ID) - val selection = "${MediaStore.Audio.Media.DATA} = ?" - val selectionArgs = arrayOf(file.absolutePath) - val queryUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI - - context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor -> - if (cursor.moveToFirst()) { - val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)) - return Uri.withAppendedPath(queryUri, id.toString()) - } - } - return null - } - FileType.DOCUMENT -> { - val projection = arrayOf(MediaStore.Files.FileColumns._ID) - val selection = "${MediaStore.Files.FileColumns.DATA} = ?" - val selectionArgs = arrayOf(file.absolutePath) - val queryUri = MediaStore.Files.getContentUri("external") - - context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor -> - if (cursor.moveToFirst()) { - val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)) - return Uri.withAppendedPath(queryUri, id.toString()) - } - } - - return null + context.contentResolver.query(queryUri, projection, selection, selectionArgs, null)?.use { cursor -> + if (cursor.moveToFirst()) { + val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)) + return Uri.withAppendedPath(queryUri, id.toString()) } } + // If the file is not found in MediaStore, fallback to FileProvider for hidden files + return if (file.exists()) { + FileProvider.getUriForFile(context, "devs.org.calculator.fileprovider", file) + } else { + null + } } + } diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..d5d6815 --- /dev/null +++ b/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,8 @@ + + + + + + + +