Remove SilentBackgroundTask.kt

This commit is contained in:
tzugen 2021-11-13 12:57:14 +01:00
parent 45e9728e0f
commit ed152fa52a
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
7 changed files with 158 additions and 242 deletions

View File

@ -59,7 +59,6 @@
<ID>NestedBlockDepth:DownloadFile.kt$DownloadFile.DownloadTask$override fun execute()</ID> <ID>NestedBlockDepth:DownloadFile.kt$DownloadFile.DownloadTask$override fun execute()</ID>
<ID>NestedBlockDepth:DownloadHandler.kt$DownloadHandler$private fun downloadRecursively( fragment: Fragment, id: String, name: String?, isShare: Boolean, isDirectory: Boolean, save: Boolean, append: Boolean, autoPlay: Boolean, shuffle: Boolean, background: Boolean, playNext: Boolean, unpin: Boolean, isArtist: Boolean )</ID> <ID>NestedBlockDepth:DownloadHandler.kt$DownloadHandler$private fun downloadRecursively( fragment: Fragment, id: String, name: String?, isShare: Boolean, isDirectory: Boolean, save: Boolean, append: Boolean, autoPlay: Boolean, shuffle: Boolean, background: Boolean, playNext: Boolean, unpin: Boolean, isArtist: Boolean )</ID>
<ID>NestedBlockDepth:MediaPlayerService.kt$MediaPlayerService$private fun setupOnSongCompletedHandler()</ID> <ID>NestedBlockDepth:MediaPlayerService.kt$MediaPlayerService$private fun setupOnSongCompletedHandler()</ID>
<ID>ReturnCount:CommunicationErrorHandler.kt$CommunicationErrorHandler.Companion$fun getErrorMessage(error: Throwable, context: Context): String</ID>
<ID>ReturnCount:ServerRowAdapter.kt$ServerRowAdapter$ private fun popupMenuItemClick(menuItem: MenuItem, position: Int): Boolean</ID> <ID>ReturnCount:ServerRowAdapter.kt$ServerRowAdapter$ private fun popupMenuItemClick(menuItem: MenuItem, position: Int): Boolean</ID>
<ID>ReturnCount:TrackCollectionFragment.kt$TrackCollectionFragment$override fun onContextItemSelected(menuItem: MenuItem): Boolean</ID> <ID>ReturnCount:TrackCollectionFragment.kt$TrackCollectionFragment$override fun onContextItemSelected(menuItem: MenuItem): Boolean</ID>
<ID>TooGenericExceptionCaught:DownloadFile.kt$DownloadFile$e: Exception</ID> <ID>TooGenericExceptionCaught:DownloadFile.kt$DownloadFile$e: Exception</ID>
@ -74,7 +73,6 @@
<ID>TooManyFunctions:MediaPlayerService.kt$MediaPlayerService : Service</ID> <ID>TooManyFunctions:MediaPlayerService.kt$MediaPlayerService : Service</ID>
<ID>TooManyFunctions:RESTMusicService.kt$RESTMusicService : MusicService</ID> <ID>TooManyFunctions:RESTMusicService.kt$RESTMusicService : MusicService</ID>
<ID>TooManyFunctions:TrackCollectionFragment.kt$TrackCollectionFragment : Fragment</ID> <ID>TooManyFunctions:TrackCollectionFragment.kt$TrackCollectionFragment : Fragment</ID>
<ID>UtilityClassWithPublicConstructor:CommunicationErrorHandler.kt$CommunicationErrorHandler</ID>
<ID>UtilityClassWithPublicConstructor:FragmentTitle.kt$FragmentTitle</ID> <ID>UtilityClassWithPublicConstructor:FragmentTitle.kt$FragmentTitle</ID>
</CurrentIssues> </CurrentIssues>
</SmellBaseline> </SmellBaseline>

View File

@ -20,7 +20,7 @@ package org.moire.ultrasonic.util;
import android.app.Activity; import android.app.Activity;
import android.os.Handler; import android.os.Handler;
import org.moire.ultrasonic.service.CommunicationErrorHandler; import org.moire.ultrasonic.service.CommunicationErrorUtil;
/** /**
* @author Sindre Mehus * @author Sindre Mehus
@ -54,12 +54,12 @@ public abstract class BackgroundTask<T> implements ProgressListener
protected void error(Throwable error) protected void error(Throwable error)
{ {
CommunicationErrorHandler.Companion.handleError(error, activity); CommunicationErrorUtil.Companion.handleError(error, activity);
} }
protected String getErrorMessage(Throwable error) protected String getErrorMessage(Throwable error)
{ {
return CommunicationErrorHandler.Companion.getErrorMessage(error, activity); return CommunicationErrorUtil.Companion.getErrorMessage(error, activity);
} }
@Override @Override

View File

@ -18,7 +18,7 @@ import org.koin.core.component.inject
import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.data.ServerSetting import org.moire.ultrasonic.data.ServerSetting
import org.moire.ultrasonic.domain.MusicFolder import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.service.CommunicationErrorHandler import org.moire.ultrasonic.service.CommunicationErrorUtil
import org.moire.ultrasonic.service.MusicService import org.moire.ultrasonic.service.MusicService
import org.moire.ultrasonic.service.MusicServiceFactory import org.moire.ultrasonic.service.MusicServiceFactory
import org.moire.ultrasonic.util.Settings import org.moire.ultrasonic.util.Settings
@ -94,7 +94,7 @@ open class GenericListModel(application: Application) :
private fun handleException(exception: Exception, context: Context) { private fun handleException(exception: Exception, context: Context) {
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
CommunicationErrorHandler.handleError(exception, context) CommunicationErrorUtil.handleError(exception, context)
} }
} }

View File

@ -51,6 +51,8 @@ import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
@ -65,6 +67,7 @@ import org.moire.ultrasonic.domain.RepeatMode
import org.moire.ultrasonic.featureflags.Feature import org.moire.ultrasonic.featureflags.Feature
import org.moire.ultrasonic.featureflags.FeatureStorage import org.moire.ultrasonic.featureflags.FeatureStorage
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
import org.moire.ultrasonic.service.CommunicationErrorUtil
import org.moire.ultrasonic.service.DownloadFile import org.moire.ultrasonic.service.DownloadFile
import org.moire.ultrasonic.service.LocalMediaPlayer import org.moire.ultrasonic.service.LocalMediaPlayer
import org.moire.ultrasonic.service.MediaPlayerController import org.moire.ultrasonic.service.MediaPlayerController
@ -76,19 +79,18 @@ import org.moire.ultrasonic.subsonic.ShareHandler
import org.moire.ultrasonic.util.CancellationToken import org.moire.ultrasonic.util.CancellationToken
import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.Settings import org.moire.ultrasonic.util.Settings
import org.moire.ultrasonic.util.SilentBackgroundTask
import org.moire.ultrasonic.util.Util import org.moire.ultrasonic.util.Util
import org.moire.ultrasonic.view.AutoRepeatButton import org.moire.ultrasonic.view.AutoRepeatButton
import org.moire.ultrasonic.view.SongListAdapter import org.moire.ultrasonic.view.SongListAdapter
import org.moire.ultrasonic.view.VisualizerView import org.moire.ultrasonic.view.VisualizerView
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.CancellationException
/** /**
* Contains the Music Player screen of Ultrasonic with playback controls and the playlist * Contains the Music Player screen of Ultrasonic with playback controls and the playlist
* *
* TODO: This class was more or less straight converted from Java legacy code. * TODO: This class was more or less straight converted from Java legacy code.
* There are many places where further cleanup would be nice. * There are many places where further cleanup would be nice.
* The usage of threads and SilentBackgroundTask can be replaced with Coroutines.
*/ */
@Suppress("LargeClass", "TooManyFunctions", "MagicNumber") @Suppress("LargeClass", "TooManyFunctions", "MagicNumber")
class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinComponent { class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinComponent {
@ -112,8 +114,9 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
private lateinit var executorService: ScheduledExecutorService private lateinit var executorService: ScheduledExecutorService
private var currentPlaying: DownloadFile? = null private var currentPlaying: DownloadFile? = null
private var currentSong: MusicDirectory.Entry? = null private var currentSong: MusicDirectory.Entry? = null
private var onProgressChangedTask: SilentBackgroundTask<Void?>? = null private var onProgressChangedTask: Job? = null
private var rxBusSubscription: Disposable? = null private var rxBusSubscription: Disposable? = null
private val scope: CoroutineScope = viewLifecycleOwner.lifecycleScope
// Views and UI Elements // Views and UI Elements
private lateinit var visualizerViewLayout: LinearLayout private lateinit var visualizerViewLayout: LinearLayout
@ -233,17 +236,11 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
previousButton.setOnClickListener { previousButton.setOnClickListener {
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable() networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
object : SilentBackgroundTask<Void?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
override fun doInBackground(): Void? { mediaPlayerController.previous()
mediaPlayerController.previous() onCurrentChanged()
return null onSliderProgressChanged()
} }
override fun done(result: Void?) {
onCurrentChanged()
onSliderProgressChanged()
}
}.execute()
} }
previousButton.setOnRepeatListener { previousButton.setOnRepeatListener {
@ -253,19 +250,11 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
nextButton.setOnClickListener { nextButton.setOnClickListener {
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable() networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
object : SilentBackgroundTask<Boolean?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
override fun doInBackground(): Boolean { mediaPlayerController.next()
mediaPlayerController.next() onCurrentChanged()
return true onSliderProgressChanged()
} }
override fun done(result: Boolean?) {
if (result == true) {
onCurrentChanged()
onSliderProgressChanged()
}
}
}.execute()
} }
nextButton.setOnRepeatListener { nextButton.setOnRepeatListener {
@ -273,44 +262,26 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
changeProgress(incrementTime) changeProgress(incrementTime)
} }
pauseButton.setOnClickListener { pauseButton.setOnClickListener {
object : SilentBackgroundTask<Void?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
override fun doInBackground(): Void? { mediaPlayerController.pause()
mediaPlayerController.pause() onCurrentChanged()
return null onSliderProgressChanged()
} }
override fun done(result: Void?) {
onCurrentChanged()
onSliderProgressChanged()
}
}.execute()
} }
stopButton.setOnClickListener { stopButton.setOnClickListener {
object : SilentBackgroundTask<Void?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
override fun doInBackground(): Void? { mediaPlayerController.reset()
mediaPlayerController.reset() onCurrentChanged()
return null onSliderProgressChanged()
} }
override fun done(result: Void?) {
onCurrentChanged()
onSliderProgressChanged()
}
}.execute()
} }
startButton.setOnClickListener { startButton.setOnClickListener {
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable() networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
object : SilentBackgroundTask<Void?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
override fun doInBackground(): Void? { start()
start() onCurrentChanged()
return null onSliderProgressChanged()
} }
override fun done(result: Void?) {
onCurrentChanged()
onSliderProgressChanged()
}
}.execute()
} }
shuffleButton.setOnClickListener { shuffleButton.setOnClickListener {
mediaPlayerController.shuffle() mediaPlayerController.shuffle()
@ -338,16 +309,10 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
progressBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { progressBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onStopTrackingTouch(seekBar: SeekBar) { override fun onStopTrackingTouch(seekBar: SeekBar) {
object : SilentBackgroundTask<Void?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
override fun doInBackground(): Void? { mediaPlayerController.seekTo(progressBar.progress)
mediaPlayerController.seekTo(progressBar.progress) onSliderProgressChanged()
return null }
}
override fun done(result: Void?) {
onSliderProgressChanged()
}
}.execute()
} }
override fun onStartTrackingTouch(seekBar: SeekBar) {} override fun onStartTrackingTouch(seekBar: SeekBar) {}
@ -356,17 +321,11 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
playlistView.setOnItemClickListener { _, _, position, _ -> playlistView.setOnItemClickListener { _, _, position, _ ->
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable() networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
object : SilentBackgroundTask<Void?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
override fun doInBackground(): Void? { mediaPlayerController.play(position)
mediaPlayerController.play(position) onCurrentChanged()
return null onSliderProgressChanged()
} }
override fun done(result: Void?) {
onCurrentChanged()
onSliderProgressChanged()
}
}.execute()
} }
registerForContextMenu(playlistView) registerForContextMenu(playlistView)
@ -429,7 +388,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
} }
// Query the Jukebox state off-thread // Query the Jukebox state off-thread
viewLifecycleOwner.lifecycleScope.launch { scope.launch(CommunicationErrorUtil.handler(context)) {
try { try {
jukeboxAvailable = mediaPlayerController.isJukeboxAvailable jukeboxAvailable = mediaPlayerController.isJukeboxAvailable
} catch (all: Exception) { } catch (all: Exception) {
@ -819,33 +778,28 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
private fun savePlaylistInBackground(playlistName: String) { private fun savePlaylistInBackground(playlistName: String) {
Util.toast(context, resources.getString(R.string.download_playlist_saving, playlistName)) Util.toast(context, resources.getString(R.string.download_playlist_saving, playlistName))
mediaPlayerController.suggestedPlaylistName = playlistName mediaPlayerController.suggestedPlaylistName = playlistName
object : SilentBackgroundTask<Void?>(activity) {
@Throws(Throwable::class)
override fun doInBackground(): Void? {
val entries: MutableList<MusicDirectory.Entry> = LinkedList()
for (downloadFile in mediaPlayerController.playList) {
entries.add(downloadFile.song)
}
val musicService = getMusicService()
musicService.createPlaylist(null, playlistName, entries)
return null
}
override fun done(result: Void?) { scope.launch {
val entries: MutableList<MusicDirectory.Entry> = LinkedList()
for (downloadFile in mediaPlayerController.playList) {
entries.add(downloadFile.song)
}
val musicService = getMusicService()
musicService.createPlaylist(null, playlistName, entries)
}.invokeOnCompletion {
if (it == null || it is CancellationException) {
Util.toast(context, R.string.download_playlist_done) Util.toast(context, R.string.download_playlist_done)
} } else {
Timber.e(it, "Exception has occurred in savePlaylistInBackground")
override fun error(error: Throwable) {
Timber.e(error, "Exception has occurred in savePlaylistInBackground")
val msg = String.format( val msg = String.format(
Locale.ROOT, Locale.ROOT,
"%s %s", "%s %s",
resources.getString(R.string.download_playlist_error), resources.getString(R.string.download_playlist_error),
getErrorMessage(error) CommunicationErrorUtil.getErrorMessage(it, context)
) )
Util.toast(context, msg) Util.toast(context, msg)
} }
}.execute() }
} }
private fun toggleFullScreenAlbumArt() { private fun toggleFullScreenAlbumArt() {
@ -979,116 +933,96 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
if (onProgressChangedTask != null) { if (onProgressChangedTask != null) {
return return
} }
onProgressChangedTask = object : SilentBackgroundTask<Void?>(activity) {
var isJukeboxEnabled = false onProgressChangedTask = scope.launch(CommunicationErrorUtil.handler(context)) {
var millisPlayed = 0
var duration: Int? = null val isJukeboxEnabled: Boolean = mediaPlayerController.isJukeboxEnabled
var playerState: PlayerState? = null val millisPlayed = max(0, mediaPlayerController.playerPosition)
override fun doInBackground(): Void? { val duration = mediaPlayerController.playerDuration
isJukeboxEnabled = mediaPlayerController.isJukeboxEnabled val playerState = mediaPlayerController.playerState
millisPlayed = max(0, mediaPlayerController.playerPosition)
duration = mediaPlayerController.playerDuration if (cancellationToken.isCancellationRequested) return@launch
playerState = mediaPlayerController.playerState if (currentPlaying != null) {
return null positionTextView.text = Util.formatTotalDuration(millisPlayed.toLong(), true)
durationTextView.text = Util.formatTotalDuration(duration.toLong(), true)
progressBar.max =
if (duration == 0) 100 else duration // Work-around for apparent bug.
progressBar.progress = millisPlayed
progressBar.isEnabled = currentPlaying!!.isWorkDone || isJukeboxEnabled
} else {
positionTextView.setText(R.string.util_zero_time)
durationTextView.setText(R.string.util_no_time)
progressBar.progress = 0
progressBar.max = 0
progressBar.isEnabled = false
} }
@Suppress("LongMethod") when (playerState) {
override fun done(result: Void?) { PlayerState.DOWNLOADING -> {
if (cancellationToken.isCancellationRequested) return val progress =
if (currentPlaying != null) { if (currentPlaying != null) currentPlaying!!.progress.value!! else 0
val millisTotal = if (duration == null) 0 else duration!! val downloadStatus = resources.getString(
positionTextView.text = Util.formatTotalDuration(millisPlayed.toLong(), true) R.string.download_playerstate_downloading,
durationTextView.text = Util.formatTotalDuration(millisTotal.toLong(), true) Util.formatPercentage(progress)
progressBar.max =
if (millisTotal == 0) 100 else millisTotal // Work-around for apparent bug.
progressBar.progress = millisPlayed
progressBar.isEnabled = currentPlaying!!.isWorkDone || isJukeboxEnabled
} else {
positionTextView.setText(R.string.util_zero_time)
durationTextView.setText(R.string.util_no_time)
progressBar.progress = 0
progressBar.max = 0
progressBar.isEnabled = false
}
when (playerState) {
PlayerState.DOWNLOADING -> {
val progress =
if (currentPlaying != null) currentPlaying!!.progress.value!! else 0
val downloadStatus = resources.getString(
R.string.download_playerstate_downloading,
Util.formatPercentage(progress)
)
setTitle(this@PlayerFragment, downloadStatus)
}
PlayerState.PREPARING -> setTitle(
this@PlayerFragment,
R.string.download_playerstate_buffering
) )
PlayerState.STARTED -> { setTitle(this@PlayerFragment, downloadStatus)
if (mediaPlayerController.isShufflePlayEnabled) {
setTitle(
this@PlayerFragment,
R.string.download_playerstate_playing_shuffle
)
} else {
setTitle(this@PlayerFragment, R.string.common_appname)
}
}
PlayerState.IDLE,
PlayerState.PREPARED,
PlayerState.STOPPED,
PlayerState.PAUSED,
PlayerState.COMPLETED -> {
}
else -> setTitle(this@PlayerFragment, R.string.common_appname)
} }
PlayerState.PREPARING -> setTitle(
when (playerState) { this@PlayerFragment,
PlayerState.STARTED -> { R.string.download_playerstate_buffering
pauseButton.isVisible = true )
stopButton.isVisible = false PlayerState.STARTED -> {
startButton.isVisible = false if (mediaPlayerController.isShufflePlayEnabled) {
} setTitle(
PlayerState.DOWNLOADING, PlayerState.PREPARING -> { this@PlayerFragment,
pauseButton.isVisible = false R.string.download_playerstate_playing_shuffle
stopButton.isVisible = true )
startButton.isVisible = false } else {
} setTitle(this@PlayerFragment, R.string.common_appname)
else -> {
pauseButton.isVisible = false
stopButton.isVisible = false
startButton.isVisible = true
} }
} }
PlayerState.IDLE,
// TODO: It would be a lot nicer if MediaPlayerController would send an event PlayerState.PREPARED,
// when this is necessary instead of updating every time PlayerState.STOPPED,
displaySongRating() PlayerState.PAUSED,
onProgressChangedTask = null PlayerState.COMPLETED -> {
}
else -> setTitle(this@PlayerFragment, R.string.common_appname)
} }
when (playerState) {
PlayerState.STARTED -> {
pauseButton.isVisible = true
stopButton.isVisible = false
startButton.isVisible = false
}
PlayerState.DOWNLOADING, PlayerState.PREPARING -> {
pauseButton.isVisible = false
stopButton.isVisible = true
startButton.isVisible = false
}
else -> {
pauseButton.isVisible = false
stopButton.isVisible = false
startButton.isVisible = true
}
}
// TODO: It would be a lot nicer if MediaPlayerController would send an event
// when this is necessary instead of updating every time
displaySongRating()
onProgressChangedTask = null
} }
onProgressChangedTask!!.execute()
} }
private fun changeProgress(ms: Int) { private fun changeProgress(ms: Int) {
object : SilentBackgroundTask<Void?>(activity) { scope.launch(CommunicationErrorUtil.handler(context)) {
var msPlayed = 0 val msPlayed: Int = max(0, mediaPlayerController.playerPosition)
var duration: Int? = null val duration = mediaPlayerController.playerDuration
var seekTo = 0 val seekTo = (msPlayed + ms).coerceAtMost(duration)
override fun doInBackground(): Void? { mediaPlayerController.seekTo(seekTo)
msPlayed = max(0, mediaPlayerController.playerPosition) progressBar.progress = seekTo
duration = mediaPlayerController.playerDuration }
val msTotal = duration!!
seekTo = (msPlayed + ms).coerceAtMost(msTotal)
mediaPlayerController.seekTo(seekTo)
return null
}
override fun done(result: Void?) {
progressBar.progress = seekTo
}
}.execute()
} }
override fun onDown(me: MotionEvent): Boolean { override fun onDown(me: MotionEvent): Boolean {

View File

@ -38,7 +38,7 @@ import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
import org.moire.ultrasonic.service.CommunicationErrorHandler import org.moire.ultrasonic.service.CommunicationErrorUtil
import org.moire.ultrasonic.service.MediaPlayerController import org.moire.ultrasonic.service.MediaPlayerController
import org.moire.ultrasonic.subsonic.DownloadHandler import org.moire.ultrasonic.subsonic.DownloadHandler
import org.moire.ultrasonic.subsonic.ImageLoaderProvider import org.moire.ultrasonic.subsonic.ImageLoaderProvider
@ -211,7 +211,7 @@ class TrackCollectionFragment : Fragment() {
val handler = CoroutineExceptionHandler { _, exception -> val handler = CoroutineExceptionHandler { _, exception ->
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
CommunicationErrorHandler.handleError(exception, context) CommunicationErrorUtil.handleError(exception, context)
} }
refreshAlbumListView!!.isRefreshing = false refreshAlbumListView!!.isRefreshing = false
} }

View File

@ -20,12 +20,16 @@ package org.moire.ultrasonic.service
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context import android.content.Context
import android.os.Handler
import android.os.Looper
import com.fasterxml.jackson.core.JsonParseException import com.fasterxml.jackson.core.JsonParseException
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.IOException import java.io.IOException
import java.security.cert.CertPathValidatorException import java.security.cert.CertPathValidatorException
import java.security.cert.CertificateException import java.security.cert.CertificateException
import javax.net.ssl.SSLException import javax.net.ssl.SSLException
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineExceptionHandler
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
import org.moire.ultrasonic.api.subsonic.ApiNotSupportedException import org.moire.ultrasonic.api.subsonic.ApiNotSupportedException
import org.moire.ultrasonic.api.subsonic.SubsonicRESTException import org.moire.ultrasonic.api.subsonic.SubsonicRESTException
@ -37,8 +41,19 @@ import timber.log.Timber
* Contains helper functions to handle the exceptions * Contains helper functions to handle the exceptions
* thrown during the communication with a Subsonic server * thrown during the communication with a Subsonic server
*/ */
class CommunicationErrorHandler { @Suppress("ReturnCount", "UtilityClassWithPublicConstructor")
class CommunicationErrorUtil {
companion object { companion object {
fun handler(context: Context?, handler: ((CoroutineContext, Throwable) -> Unit)? = null):
CoroutineExceptionHandler {
return CoroutineExceptionHandler { coroutineContext, exception ->
Handler(Looper.getMainLooper()).post {
handleError(exception, context)
handler?.invoke(coroutineContext, exception)
}
}
}
fun handleError(error: Throwable?, context: Context?) { fun handleError(error: Throwable?, context: Context?) {
Timber.w(error) Timber.w(error)
@ -53,7 +68,8 @@ class CommunicationErrorHandler {
.create().show() .create().show()
} }
fun getErrorMessage(error: Throwable, context: Context): String { fun getErrorMessage(error: Throwable, context: Context?): String {
if (context == null) return "Couldn't get Error message, Context is null"
if (error is IOException && !Util.isNetworkConnected()) { if (error is IOException && !Util.isNetworkConnected()) {
return context.resources.getString(R.string.background_task_no_network) return context.resources.getString(R.string.background_task_no_network)
} else if (error is FileNotFoundException) { } else if (error is FileNotFoundException) {

View File

@ -1,32 +0,0 @@
/*
* SilentBackgroundTask.kt
* Copyright (C) 2009-2021 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.util
import android.app.Activity
/**
* @author Sindre Mehus
*/
abstract class SilentBackgroundTask<T>(activity: Activity?) : BackgroundTask<T>(activity) {
override fun execute() {
val thread: Thread = object : Thread() {
override fun run() {
try {
val result = doInBackground()
handler.post { done(result) }
} catch (all: Throwable) {
handler.post { error(all) }
}
}
}
thread.start()
}
override fun updateProgress(messageId: Int) {}
override fun updateProgress(message: String) {}
}