[Android] Play queue: Prevent ANR
Geoffrey Métais
git at videolan.org
Fri Dec 27 10:57:48 CET 2019
vlc-android | branch: master | Geoffrey Métais <geoffrey.metais at gmail.com> | Thu Dec 26 11:30:11 2019 +0100| [95c9aa0ae981675f4e0859d7ede1b8dc88c3e383] | committer: Geoffrey Métais
Play queue: Prevent ANR
canSwitchToVideo() calls getVideoTracksCount() which can block main
thread.
> https://code.videolan.org/videolan/vlc-android/commit/95c9aa0ae981675f4e0859d7ede1b8dc88c3e383
---
.../src/org/videolan/vlc/gui/audio/AudioPlayer.kt | 2 +-
.../vlc/gui/tv/audioplayer/AudioPlayerActivity.kt | 32 ++++++++++------------
.../org/videolan/vlc/viewmodels/PlaylistModel.kt | 6 ++--
3 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt b/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt
index 42608cb7a..6109c4fd5 100644
--- a/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt
+++ b/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.kt
@@ -355,7 +355,7 @@ class AudioPlayer : Fragment(), PlaylistAdapter.IPlayer, TextWatcher, IAudioPlay
it.uri, playlistModel.currentMediaPosition)
else if (hasMedia()) {
it.removeFlags(MediaWrapper.MEDIA_FORCE_AUDIO)
- playlistModel.switchToVideo()
+ lifecycleScope.launch(start = CoroutineStart.UNDISPATCHED) { playlistModel.switchToVideo() }
}
}
}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.kt b/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.kt
index 823236c5a..51589e77c 100644
--- a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.kt
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.kt
@@ -38,10 +38,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.ObsoleteCoroutinesApi
-import kotlinx.coroutines.withContext
+import kotlinx.coroutines.*
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.vlc.R
import org.videolan.vlc.databinding.TvAudioPlayerBinding
@@ -113,20 +110,21 @@ class AudioPlayerActivity : BaseTvActivity() {
wasPlaying = state.playing
val mw = model.currentMediaWrapper
- if (mw != null && !mw.hasFlag(MediaWrapper.MEDIA_FORCE_AUDIO) && model.canSwitchToVideo()) {
- model.switchToVideo()
- finish()
- return
+ lifecycleScope.launch {
+ if (model.switchToVideo()) {
+ finish()
+ return at launch
+ }
+ binding.mediaTitle.text = state.title
+ binding.mediaArtist.text = state.artist
+ binding.buttonShuffle.setImageResource(if (shuffling)
+ R.drawable.ic_shuffle_on
+ else
+ R.drawable.ic_shuffle)
+ if (mw == null || TextUtils.equals(currentCoverArt, mw.artworkMrl)) return at launch
+ currentCoverArt = mw.artworkMrl
+ updateBackground()
}
- binding.mediaTitle.text = state.title
- binding.mediaArtist.text = state.artist
- binding.buttonShuffle.setImageResource(if (shuffling)
- R.drawable.ic_shuffle_on
- else
- R.drawable.ic_shuffle)
- if (mw == null || TextUtils.equals(currentCoverArt, mw.artworkMrl)) return
- currentCoverArt = mw.artworkMrl
- updateBackground()
}
private fun updateBackground() = lifecycleScope.launchWhenStarted {
diff --git a/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt b/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt
index ad870843b..e7411c7a9 100644
--- a/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt
+++ b/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt
@@ -23,9 +23,11 @@ package org.videolan.vlc.viewmodels
import androidx.annotation.MainThread
import androidx.fragment.app.Fragment
import androidx.lifecycle.*
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import kotlinx.coroutines.channels.actor
+import kotlinx.coroutines.withContext
import org.videolan.medialibrary.Tools
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.vlc.PlaybackService
@@ -182,7 +184,7 @@ class PlaylistModel : ViewModel(), PlaybackService.Callback by EmptyPBSCallback,
fun load(medialist: List<MediaWrapper>, position: Int) = service?.load(medialist, position)
- fun switchToVideo() : Boolean {
+ suspend fun switchToVideo() : Boolean {
service?.apply {
if (PlaylistManager.hasMedia() && !isVideoPlaying && !hasRenderer()) {
currentMediaWrapper?.run {
@@ -196,7 +198,7 @@ class PlaylistModel : ViewModel(), PlaybackService.Callback by EmptyPBSCallback,
return false
}
- fun canSwitchToVideo() = service?.playlistManager?.player?.canSwitchToVideo() ?: false
+ suspend fun canSwitchToVideo() = withContext(Dispatchers.IO) { service?.playlistManager?.player?.canSwitchToVideo() ?: false }
fun toggleABRepeat() = service?.playlistManager?.toggleABRepeat()
More information about the Android
mailing list