mirror of
				https://github.com/SimpleMobileTools/Simple-Voice-Recorder.git
				synced 2025-06-05 21:59:31 +02:00 
			
		
		
		
	Read using new queries on R+ devices to properly get trashed media
This commit is contained in:
		| @@ -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' | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user