From 31b38ec70e56e55d8a4bd31d577bdff3bb1051bf Mon Sep 17 00:00:00 2001 From: gavine99 Date: Tue, 18 Feb 2025 21:49:58 +1100 Subject: [PATCH] changes to fix a bug that appeared to be a race condition between deleting mms parts (attachments) and removing the message data from the realm db when deleting a message. there could be attempts to access part data that no longer exists. protected where the access was being attempted. --- .../QKSMS/feature/compose/part/AudioBinder.kt | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/AudioBinder.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/AudioBinder.kt index 44faa595..35619ab9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/AudioBinder.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/part/AudioBinder.kt @@ -35,6 +35,7 @@ import dev.octoshrimpy.quik.common.util.extensions.setBackgroundTint import dev.octoshrimpy.quik.common.util.extensions.setTint import dev.octoshrimpy.quik.common.widget.BubbleImageView import dev.octoshrimpy.quik.extensions.isAudio +import dev.octoshrimpy.quik.extensions.resourceExists import dev.octoshrimpy.quik.feature.compose.MessagesAdapter import dev.octoshrimpy.quik.model.Message import dev.octoshrimpy.quik.model.MmsPart @@ -134,48 +135,50 @@ class AudioBinder @Inject constructor(colors: Colors, private val context: Conte } } else -> { - QkMediaPlayer.reset() // make sure reset before trying to (re-)use + if (part.getUri().resourceExists(context)) { + QkMediaPlayer.reset() // make sure reset before trying to (re-)use - QkMediaPlayer.setOnPreparedListener { - // start media playing - QkMediaPlayer.start() + QkMediaPlayer.setOnPreparedListener { + // start media playing + QkMediaPlayer.start() - uiToPlaying(holder) + uiToPlaying(holder) - // set current view holder and part as active - audioState.apply { - audioState.state = QkMediaPlayer.PlayingState.Playing - partId = part.id - viewHolder = holder + // set current view holder and part as active + audioState.apply { + audioState.state = QkMediaPlayer.PlayingState.Playing + partId = part.id + viewHolder = holder + } + + // start progress bar update timer + startSeekBarUpdateTimer() } - // start progress bar update timer - startSeekBarUpdateTimer() - } + QkMediaPlayer.setOnCompletionListener { // also called on error because we don't have an onerrorlistener + audioState.apply { + // if this part is currently active, set it to stopped and inactive + if ((partId == part.id) && (viewHolder != null)) + uiToStopped(viewHolder!!) - QkMediaPlayer.setOnCompletionListener { // also called on error because we don't have an onerrorlistener - audioState.apply { - // if this part is currently active, set it to stopped and inactive - if ((partId == part.id) && (viewHolder != null)) - uiToStopped(viewHolder!!) - - state = QkMediaPlayer.PlayingState.Stopped - partId = -1 - viewHolder = null + state = QkMediaPlayer.PlayingState.Stopped + partId = -1 + viewHolder = null + } } + + // start the media player play sequence + QkMediaPlayer.setAudioAttributes( + AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) // music, maybe?? could be voice. don't want to use CONTENT_TYPE_UNKNOWN though + .setUsage(AudioAttributes.USAGE_MEDIA) + .build() + ) + + QkMediaPlayer.setDataSource(context, part.getUri()) + + QkMediaPlayer.prepareAsync() } - - // start the media player play sequence - QkMediaPlayer.setAudioAttributes( - AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) // music, maybe?? could be voice. don't want to use CONTENT_TYPE_UNKNOWN though - .setUsage(AudioAttributes.USAGE_MEDIA) - .build() - ) - - QkMediaPlayer.setDataSource(context, part.getUri()) - - QkMediaPlayer.prepareAsync() } } } @@ -234,7 +237,8 @@ class AudioBinder @Inject constructor(colors: Colors, private val context: Conte } MediaMetadataRetriever().use { - it.setDataSource(context, part.getUri()) + if (part.getUri().resourceExists(context)) + it.setDataSource(context, part.getUri()) // metadata title holder.metadataTitle.apply {