CommunicationError to Object with static methods
This commit is contained in:
parent
ed152fa52a
commit
1ed9360bc7
|
@ -20,7 +20,6 @@ package org.moire.ultrasonic.util;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import org.moire.ultrasonic.service.CommunicationErrorUtil;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
|
@ -54,12 +53,12 @@ public abstract class BackgroundTask<T> implements ProgressListener
|
|||
|
||||
protected void error(Throwable error)
|
||||
{
|
||||
CommunicationErrorUtil.Companion.handleError(error, activity);
|
||||
CommunicationError.handleError(error, activity);
|
||||
}
|
||||
|
||||
protected String getErrorMessage(Throwable error)
|
||||
{
|
||||
return CommunicationErrorUtil.Companion.getErrorMessage(error, activity);
|
||||
return CommunicationError.getErrorMessage(error, activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,9 +18,9 @@ import org.koin.core.component.inject
|
|||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.data.ServerSetting
|
||||
import org.moire.ultrasonic.domain.MusicFolder
|
||||
import org.moire.ultrasonic.service.CommunicationErrorUtil
|
||||
import org.moire.ultrasonic.service.MusicService
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory
|
||||
import org.moire.ultrasonic.util.CommunicationError
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
|
||||
/**
|
||||
|
@ -94,7 +94,7 @@ open class GenericListModel(application: Application) :
|
|||
|
||||
private fun handleException(exception: Exception, context: Context) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
CommunicationErrorUtil.handleError(exception, context)
|
||||
CommunicationError.handleError(exception, context)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import java.util.ArrayList
|
|||
import java.util.Date
|
||||
import java.util.LinkedList
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.CancellationException
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
@ -67,7 +68,6 @@ import org.moire.ultrasonic.domain.RepeatMode
|
|||
import org.moire.ultrasonic.featureflags.Feature
|
||||
import org.moire.ultrasonic.featureflags.FeatureStorage
|
||||
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.LocalMediaPlayer
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
|
@ -77,6 +77,7 @@ import org.moire.ultrasonic.subsonic.ImageLoaderProvider
|
|||
import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker
|
||||
import org.moire.ultrasonic.subsonic.ShareHandler
|
||||
import org.moire.ultrasonic.util.CancellationToken
|
||||
import org.moire.ultrasonic.util.CommunicationError
|
||||
import org.moire.ultrasonic.util.Constants
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
|
@ -84,7 +85,6 @@ import org.moire.ultrasonic.view.AutoRepeatButton
|
|||
import org.moire.ultrasonic.view.SongListAdapter
|
||||
import org.moire.ultrasonic.view.VisualizerView
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.CancellationException
|
||||
|
||||
/**
|
||||
* Contains the Music Player screen of Ultrasonic with playback controls and the playlist
|
||||
|
@ -236,7 +236,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
|
||||
previousButton.setOnClickListener {
|
||||
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
mediaPlayerController.previous()
|
||||
onCurrentChanged()
|
||||
onSliderProgressChanged()
|
||||
|
@ -250,7 +250,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
|
||||
nextButton.setOnClickListener {
|
||||
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
mediaPlayerController.next()
|
||||
onCurrentChanged()
|
||||
onSliderProgressChanged()
|
||||
|
@ -262,14 +262,14 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
changeProgress(incrementTime)
|
||||
}
|
||||
pauseButton.setOnClickListener {
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
mediaPlayerController.pause()
|
||||
onCurrentChanged()
|
||||
onSliderProgressChanged()
|
||||
}
|
||||
}
|
||||
stopButton.setOnClickListener {
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
mediaPlayerController.reset()
|
||||
onCurrentChanged()
|
||||
onSliderProgressChanged()
|
||||
|
@ -277,7 +277,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
}
|
||||
startButton.setOnClickListener {
|
||||
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
start()
|
||||
onCurrentChanged()
|
||||
onSliderProgressChanged()
|
||||
|
@ -309,7 +309,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
|
||||
progressBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
mediaPlayerController.seekTo(progressBar.progress)
|
||||
onSliderProgressChanged()
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
|
||||
playlistView.setOnItemClickListener { _, _, position, _ ->
|
||||
networkAndStorageChecker.warnIfNetworkOrStorageUnavailable()
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
mediaPlayerController.play(position)
|
||||
onCurrentChanged()
|
||||
onSliderProgressChanged()
|
||||
|
@ -388,7 +388,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
}
|
||||
|
||||
// Query the Jukebox state off-thread
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
try {
|
||||
jukeboxAvailable = mediaPlayerController.isJukeboxAvailable
|
||||
} catch (all: Exception) {
|
||||
|
@ -795,7 +795,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
Locale.ROOT,
|
||||
"%s %s",
|
||||
resources.getString(R.string.download_playlist_error),
|
||||
CommunicationErrorUtil.getErrorMessage(it, context)
|
||||
CommunicationError.getErrorMessage(it, context)
|
||||
)
|
||||
Util.toast(context, msg)
|
||||
}
|
||||
|
@ -934,7 +934,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
return
|
||||
}
|
||||
|
||||
onProgressChangedTask = scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
onProgressChangedTask = scope.launch(CommunicationError.getHandler(context)) {
|
||||
|
||||
val isJukeboxEnabled: Boolean = mediaPlayerController.isJukeboxEnabled
|
||||
val millisPlayed = max(0, mediaPlayerController.playerPosition)
|
||||
|
@ -1016,7 +1016,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
|
|||
}
|
||||
|
||||
private fun changeProgress(ms: Int) {
|
||||
scope.launch(CommunicationErrorUtil.handler(context)) {
|
||||
scope.launch(CommunicationError.getHandler(context)) {
|
||||
val msPlayed: Int = max(0, mediaPlayerController.playerPosition)
|
||||
val duration = mediaPlayerController.playerDuration
|
||||
val seekTo = (msPlayed + ms).coerceAtMost(duration)
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
|||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
|
||||
import org.moire.ultrasonic.service.CommunicationErrorUtil
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
import org.moire.ultrasonic.subsonic.DownloadHandler
|
||||
import org.moire.ultrasonic.subsonic.ImageLoaderProvider
|
||||
|
@ -47,6 +46,7 @@ import org.moire.ultrasonic.subsonic.ShareHandler
|
|||
import org.moire.ultrasonic.subsonic.VideoPlayer
|
||||
import org.moire.ultrasonic.util.AlbumHeader
|
||||
import org.moire.ultrasonic.util.CancellationToken
|
||||
import org.moire.ultrasonic.util.CommunicationError
|
||||
import org.moire.ultrasonic.util.Constants
|
||||
import org.moire.ultrasonic.util.EntryByDiscAndTrackComparator
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
|
@ -211,7 +211,7 @@ class TrackCollectionFragment : Fragment() {
|
|||
|
||||
val handler = CoroutineExceptionHandler { _, exception ->
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
CommunicationErrorUtil.handleError(exception, context)
|
||||
CommunicationError.handleError(exception, context)
|
||||
}
|
||||
refreshAlbumListView!!.isRefreshing = false
|
||||
}
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
This file is part of Subsonic.
|
||||
|
||||
Subsonic is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Subsonic is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2020 (C) Jozsef Varga
|
||||
*/
|
||||
package org.moire.ultrasonic.service
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.fasterxml.jackson.core.JsonParseException
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.security.cert.CertPathValidatorException
|
||||
import java.security.cert.CertificateException
|
||||
import javax.net.ssl.SSLException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.api.subsonic.ApiNotSupportedException
|
||||
import org.moire.ultrasonic.api.subsonic.SubsonicRESTException
|
||||
import org.moire.ultrasonic.subsonic.getLocalizedErrorMessage
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Contains helper functions to handle the exceptions
|
||||
* thrown during the communication with a Subsonic server
|
||||
*/
|
||||
@Suppress("ReturnCount", "UtilityClassWithPublicConstructor")
|
||||
class CommunicationErrorUtil {
|
||||
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?) {
|
||||
Timber.w(error)
|
||||
|
||||
if (context == null) return
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(R.string.error_label)
|
||||
.setMessage(getErrorMessage(error!!, context))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.common_ok) { _, _ -> }
|
||||
.create().show()
|
||||
}
|
||||
|
||||
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()) {
|
||||
return context.resources.getString(R.string.background_task_no_network)
|
||||
} else if (error is FileNotFoundException) {
|
||||
return context.resources.getString(R.string.background_task_not_found)
|
||||
} else if (error is JsonParseException) {
|
||||
return context.resources.getString(R.string.background_task_parse_error)
|
||||
} else if (error is SSLException) {
|
||||
return if (
|
||||
error.cause is CertificateException &&
|
||||
error.cause?.cause is CertPathValidatorException
|
||||
) {
|
||||
context.resources
|
||||
.getString(
|
||||
R.string.background_task_ssl_cert_error, error.cause?.cause?.message
|
||||
)
|
||||
} else {
|
||||
context.resources.getString(R.string.background_task_ssl_error)
|
||||
}
|
||||
} else if (error is ApiNotSupportedException) {
|
||||
return context.resources.getString(
|
||||
R.string.background_task_unsupported_api, error.serverApiVersion
|
||||
)
|
||||
} else if (error is IOException) {
|
||||
return context.resources.getString(R.string.background_task_network_error)
|
||||
} else if (error is SubsonicRESTException) {
|
||||
return error.getLocalizedErrorMessage(context)
|
||||
}
|
||||
val message = error.message
|
||||
return message ?: error.javaClass.simpleName
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* CommunicationErrorUtil.kt
|
||||
* Copyright (C) 2009-2021 Ultrasonic developers
|
||||
*
|
||||
* Distributed under terms of the GNU GPLv3 license.
|
||||
*/
|
||||
package org.moire.ultrasonic.util
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.fasterxml.jackson.core.JsonParseException
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.security.cert.CertPathValidatorException
|
||||
import java.security.cert.CertificateException
|
||||
import javax.net.ssl.SSLException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.api.subsonic.ApiNotSupportedException
|
||||
import org.moire.ultrasonic.api.subsonic.SubsonicRESTException
|
||||
import org.moire.ultrasonic.subsonic.getLocalizedErrorMessage
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Contains helper functions to handle the exceptions
|
||||
* thrown during the communication with a Subsonic server
|
||||
*/
|
||||
object CommunicationError {
|
||||
fun getHandler(context: Context?, handler: ((CoroutineContext, Throwable) -> Unit)? = null):
|
||||
CoroutineExceptionHandler {
|
||||
return CoroutineExceptionHandler { coroutineContext, exception ->
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
handleError(exception, context)
|
||||
handler?.invoke(coroutineContext, exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun handleError(error: Throwable?, context: Context?) {
|
||||
Timber.w(error)
|
||||
|
||||
if (context == null) return
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(R.string.error_label)
|
||||
.setMessage(getErrorMessage(error!!, context))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.common_ok) { _, _ -> }
|
||||
.create().show()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Suppress("ReturnCount")
|
||||
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()) {
|
||||
return context.resources.getString(R.string.background_task_no_network)
|
||||
} else if (error is FileNotFoundException) {
|
||||
return context.resources.getString(R.string.background_task_not_found)
|
||||
} else if (error is JsonParseException) {
|
||||
return context.resources.getString(R.string.background_task_parse_error)
|
||||
} else if (error is SSLException) {
|
||||
return if (
|
||||
error.cause is CertificateException &&
|
||||
error.cause?.cause is CertPathValidatorException
|
||||
) {
|
||||
context.resources
|
||||
.getString(
|
||||
R.string.background_task_ssl_cert_error, error.cause?.cause?.message
|
||||
)
|
||||
} else {
|
||||
context.resources.getString(R.string.background_task_ssl_error)
|
||||
}
|
||||
} else if (error is ApiNotSupportedException) {
|
||||
return context.resources.getString(
|
||||
R.string.background_task_unsupported_api, error.serverApiVersion
|
||||
)
|
||||
} else if (error is IOException) {
|
||||
return context.resources.getString(R.string.background_task_network_error)
|
||||
} else if (error is SubsonicRESTException) {
|
||||
return error.getLocalizedErrorMessage(context)
|
||||
}
|
||||
val message = error.message
|
||||
return message ?: error.javaClass.simpleName
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue