From e784ca7b779a8c39b6932012269b6b1308f6b24a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 10 Jan 2023 10:49:57 +0100 Subject: [PATCH] Reworked Media Store export functions in compatibility packages --- .../main/files/fragments/TopBarFragment.kt | 10 +- .../compatibility/Api23Compatibility.kt | 157 ++++++++--------- .../compatibility/Api29Compatibility.kt | 162 ++++++++---------- .../java/org/linphone/core/CoreContext.kt | 6 +- 4 files changed, 152 insertions(+), 183 deletions(-) diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt index 320df704b..9134163dc 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt @@ -95,7 +95,7 @@ class TopBarFragment : GenericFragment() { Compatibility.addImageToMediaStore(requireContext(), content) } if (export.await()) { - Log.i("[File Viewer] Adding image ${content.name} to Media Store terminated: ${content.userData}") + Log.i("[File Viewer] Successfully exported image [${content.name}] to Media Store: ${content.userData}") mediaStoreFilePath = content.userData.toString() } else { Log.e("[File Viewer] Something went wrong while copying file to Media Store...") @@ -106,7 +106,7 @@ class TopBarFragment : GenericFragment() { Compatibility.addVideoToMediaStore(requireContext(), content) } if (export.await()) { - Log.i("[File Viewer] Adding video ${content.name} to Media Store terminated: ${content.userData}") + Log.i("[File Viewer] Successfully exported video [${content.name}] to Media Store: ${content.userData}") mediaStoreFilePath = content.userData.toString() } else { Log.e("[File Viewer] Something went wrong while copying file to Media Store...") @@ -117,14 +117,14 @@ class TopBarFragment : GenericFragment() { Compatibility.addAudioToMediaStore(requireContext(), content) } if (export.await()) { - Log.i("[File Viewer] Adding audio ${content.name} to Media Store terminated: ${content.userData}") + Log.i("[File Viewer] Successfully exported audio [${content.name}] to Media Store: ${content.userData}") mediaStoreFilePath = content.userData.toString() } else { Log.e("[File Viewer] Something went wrong while copying file to Media Store...") } } else -> { - Log.w("[File Viewer] File ${content.name} isn't either an image, an audio file or a video, can't add it to the Media Store") + Log.w("[File Viewer] File [${content.name}] isn't either an image, an audio file or a video, can't add it to the Media Store") } } } else { @@ -142,7 +142,7 @@ class TopBarFragment : GenericFragment() { if (!FileUtils.openFileInThirdPartyApp(requireActivity(), plainFilePath)) { (requireActivity() as SnackBarActivity).showSnackBar(R.string.chat_message_no_app_found_to_handle_file_mime_type) if (plainFilePath != content.filePath.orEmpty()) { - Log.i("[File Viewer] No app to open plain file path: $plainFilePath, destroying it") + Log.i("[File Viewer] No app to open plain file path [$plainFilePath], destroying it") FileUtils.deleteFile(plainFilePath) } plainFilePath = "" diff --git a/app/src/main/java/org/linphone/compatibility/Api23Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api23Compatibility.kt index 6f73dab31..0aee2bb75 100644 --- a/app/src/main/java/org/linphone/compatibility/Api23Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Api23Compatibility.kt @@ -142,119 +142,100 @@ class Api23Compatibility { } suspend fun addImageToMediaStore(context: Context, content: Content): Boolean { - if (!PermissionHelper.get().hasWriteExternalStoragePermission()) { - Log.e("[Media Store] Write external storage permission denied") - return false - } - - val plainFilePath = content.exportPlainFile().orEmpty() - val isVfsEncrypted = plainFilePath.isNotEmpty() - Log.w("[Media Store] Content is encrypted, requesting plain file path") - val filePath = if (isVfsEncrypted) plainFilePath else content.filePath - if (filePath == null) { - Log.e("[Media Store] Content doesn't have a file path!") - return false - } - - val appName = AppUtils.getString(R.string.app_name) - val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName" - val fileName = content.name - val mime = "${content.type}/${content.subtype}" - Log.i("[Media Store] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath") - - val values = ContentValues().apply { - put(MediaStore.Images.Media.DISPLAY_NAME, fileName) - put(MediaStore.Images.Media.MIME_TYPE, mime) - } - val collection = MediaStore.Images.Media.getContentUri("external") - val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values) - if (isVfsEncrypted) { - Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath") - FileUtils.deleteFile(plainFilePath) - } - if (mediaStoreFilePath.isNotEmpty()) { - content.userData = mediaStoreFilePath - return true - } - return false + return addContentToMediaStore(context, content, isImage = true) } suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean { - if (!PermissionHelper.get().hasWriteExternalStoragePermission()) { - Log.e("[Media Store] Write external storage permission denied") - return false - } - - val plainFilePath = content.exportPlainFile().orEmpty() - val isVfsEncrypted = plainFilePath.isNotEmpty() - Log.w("[Media Store] Content is encrypted, requesting plain file path") - val filePath = if (isVfsEncrypted) plainFilePath else content.filePath - if (filePath == null) { - Log.e("[Media Store] Content doesn't have a file path!") - return false - } - - val appName = AppUtils.getString(R.string.app_name) - val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName" - val fileName = content.name - val mime = "${content.type}/${content.subtype}" - Log.i("[Media Store] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath") - - val values = ContentValues().apply { - put(MediaStore.Video.Media.TITLE, fileName) - put(MediaStore.Video.Media.DISPLAY_NAME, fileName) - put(MediaStore.Video.Media.MIME_TYPE, mime) - } - val collection = MediaStore.Video.Media.getContentUri("external") - val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values) - if (isVfsEncrypted) { - Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath") - FileUtils.deleteFile(plainFilePath) - } - if (mediaStoreFilePath.isNotEmpty()) { - content.userData = mediaStoreFilePath - return true - } - return false + return addContentToMediaStore(context, content, isVideo = true) } suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean { + return addContentToMediaStore(context, content, isAudio = true) + } + + private suspend fun addContentToMediaStore( + context: Context, + content: Content, + isImage: Boolean = false, + isVideo: Boolean = false, + isAudio: Boolean = false + ): Boolean { if (!PermissionHelper.get().hasWriteExternalStoragePermission()) { Log.e("[Media Store] Write external storage permission denied") return false } - val plainFilePath = content.exportPlainFile().orEmpty() - val isVfsEncrypted = plainFilePath.isNotEmpty() - Log.w("[Media Store] Content is encrypted, requesting plain file path") - val filePath = if (isVfsEncrypted) plainFilePath else content.filePath - if (filePath == null) { + val isContentEncrypted = content.isFileEncrypted + val filePath = if (content.isFileEncrypted) { + val plainFilePath = content.exportPlainFile().orEmpty() + Log.w("[Media Store] Content is encrypted, plain file path is: $plainFilePath") + plainFilePath + } else content.filePath + + if (filePath.isNullOrEmpty()) { Log.e("[Media Store] Content doesn't have a file path!") return false } val appName = AppUtils.getString(R.string.app_name) - val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName" + val directory = when { + isImage -> Environment.DIRECTORY_PICTURES + isVideo -> Environment.DIRECTORY_MOVIES + isAudio -> Environment.DIRECTORY_MUSIC + else -> Environment.DIRECTORY_DOWNLOADS + } + val relativePath = "$directory/$appName" val fileName = content.name val mime = "${content.type}/${content.subtype}" - Log.i("[Media Store] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath") - - val values = ContentValues().apply { - put(MediaStore.Audio.Media.TITLE, fileName) - put(MediaStore.Audio.Media.DISPLAY_NAME, fileName) - put(MediaStore.Audio.Media.MIME_TYPE, mime) + val type = when { + isImage -> "image" + isVideo -> "video" + isAudio -> "audio" + else -> "unexpected" } - val collection = MediaStore.Audio.Media.getContentUri("external") + Log.i("[Media Store] Adding $type [$filePath] to Media Store with name [$fileName] and MIME [$mime], asking to be stored in: $relativePath") - val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values) - if (isVfsEncrypted) { - Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath") - FileUtils.deleteFile(plainFilePath) + val mediaStoreFilePath = when { + isImage -> { + val values = ContentValues().apply { + put(MediaStore.Images.Media.DISPLAY_NAME, fileName) + put(MediaStore.Images.Media.MIME_TYPE, mime) + } + val collection = MediaStore.Images.Media.getContentUri("external") + addContentValuesToCollection(context, filePath, collection, values) + } + isVideo -> { + val values = ContentValues().apply { + put(MediaStore.Video.Media.TITLE, fileName) + put(MediaStore.Video.Media.DISPLAY_NAME, fileName) + put(MediaStore.Video.Media.MIME_TYPE, mime) + } + val collection = MediaStore.Video.Media.getContentUri("external") + addContentValuesToCollection(context, filePath, collection, values) + } + isAudio -> { + val values = ContentValues().apply { + put(MediaStore.Audio.Media.TITLE, fileName) + put(MediaStore.Audio.Media.DISPLAY_NAME, fileName) + put(MediaStore.Audio.Media.MIME_TYPE, mime) + } + val collection = MediaStore.Audio.Media.getContentUri("external") + addContentValuesToCollection(context, filePath, collection, values) + } + else -> "" } + + if (isContentEncrypted) { + Log.w("[Media Store] Content was encrypted, delete plain version: $filePath") + FileUtils.deleteFile(filePath) + } + if (mediaStoreFilePath.isNotEmpty()) { + Log.i("[Media Store] Exported file path is: $mediaStoreFilePath") content.userData = mediaStoreFilePath return true } + return false } diff --git a/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt index 20ff3c63d..4533658ce 100644 --- a/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt @@ -104,113 +104,101 @@ class Api29Compatibility { } suspend fun addImageToMediaStore(context: Context, content: Content): Boolean { - val plainFilePath = content.exportPlainFile().orEmpty() - val isVfsEncrypted = plainFilePath.isNotEmpty() - Log.w("[Media Store] Content is encrypted, requesting plain file path") - val filePath = if (isVfsEncrypted) plainFilePath else content.filePath - if (filePath == null) { - Log.e("[Media Store] Content doesn't have a file path!") - return false - } - - val appName = AppUtils.getString(R.string.app_name) - val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName" - val fileName = content.name - val mime = "${content.type}/${content.subtype}" - Log.i("[Media Store] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath") - - val values = ContentValues().apply { - put(MediaStore.Images.Media.DISPLAY_NAME, fileName) - put(MediaStore.Images.Media.MIME_TYPE, mime) - put(MediaStore.Images.Media.RELATIVE_PATH, relativePath) - put(MediaStore.Images.Media.IS_PENDING, 1) - } - val collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) - val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values, MediaStore.Images.Media.IS_PENDING) - - if (isVfsEncrypted) { - Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath") - FileUtils.deleteFile(plainFilePath) - } - if (mediaStoreFilePath.isNotEmpty()) { - content.userData = mediaStoreFilePath - return true - } - return false + return addContentToMediaStore(context, content, isImage = true) } suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean { - val plainFilePath = content.exportPlainFile().orEmpty() - val isVfsEncrypted = plainFilePath.isNotEmpty() - Log.w("[Media Store] Content is encrypted, requesting plain file path") - val filePath = if (isVfsEncrypted) plainFilePath else content.filePath - if (filePath == null) { - Log.e("[Media Store] Content doesn't have a file path!") - return false - } - - val appName = AppUtils.getString(R.string.app_name) - val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName" - val fileName = content.name - val mime = "${content.type}/${content.subtype}" - Log.i("[Media Store] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath") - - val values = ContentValues().apply { - put(MediaStore.Video.Media.TITLE, fileName) - put(MediaStore.Video.Media.DISPLAY_NAME, fileName) - put(MediaStore.Video.Media.MIME_TYPE, mime) - put(MediaStore.Video.Media.RELATIVE_PATH, relativePath) - put(MediaStore.Video.Media.IS_PENDING, 1) - } - val collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) - val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values, MediaStore.Video.Media.IS_PENDING) - - if (isVfsEncrypted) { - Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath") - FileUtils.deleteFile(plainFilePath) - } - if (mediaStoreFilePath.isNotEmpty()) { - content.userData = mediaStoreFilePath - return true - } - return false + return addContentToMediaStore(context, content, isVideo = true) } suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean { - val plainFilePath = content.exportPlainFile().orEmpty() - val isVfsEncrypted = plainFilePath.isNotEmpty() - Log.w("[Media Store] Content is encrypted, requesting plain file path") - val filePath = if (isVfsEncrypted) plainFilePath else content.filePath - if (filePath == null) { + return addContentToMediaStore(context, content, isAudio = true) + } + + private suspend fun addContentToMediaStore( + context: Context, + content: Content, + isImage: Boolean = false, + isVideo: Boolean = false, + isAudio: Boolean = false + ): Boolean { + val isContentEncrypted = content.isFileEncrypted + val filePath = if (content.isFileEncrypted) { + val plainFilePath = content.exportPlainFile().orEmpty() + Log.w("[Media Store] Content is encrypted, plain file path is: $plainFilePath") + plainFilePath + } else content.filePath + + if (filePath.isNullOrEmpty()) { Log.e("[Media Store] Content doesn't have a file path!") return false } val appName = AppUtils.getString(R.string.app_name) - val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName" + val directory = when { + isImage -> Environment.DIRECTORY_PICTURES + isVideo -> Environment.DIRECTORY_MOVIES + isAudio -> Environment.DIRECTORY_MUSIC + else -> Environment.DIRECTORY_DOWNLOADS + } + val relativePath = "$directory/$appName" val fileName = content.name val mime = "${content.type}/${content.subtype}" - Log.i("[Media Store] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath") - - val values = ContentValues().apply { - put(MediaStore.Audio.Media.TITLE, fileName) - put(MediaStore.Audio.Media.DISPLAY_NAME, fileName) - put(MediaStore.Audio.Media.MIME_TYPE, mime) - put(MediaStore.Audio.Media.RELATIVE_PATH, relativePath) - put(MediaStore.Audio.Media.IS_PENDING, 1) + val type = when { + isImage -> "image" + isVideo -> "video" + isAudio -> "audio" + else -> "unexpected" } - val collection = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + Log.i("[Media Store] Adding $type [$filePath] to Media Store with name [$fileName] and MIME [$mime], asking to be stored in: $relativePath") - val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values, MediaStore.Audio.Media.IS_PENDING) - - if (isVfsEncrypted) { - Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath") - FileUtils.deleteFile(plainFilePath) + val mediaStoreFilePath = when { + isImage -> { + val values = ContentValues().apply { + put(MediaStore.Images.Media.DISPLAY_NAME, fileName) + put(MediaStore.Images.Media.MIME_TYPE, mime) + put(MediaStore.Images.Media.RELATIVE_PATH, relativePath) + put(MediaStore.Images.Media.IS_PENDING, 1) + } + val collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + addContentValuesToCollection(context, filePath, collection, values, MediaStore.Images.Media.IS_PENDING) + } + isVideo -> { + val values = ContentValues().apply { + put(MediaStore.Video.Media.TITLE, fileName) + put(MediaStore.Video.Media.DISPLAY_NAME, fileName) + put(MediaStore.Video.Media.MIME_TYPE, mime) + put(MediaStore.Video.Media.RELATIVE_PATH, relativePath) + put(MediaStore.Video.Media.IS_PENDING, 1) + } + val collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + addContentValuesToCollection(context, filePath, collection, values, MediaStore.Video.Media.IS_PENDING) + } + isAudio -> { + val values = ContentValues().apply { + put(MediaStore.Audio.Media.TITLE, fileName) + put(MediaStore.Audio.Media.DISPLAY_NAME, fileName) + put(MediaStore.Audio.Media.MIME_TYPE, mime) + put(MediaStore.Audio.Media.RELATIVE_PATH, relativePath) + put(MediaStore.Audio.Media.IS_PENDING, 1) + } + val collection = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) + addContentValuesToCollection(context, filePath, collection, values, MediaStore.Audio.Media.IS_PENDING) + } + else -> "" } + + if (isContentEncrypted) { + Log.w("[Media Store] Content was encrypted, delete plain version: $filePath") + FileUtils.deleteFile(filePath) + } + if (mediaStoreFilePath.isNotEmpty()) { + Log.i("[Media Store] Exported file path is: $mediaStoreFilePath") content.userData = mediaStoreFilePath return true } + return false } diff --git a/app/src/main/java/org/linphone/core/CoreContext.kt b/app/src/main/java/org/linphone/core/CoreContext.kt index 2281155f6..12deefea3 100644 --- a/app/src/main/java/org/linphone/core/CoreContext.kt +++ b/app/src/main/java/org/linphone/core/CoreContext.kt @@ -897,21 +897,21 @@ class CoreContext( when { FileUtils.isExtensionImage(filePath) -> { if (Compatibility.addImageToMediaStore(context, content)) { - Log.i("[Context] Adding image ${content.name} to Media Store terminated") + Log.i("[Context] Successfully exported image [${content.name}] to Media Store") } else { Log.e("[Context] Something went wrong while copying file to Media Store...") } } FileUtils.isExtensionVideo(filePath) -> { if (Compatibility.addVideoToMediaStore(context, content)) { - Log.i("[Context] Adding video ${content.name} to Media Store terminated") + Log.i("[Context] Successfully exported video [${content.name}] to Media Store") } else { Log.e("[Context] Something went wrong while copying file to Media Store...") } } FileUtils.isExtensionAudio(filePath) -> { if (Compatibility.addAudioToMediaStore(context, content)) { - Log.i("[Context] Adding audio ${content.name} to Media Store terminated") + Log.i("[Context] Successfully exported audio [${content.name}] to Media Store") } else { Log.e("[Context] Something went wrong while copying file to Media Store...") }