From fb1b3f300932ca23bcbdbcebc12ae330953fe386 Mon Sep 17 00:00:00 2001 From: mayurikhin Date: Mon, 5 Aug 2024 22:18:18 +0530 Subject: [PATCH 1/3] Support playback of video through network. Modify the MediaMetadataRetriever data sources to support remote urls. Move this to an IO Thread. --- app/src/main/AndroidManifest.xml | 1 + .../samples/socialite/ui/chat/ChatScreen.kt | 9 +++++- .../socialite/ui/home/timeline/Timeline.kt | 28 +++++++++++++------ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 409c12af..6e4a6d56 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,6 +27,7 @@ + Unit) { val bitmapState = produceState(initialValue = null) { withContext(Dispatchers.IO) { val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource(context, Uri.parse(videoUri)) + + //Locally saved files + if (videoUri.contains("content://")) { + mediaMetadataRetriever.setDataSource(context, Uri.parse(videoUri),) + } else { + //Remote url + mediaMetadataRetriever.setDataSource(videoUri, HashMap()) + } // Return any frame that the framework considers representative of a valid frame value = mediaMetadataRetriever.frameAtTime } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt index 231368c6..74124196 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt @@ -41,7 +41,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.State import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment @@ -66,6 +68,8 @@ import coil.request.ImageRequest import com.google.android.samples.socialite.R import com.google.android.samples.socialite.ui.rememberIconPainter import kotlin.math.absoluteValue +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext @Composable fun Timeline( @@ -238,15 +242,23 @@ fun MetadataOverlay(modifier: Modifier, mediaItem: TimelineMediaItem) { ) { if (mediaItem.type == TimelineMediaType.VIDEO) { val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource( - LocalContext.current, - Uri.parse(mediaItem.uri), - ) + val context = LocalContext.current.applicationContext - val duration = - mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) - ?.toLong() - duration?.let { + val duration: State = produceState(initialValue = null) { + withContext(Dispatchers.IO) { + //Locally saved files + if (mediaItem.uri.contains("content://")) { + mediaMetadataRetriever.setDataSource(context, Uri.parse(mediaItem.uri),) + } else { + //Remote url + mediaMetadataRetriever.setDataSource(mediaItem.uri, HashMap()) + } + value = + mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) + ?.toLong() + } + } + duration.value?.let { val seconds = it / 1000L val minutes = seconds / 60L Box( From 4efcf0a1503f01f88f8198087d0df61b2447f4e0 Mon Sep 17 00:00:00 2001 From: mayurikhin Date: Mon, 5 Aug 2024 22:18:18 +0530 Subject: [PATCH 2/3] Support playback of video through network. Modify the MediaMetadataRetriever data sources to support remote urls. Move this to an IO Thread.Switch logic to check for https for remote url --- app/src/main/AndroidManifest.xml | 1 + .../samples/socialite/ui/chat/ChatScreen.kt | 8 +++++- .../socialite/ui/home/timeline/Timeline.kt | 27 +++++++++++++------ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 409c12af..6e4a6d56 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,6 +27,7 @@ + Unit) { val bitmapState = produceState(initialValue = null) { withContext(Dispatchers.IO) { val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource(context, Uri.parse(videoUri)) + + // Remote url + if (videoUri.contains("https://")) { + mediaMetadataRetriever.setDataSource(videoUri, HashMap()) + } else { // Locally saved files + mediaMetadataRetriever.setDataSource(context, Uri.parse(videoUri)) + } // Return any frame that the framework considers representative of a valid frame value = mediaMetadataRetriever.frameAtTime } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt index 231368c6..df034785 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt @@ -41,7 +41,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.State import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment @@ -66,6 +68,8 @@ import coil.request.ImageRequest import com.google.android.samples.socialite.R import com.google.android.samples.socialite.ui.rememberIconPainter import kotlin.math.absoluteValue +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext @Composable fun Timeline( @@ -238,15 +242,22 @@ fun MetadataOverlay(modifier: Modifier, mediaItem: TimelineMediaItem) { ) { if (mediaItem.type == TimelineMediaType.VIDEO) { val mediaMetadataRetriever = MediaMetadataRetriever() - mediaMetadataRetriever.setDataSource( - LocalContext.current, - Uri.parse(mediaItem.uri), - ) + val context = LocalContext.current.applicationContext - val duration = - mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) - ?.toLong() - duration?.let { + val duration: State = produceState(initialValue = null) { + withContext(Dispatchers.IO) { + // Remote url + if (mediaItem.uri.contains("https://")) { + mediaMetadataRetriever.setDataSource(mediaItem.uri, HashMap()) + } else { // Locally saved files + mediaMetadataRetriever.setDataSource(context, Uri.parse(mediaItem.uri)) + } + value = + mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) + ?.toLong() + } + } + duration.value?.let { val seconds = it / 1000L val minutes = seconds / 60L Box( From f4aedca5281a4efd7080ca959143d91386067b40 Mon Sep 17 00:00:00 2001 From: mayurikhin Date: Tue, 6 Aug 2024 11:35:19 +0530 Subject: [PATCH 3/3] Adding comments as to why IO thread was used --- .../com/google/android/samples/socialite/ui/chat/ChatScreen.kt | 2 ++ .../android/samples/socialite/ui/home/timeline/Timeline.kt | 1 + 2 files changed, 3 insertions(+) diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt b/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt index c65f25c0..95bcce74 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt @@ -379,6 +379,8 @@ private fun MessageBubble( @Composable private fun VideoMessagePreview(videoUri: String, onClick: () -> Unit) { val context = LocalContext.current.applicationContext + + // Running on an IO thread for loading metadata from remote urls to reduce lag time val bitmapState = produceState(initialValue = null) { withContext(Dispatchers.IO) { val mediaMetadataRetriever = MediaMetadataRetriever() diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt index df034785..87446b22 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/timeline/Timeline.kt @@ -244,6 +244,7 @@ fun MetadataOverlay(modifier: Modifier, mediaItem: TimelineMediaItem) { val mediaMetadataRetriever = MediaMetadataRetriever() val context = LocalContext.current.applicationContext + // Running on an IO thread for loading metadata from remote urls to reduce lag time val duration: State = produceState(initialValue = null) { withContext(Dispatchers.IO) { // Remote url