Read using new queries on R+ devices to properly get trashed media

This commit is contained in:
Ensar Sarajčić 2023-07-25 12:13:54 +02:00
parent b9035f2612
commit 950f5a0207
3 changed files with 59 additions and 21 deletions

View File

@ -63,7 +63,7 @@ android {
} }
dependencies { dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:f76d729b9d' implementation 'com.github.esensar:Simple-Commons:6e36665609'
implementation 'org.greenrobot:eventbus:3.3.1' implementation 'org.greenrobot:eventbus:3.3.1'
implementation 'com.github.Armen101:AudioRecordView:1.0.4' implementation 'com.github.Armen101:AudioRecordView:1.0.4'
implementation 'androidx.documentfile:documentfile:1.0.1' implementation 'androidx.documentfile:documentfile:1.0.1'

View File

@ -3,13 +3,13 @@ package com.simplemobiletools.voicerecorder.extensions
import android.content.ContentValues import android.content.ContentValues
import android.provider.MediaStore import android.provider.MediaStore
import android.provider.MediaStore.Audio.Media import android.provider.MediaStore.Audio.Media
import androidx.core.net.toUri
import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.deleteFile import com.simplemobiletools.commons.extensions.deleteFile
import com.simplemobiletools.commons.extensions.getParentPath import com.simplemobiletools.commons.extensions.getParentPath
import com.simplemobiletools.commons.extensions.toFileDirItem import com.simplemobiletools.commons.extensions.toFileDirItem
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.FileDirItem import com.simplemobiletools.commons.models.FileDirItem
import com.simplemobiletools.voicerecorder.helpers.getAudioFileContentUri
import com.simplemobiletools.voicerecorder.models.Recording import com.simplemobiletools.voicerecorder.models.Recording
import java.io.File import java.io.File
@ -17,7 +17,7 @@ fun BaseSimpleActivity.deleteRecordings(recordingsToRemove: Collection<Recording
when { when {
isRPlus() -> { isRPlus() -> {
val fileUris = recordingsToRemove.map { recording -> val fileUris = recordingsToRemove.map { recording ->
"${Media.EXTERNAL_CONTENT_URI}/${recording.id.toLong()}".toUri() getAudioFileContentUri(recording.id.toLong())
} }
deleteSDK30Uris(fileUris, callback) deleteSDK30Uris(fileUris, callback)
@ -52,7 +52,7 @@ fun BaseSimpleActivity.restoreRecordings(recordingsToRestore: Collection<Recordi
when { when {
isRPlus() -> { isRPlus() -> {
val fileUris = recordingsToRestore.map { recording -> val fileUris = recordingsToRestore.map { recording ->
"${Media.EXTERNAL_CONTENT_URI}/${recording.id.toLong()}".toUri() getAudioFileContentUri(recording.id.toLong())
} }
trashSDK30Uris(fileUris, false, callback) trashSDK30Uris(fileUris, false, callback)
@ -107,7 +107,7 @@ fun BaseSimpleActivity.moveRecordingsToRecycleBin(recordingsToMove: Collection<R
when { when {
isRPlus() -> { isRPlus() -> {
val fileUris = recordingsToMove.map { recording -> val fileUris = recordingsToMove.map { recording ->
"${Media.EXTERNAL_CONTENT_URI}/${recording.id.toLong()}".toUri() getAudioFileContentUri(recording.id.toLong())
} }
trashSDK30Uris(fileUris, true, callback) trashSDK30Uris(fileUris, true, callback)

View File

@ -3,13 +3,16 @@ package com.simplemobiletools.voicerecorder.extensions
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.ComponentName import android.content.ComponentName
import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.database.Cursor
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.media.MediaMetadataRetriever import android.media.MediaMetadataRetriever
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.provider.MediaStore import android.provider.MediaStore
import android.provider.MediaStore.Audio.Media import android.provider.MediaStore.Audio.Media
@ -57,6 +60,37 @@ fun Context.getDefaultRecordingsRelativePath(): String {
} }
} }
@SuppressLint("InlinedApi")
fun Context.getNewMediaStoreRecordings(trashed: Boolean = false): ArrayList<Recording> {
val recordings = ArrayList<Recording>()
val uri = Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val projection = arrayOf(
Media._ID,
Media.DISPLAY_NAME,
Media.DATE_ADDED,
Media.DURATION,
Media.SIZE
)
val bundle = Bundle().apply {
putStringArray(ContentResolver.QUERY_ARG_SORT_COLUMNS, arrayOf(Media.DATE_ADDED))
putInt(ContentResolver.QUERY_ARG_SORT_DIRECTION, ContentResolver.QUERY_SORT_DIRECTION_DESCENDING)
putString(ContentResolver.QUERY_ARG_SQL_SELECTION, "${Media.OWNER_PACKAGE_NAME} = ?")
putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(packageName))
if (config.useRecycleBin) {
val trashedValue = if (trashed) MediaStore.MATCH_ONLY else MediaStore.MATCH_EXCLUDE
putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, trashedValue)
}
}
queryCursor(uri, projection, bundle, true) { cursor ->
val recording = readRecordingFromCursor(cursor)
recordings.add(recording)
}
return recordings
}
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
fun Context.getMediaStoreRecordings(trashed: Boolean = false): ArrayList<Recording> { fun Context.getMediaStoreRecordings(trashed: Boolean = false): ArrayList<Recording> {
val recordings = ArrayList<Recording>() val recordings = ArrayList<Recording>()
@ -81,21 +115,7 @@ fun Context.getMediaStoreRecordings(trashed: Boolean = false): ArrayList<Recordi
} }
queryCursor(uri, projection, selection, selectionArgs, sortOrder, true) { cursor -> queryCursor(uri, projection, selection, selectionArgs, sortOrder, true) { cursor ->
val id = cursor.getIntValue(Media._ID) val recording = readRecordingFromCursor(cursor)
val title = cursor.getStringValue(Media.DISPLAY_NAME)
val timestamp = cursor.getIntValue(Media.DATE_ADDED)
var duration = cursor.getLongValue(Media.DURATION) / 1000
var size = cursor.getIntValue(Media.SIZE)
if (duration == 0L) {
duration = getDurationFromUri(getAudioFileContentUri(id.toLong()))
}
if (size == 0) {
size = getSizeFromUri(id.toLong())
}
val recording = Recording(id, title, "", timestamp, duration.toInt(), size)
recordings.add(recording) recordings.add(recording)
} }
@ -152,7 +172,7 @@ fun Context.getAllRecordings(trashed: Boolean = false): ArrayList<Recording> {
val recordings = ArrayList<Recording>() val recordings = ArrayList<Recording>()
return when { return when {
isRPlus() -> { isRPlus() -> {
recordings.addAll(getMediaStoreRecordings(trashed)) recordings.addAll(getNewMediaStoreRecordings(trashed))
recordings.addAll(getSAFRecordings(trashed)) recordings.addAll(getSAFRecordings(trashed))
recordings recordings
} }
@ -181,6 +201,24 @@ fun Context.getOrCreateTrashFolder(): String {
return trashFolder return trashFolder
} }
private fun Context.readRecordingFromCursor(cursor: Cursor): Recording {
val id = cursor.getIntValue(Media._ID)
val title = cursor.getStringValue(Media.DISPLAY_NAME)
val timestamp = cursor.getIntValue(Media.DATE_ADDED)
var duration = cursor.getLongValue(Media.DURATION) / 1000
var size = cursor.getIntValue(Media.SIZE)
if (duration == 0L) {
duration = getDurationFromUri(getAudioFileContentUri(id.toLong()))
}
if (size == 0) {
size = getSizeFromUri(id.toLong())
}
return Recording(id, title, "", timestamp, duration.toInt(), size)
}
private fun Context.getSizeFromUri(id: Long): Int { private fun Context.getSizeFromUri(id: Long): Int {
val recordingUri = getAudioFileContentUri(id) val recordingUri = getAudioFileContentUri(id)
return try { return try {