From f7949100a74c40c56b47089636442a80aff9daaa Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 3 May 2021 19:44:11 +0200 Subject: [PATCH] Sent video does not contains duration (#3272) When using the file picker (and not the media picker). Now when using the file picker, we detect the mime type and we send the correct event Also some code duplication --- CHANGES.md | 1 + .../im/vector/lib/multipicker/AudioPicker.kt | 46 +----- .../im/vector/lib/multipicker/CameraPicker.kt | 37 +---- .../lib/multipicker/CameraVideoPicker.kt | 49 +----- .../im/vector/lib/multipicker/FilePicker.kt | 46 ++++-- .../im/vector/lib/multipicker/ImagePicker.kt | 44 +---- .../im/vector/lib/multipicker/MediaPicker.kt | 87 ++-------- .../im/vector/lib/multipicker/VideoPicker.kt | 55 +------ .../multipicker/utils/ContentResolverUtil.kt | 152 ++++++++++++++++++ .../lib/multipicker/utils/MimeTypeUtil.kt | 21 +++ .../features/attachments/AttachmentsMapper.kt | 10 ++ 11 files changed, 237 insertions(+), 311 deletions(-) create mode 100644 multipicker/src/main/java/im/vector/lib/multipicker/utils/ContentResolverUtil.kt create mode 100644 multipicker/src/main/java/im/vector/lib/multipicker/utils/MimeTypeUtil.kt diff --git a/CHANGES.md b/CHANGES.md index 7a596066aa..a48156ac4e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,7 @@ Bugfix 🐛: - Fix wording issue (#3242) - Fix missing sender information after edits (#3184) - Fix read marker not updating automatically (#3267) + - Sent video does not contains duration (#3272) Translations 🗣: - diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt index e8970d72ef..739bda7004 100644 --- a/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt +++ b/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt @@ -18,9 +18,8 @@ package im.vector.lib.multipicker import android.content.Context import android.content.Intent -import android.media.MediaMetadataRetriever -import android.provider.MediaStore import im.vector.lib.multipicker.entity.MultiPickerAudioType +import im.vector.lib.multipicker.utils.toMultiPickerAudioType /** * Audio file picker implementation @@ -32,48 +31,9 @@ class AudioPicker : Picker() { * Returns selected audio files or empty list if user did not select any files. */ override fun getSelectedFiles(context: Context, data: Intent?): List { - val audioList = mutableListOf() - - getSelectedUriList(data).forEach { selectedUri -> - val projection = arrayOf( - MediaStore.Audio.Media.DISPLAY_NAME, - MediaStore.Audio.Media.SIZE - ) - - context.contentResolver.query( - selectedUri, - projection, - null, - null, - null - )?.use { cursor -> - val nameColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME) - val sizeColumn = cursor.getColumnIndex(MediaStore.Audio.Media.SIZE) - - if (cursor.moveToNext()) { - val name = cursor.getString(nameColumn) - val size = cursor.getLong(sizeColumn) - var duration = 0L - - context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd -> - val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource(pfd.fileDescriptor) - duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L - } - - audioList.add( - MultiPickerAudioType( - name, - size, - context.contentResolver.getType(selectedUri), - selectedUri, - duration - ) - ) - } - } + return getSelectedUriList(data).mapNotNull { selectedUri -> + selectedUri.toMultiPickerAudioType(context) } - return audioList } override fun createIntent(): Intent { diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/CameraPicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/CameraPicker.kt index 64df788e53..b1442a56e1 100644 --- a/multipicker/src/main/java/im/vector/lib/multipicker/CameraPicker.kt +++ b/multipicker/src/main/java/im/vector/lib/multipicker/CameraPicker.kt @@ -23,7 +23,7 @@ import android.provider.MediaStore import androidx.activity.result.ActivityResultLauncher import androidx.core.content.FileProvider import im.vector.lib.multipicker.entity.MultiPickerImageType -import im.vector.lib.multipicker.utils.ImageUtils +import im.vector.lib.multipicker.utils.toMultiPickerImageType import java.io.File import java.text.SimpleDateFormat import java.util.Date @@ -54,40 +54,7 @@ class CameraPicker { * or user cancelled the operation. */ fun getTakenPhoto(context: Context, photoUri: Uri): MultiPickerImageType? { - val projection = arrayOf( - MediaStore.Images.Media.DISPLAY_NAME, - MediaStore.Images.Media.SIZE - ) - - context.contentResolver.query( - photoUri, - projection, - null, - null, - null - )?.use { cursor -> - val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) - val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE) - - if (cursor.moveToNext()) { - val name = cursor.getString(nameColumn) - val size = cursor.getLong(sizeColumn) - - val bitmap = ImageUtils.getBitmap(context, photoUri) - val orientation = ImageUtils.getOrientation(context, photoUri) - - return MultiPickerImageType( - name, - size, - context.contentResolver.getType(photoUri), - photoUri, - bitmap?.width ?: 0, - bitmap?.height ?: 0, - orientation - ) - } - } - return null + return photoUri.toMultiPickerImageType(context) } private fun createIntent(): Intent { diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/CameraVideoPicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/CameraVideoPicker.kt index e7faf9e83c..76342b6e2e 100644 --- a/multipicker/src/main/java/im/vector/lib/multipicker/CameraVideoPicker.kt +++ b/multipicker/src/main/java/im/vector/lib/multipicker/CameraVideoPicker.kt @@ -18,12 +18,12 @@ package im.vector.lib.multipicker import android.content.Context import android.content.Intent -import android.media.MediaMetadataRetriever import android.net.Uri import android.provider.MediaStore import androidx.activity.result.ActivityResultLauncher import androidx.core.content.FileProvider import im.vector.lib.multipicker.entity.MultiPickerVideoType +import im.vector.lib.multipicker.utils.toMultiPickerVideoType import java.io.File import java.text.SimpleDateFormat import java.util.Date @@ -54,52 +54,7 @@ class CameraVideoPicker { * or user cancelled the operation. */ fun getTakenVideo(context: Context, videoUri: Uri): MultiPickerVideoType? { - val projection = arrayOf( - MediaStore.Images.Media.DISPLAY_NAME, - MediaStore.Images.Media.SIZE, - MediaStore.Images.Media.MIME_TYPE - ) - - context.contentResolver.query( - videoUri, - projection, - null, - null, - null - )?.use { cursor -> - val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) - val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE) - - if (cursor.moveToNext()) { - val name = cursor.getString(nameColumn) - val size = cursor.getLong(sizeColumn) - var duration = 0L - var width = 0 - var height = 0 - var orientation = 0 - - context.contentResolver.openFileDescriptor(videoUri, "r")?.use { pfd -> - val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource(pfd.fileDescriptor) - duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L - width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0 - height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0 - orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0 - } - - return MultiPickerVideoType( - name, - size, - context.contentResolver.getType(videoUri), - videoUri, - width, - height, - orientation, - duration - ) - } - } - return null + return videoUri.toMultiPickerVideoType(context) } private fun createIntent(): Intent { diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt index 39bd93d03e..ec98152aa7 100644 --- a/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt +++ b/multipicker/src/main/java/im/vector/lib/multipicker/FilePicker.kt @@ -19,41 +19,55 @@ package im.vector.lib.multipicker import android.content.Context import android.content.Intent import android.provider.OpenableColumns +import im.vector.lib.multipicker.entity.MultiPickerBaseType import im.vector.lib.multipicker.entity.MultiPickerFileType +import im.vector.lib.multipicker.utils.isMimeTypeAudio +import im.vector.lib.multipicker.utils.isMimeTypeImage +import im.vector.lib.multipicker.utils.isMimeTypeVideo +import im.vector.lib.multipicker.utils.toMultiPickerAudioType +import im.vector.lib.multipicker.utils.toMultiPickerImageType +import im.vector.lib.multipicker.utils.toMultiPickerVideoType /** * Implementation of selecting any type of files */ -class FilePicker : Picker() { +class FilePicker : Picker() { /** * Call this function from onActivityResult(int, int, Intent). * Returns selected files or empty list if user did not select any files. */ - override fun getSelectedFiles(context: Context, data: Intent?): List { - val fileList = mutableListOf() + override fun getSelectedFiles(context: Context, data: Intent?): List { + return getSelectedUriList(data).mapNotNull { selectedUri -> + val type = context.contentResolver.getType(selectedUri) - getSelectedUriList(data).forEach { selectedUri -> - context.contentResolver.query(selectedUri, null, null, null, null) - ?.use { cursor -> - val nameColumn = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) - val sizeColumn = cursor.getColumnIndex(OpenableColumns.SIZE) - if (cursor.moveToFirst()) { - val name = cursor.getString(nameColumn) - val size = cursor.getLong(sizeColumn) + when { + type.isMimeTypeVideo() -> selectedUri.toMultiPickerVideoType(context) + type.isMimeTypeImage() -> selectedUri.toMultiPickerImageType(context) + type.isMimeTypeAudio() -> selectedUri.toMultiPickerAudioType(context) + else -> { + // Other files + context.contentResolver.query(selectedUri, null, null, null, null) + ?.use { cursor -> + val nameColumn = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) + val sizeColumn = cursor.getColumnIndex(OpenableColumns.SIZE) + if (cursor.moveToFirst()) { + val name = cursor.getString(nameColumn) + val size = cursor.getLong(sizeColumn) - fileList.add( MultiPickerFileType( name, size, context.contentResolver.getType(selectedUri), selectedUri ) - ) - } - } + } else { + null + } + } + } + } } - return fileList } override fun createIntent(): Intent { diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/ImagePicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/ImagePicker.kt index ce73058039..4cc2352109 100644 --- a/multipicker/src/main/java/im/vector/lib/multipicker/ImagePicker.kt +++ b/multipicker/src/main/java/im/vector/lib/multipicker/ImagePicker.kt @@ -18,9 +18,8 @@ package im.vector.lib.multipicker import android.content.Context import android.content.Intent -import android.provider.MediaStore import im.vector.lib.multipicker.entity.MultiPickerImageType -import im.vector.lib.multipicker.utils.ImageUtils +import im.vector.lib.multipicker.utils.toMultiPickerImageType /** * Image Picker implementation @@ -32,46 +31,9 @@ class ImagePicker : Picker() { * Returns selected image files or empty list if user did not select any files. */ override fun getSelectedFiles(context: Context, data: Intent?): List { - val imageList = mutableListOf() - - getSelectedUriList(data).forEach { selectedUri -> - val projection = arrayOf( - MediaStore.Images.Media.DISPLAY_NAME, - MediaStore.Images.Media.SIZE - ) - - context.contentResolver.query( - selectedUri, - projection, - null, - null, - null - )?.use { cursor -> - val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) - val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE) - - if (cursor.moveToNext()) { - val name = cursor.getString(nameColumn) - val size = cursor.getLong(sizeColumn) - - val bitmap = ImageUtils.getBitmap(context, selectedUri) - val orientation = ImageUtils.getOrientation(context, selectedUri) - - imageList.add( - MultiPickerImageType( - name, - size, - context.contentResolver.getType(selectedUri), - selectedUri, - bitmap?.width ?: 0, - bitmap?.height ?: 0, - orientation - ) - ) - } - } + return getSelectedUriList(data).mapNotNull { selectedUri -> + selectedUri.toMultiPickerImageType(context) } - return imageList } override fun createIntent(): Intent { diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/MediaPicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/MediaPicker.kt index 76929b52bd..c58abde694 100644 --- a/multipicker/src/main/java/im/vector/lib/multipicker/MediaPicker.kt +++ b/multipicker/src/main/java/im/vector/lib/multipicker/MediaPicker.kt @@ -18,12 +18,10 @@ package im.vector.lib.multipicker import android.content.Context import android.content.Intent -import android.media.MediaMetadataRetriever -import android.provider.MediaStore import im.vector.lib.multipicker.entity.MultiPickerBaseMediaType -import im.vector.lib.multipicker.entity.MultiPickerImageType -import im.vector.lib.multipicker.entity.MultiPickerVideoType -import im.vector.lib.multipicker.utils.ImageUtils +import im.vector.lib.multipicker.utils.isMimeTypeVideo +import im.vector.lib.multipicker.utils.toMultiPickerImageType +import im.vector.lib.multipicker.utils.toMultiPickerVideoType /** * Image/Video Picker implementation @@ -35,79 +33,16 @@ class MediaPicker : Picker() { * Returns selected image/video files or empty list if user did not select any files. */ override fun getSelectedFiles(context: Context, data: Intent?): List { - val mediaList = mutableListOf() + return getSelectedUriList(data).mapNotNull { selectedUri -> + val mimeType = context.contentResolver.getType(selectedUri) - getSelectedUriList(data).forEach { selectedUri -> - val projection = arrayOf( - MediaStore.Images.Media.DISPLAY_NAME, - MediaStore.Images.Media.SIZE, - MediaStore.Images.Media.MIME_TYPE - ) - - context.contentResolver.query( - selectedUri, - projection, - null, - null, - null - )?.use { cursor -> - val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) - val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE) - val mimeTypeColumn = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE) - - if (cursor.moveToNext()) { - val name = cursor.getString(nameColumn) - val size = cursor.getLong(sizeColumn) - val mimeType = cursor.getString(mimeTypeColumn) - - if (mimeType.isMimeTypeVideo()) { - var duration = 0L - var width = 0 - var height = 0 - var orientation = 0 - - context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd -> - val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource(pfd.fileDescriptor) - duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L - width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0 - height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0 - orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0 - } - - mediaList.add( - MultiPickerVideoType( - name, - size, - context.contentResolver.getType(selectedUri), - selectedUri, - width, - height, - orientation, - duration - ) - ) - } else { - // Assume it's an image - val bitmap = ImageUtils.getBitmap(context, selectedUri) - val orientation = ImageUtils.getOrientation(context, selectedUri) - - mediaList.add( - MultiPickerImageType( - name, - size, - context.contentResolver.getType(selectedUri), - selectedUri, - bitmap?.width ?: 0, - bitmap?.height ?: 0, - orientation - ) - ) - } - } + if (mimeType.isMimeTypeVideo()) { + selectedUri.toMultiPickerVideoType(context) + } else { + // Assume it's an image + selectedUri.toMultiPickerImageType(context) } } - return mediaList } override fun createIntent(): Intent { @@ -119,6 +54,4 @@ class MediaPicker : Picker() { putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes) } } - - private fun String?.isMimeTypeVideo() = this?.startsWith("video/") == true } diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt index dada9ac5bd..6b6bc52c1b 100644 --- a/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt +++ b/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt @@ -18,9 +18,8 @@ package im.vector.lib.multipicker import android.content.Context import android.content.Intent -import android.media.MediaMetadataRetriever -import android.provider.MediaStore import im.vector.lib.multipicker.entity.MultiPickerVideoType +import im.vector.lib.multipicker.utils.toMultiPickerVideoType /** * Video Picker implementation @@ -32,57 +31,9 @@ class VideoPicker : Picker() { * Returns selected video files or empty list if user did not select any files. */ override fun getSelectedFiles(context: Context, data: Intent?): List { - val videoList = mutableListOf() - - getSelectedUriList(data).forEach { selectedUri -> - val projection = arrayOf( - MediaStore.Video.Media.DISPLAY_NAME, - MediaStore.Video.Media.SIZE - ) - - context.contentResolver.query( - selectedUri, - projection, - null, - null, - null - )?.use { cursor -> - val nameColumn = cursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME) - val sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE) - - if (cursor.moveToNext()) { - val name = cursor.getString(nameColumn) - val size = cursor.getLong(sizeColumn) - var duration = 0L - var width = 0 - var height = 0 - var orientation = 0 - - context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd -> - val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource(pfd.fileDescriptor) - duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L - width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0 - height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0 - orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0 - } - - videoList.add( - MultiPickerVideoType( - name, - size, - context.contentResolver.getType(selectedUri), - selectedUri, - width, - height, - orientation, - duration - ) - ) - } - } + return getSelectedUriList(data).mapNotNull { selectedUri -> + selectedUri.toMultiPickerVideoType(context) } - return videoList } override fun createIntent(): Intent { diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/utils/ContentResolverUtil.kt b/multipicker/src/main/java/im/vector/lib/multipicker/utils/ContentResolverUtil.kt new file mode 100644 index 0000000000..a1982b0bbc --- /dev/null +++ b/multipicker/src/main/java/im/vector/lib/multipicker/utils/ContentResolverUtil.kt @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.lib.multipicker.utils + +import android.content.Context +import android.media.MediaMetadataRetriever +import android.net.Uri +import android.provider.MediaStore +import im.vector.lib.multipicker.entity.MultiPickerAudioType +import im.vector.lib.multipicker.entity.MultiPickerImageType +import im.vector.lib.multipicker.entity.MultiPickerVideoType + +internal fun Uri.toMultiPickerImageType(context: Context): MultiPickerImageType? { + val projection = arrayOf( + MediaStore.Images.Media.DISPLAY_NAME, + MediaStore.Images.Media.SIZE + ) + + return context.contentResolver.query( + this, + projection, + null, + null, + null + )?.use { cursor -> + val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) + val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE) + + if (cursor.moveToNext()) { + val name = cursor.getString(nameColumn) + val size = cursor.getLong(sizeColumn) + + val bitmap = ImageUtils.getBitmap(context, this) + val orientation = ImageUtils.getOrientation(context, this) + + MultiPickerImageType( + name, + size, + context.contentResolver.getType(this), + this, + bitmap?.width ?: 0, + bitmap?.height ?: 0, + orientation + ) + } else { + null + } + } +} + +internal fun Uri.toMultiPickerVideoType(context: Context): MultiPickerVideoType? { + val projection = arrayOf( + MediaStore.Video.Media.DISPLAY_NAME, + MediaStore.Video.Media.SIZE + ) + + return context.contentResolver.query( + this, + projection, + null, + null, + null + )?.use { cursor -> + val nameColumn = cursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME) + val sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE) + + if (cursor.moveToNext()) { + val name = cursor.getString(nameColumn) + val size = cursor.getLong(sizeColumn) + var duration = 0L + var width = 0 + var height = 0 + var orientation = 0 + + context.contentResolver.openFileDescriptor(this, "r")?.use { pfd -> + val mediaMetadataRetriever = MediaMetadataRetriever() + mediaMetadataRetriever.setDataSource(pfd.fileDescriptor) + duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L + width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0 + height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0 + orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0 + } + + MultiPickerVideoType( + name, + size, + context.contentResolver.getType(this), + this, + width, + height, + orientation, + duration + ) + } else { + null + } + } +} + +internal fun Uri.toMultiPickerAudioType(context: Context): MultiPickerAudioType? { + val projection = arrayOf( + MediaStore.Audio.Media.DISPLAY_NAME, + MediaStore.Audio.Media.SIZE + ) + + return context.contentResolver.query( + this, + projection, + null, + null, + null + )?.use { cursor -> + val nameColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME) + val sizeColumn = cursor.getColumnIndex(MediaStore.Audio.Media.SIZE) + + if (cursor.moveToNext()) { + val name = cursor.getString(nameColumn) + val size = cursor.getLong(sizeColumn) + var duration = 0L + + context.contentResolver.openFileDescriptor(this, "r")?.use { pfd -> + val mediaMetadataRetriever = MediaMetadataRetriever() + mediaMetadataRetriever.setDataSource(pfd.fileDescriptor) + duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L + } + + MultiPickerAudioType( + name, + size, + context.contentResolver.getType(this), + this, + duration + ) + } else { + null + } + } +} diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/utils/MimeTypeUtil.kt b/multipicker/src/main/java/im/vector/lib/multipicker/utils/MimeTypeUtil.kt new file mode 100644 index 0000000000..fc82d03dc5 --- /dev/null +++ b/multipicker/src/main/java/im/vector/lib/multipicker/utils/MimeTypeUtil.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.lib.multipicker.utils + +internal fun String?.isMimeTypeImage() = this?.startsWith("image/") == true +internal fun String?.isMimeTypeVideo() = this?.startsWith("video/") == true +internal fun String?.isMimeTypeAudio() = this?.startsWith("audio/") == true diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentsMapper.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentsMapper.kt index 7f8021ea72..2229455dfe 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentsMapper.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentsMapper.kt @@ -70,6 +70,16 @@ private fun MultiPickerBaseType.mapType(): ContentAttachmentData.Type { } } +fun MultiPickerBaseType.toContentAttachmentData(): ContentAttachmentData { + return when (this) { + is MultiPickerImageType -> toContentAttachmentData() + is MultiPickerVideoType -> toContentAttachmentData() + is MultiPickerAudioType -> toContentAttachmentData() + is MultiPickerFileType -> toContentAttachmentData() + else -> throw IllegalStateException("Unknown file type") + } +} + fun MultiPickerBaseMediaType.toContentAttachmentData(): ContentAttachmentData { return when (this) { is MultiPickerImageType -> toContentAttachmentData()