mirror of https://github.com/Ashinch/ReadYou.git
feat(infrastructure): add except BusinessException case for crash handle (#651)
This commit is contained in:
parent
441368695c
commit
69d7124a76
|
@ -8,8 +8,6 @@ import androidx.work.WorkManager
|
|||
import com.rometools.rome.feed.synd.SyndFeed
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import kotlinx.coroutines.withContext
|
||||
import me.ash.reader.R
|
||||
|
@ -27,6 +25,7 @@ import me.ash.reader.infrastructure.android.NotificationHelper
|
|||
import me.ash.reader.infrastructure.di.DefaultDispatcher
|
||||
import me.ash.reader.infrastructure.di.IODispatcher
|
||||
import me.ash.reader.infrastructure.di.MainDispatcher
|
||||
import me.ash.reader.infrastructure.exception.FeverAPIException
|
||||
import me.ash.reader.infrastructure.html.Readability
|
||||
import me.ash.reader.infrastructure.rss.RssHelper
|
||||
import me.ash.reader.infrastructure.rss.provider.fever.FeverAPI
|
||||
|
@ -90,35 +89,35 @@ class FeverRssService @Inject constructor(
|
|||
feedLink: String, searchedFeed: SyndFeed, groupId: String,
|
||||
isNotification: Boolean, isFullContent: Boolean,
|
||||
) {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
override suspend fun addGroup(destFeed: Feed?, newGroupName: String): String {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
override suspend fun renameGroup(group: Group) {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
override suspend fun renameFeed(feed: Feed) {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
override suspend fun deleteGroup(group: Group, onlyDeleteNoStarred: Boolean?) {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
override suspend fun deleteFeed(feed: Feed, onlyDeleteNoStarred: Boolean?) {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
override suspend fun moveFeed(originGroupId: String, feed: Feed) {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
override suspend fun changeFeedUrl(feed: Feed) {
|
||||
throw Exception("Unsupported")
|
||||
throw FeverAPIException("Unsupported")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import me.ash.reader.ui.ext.getCurrentVersion
|
||||
import me.ash.reader.infrastructure.exception.BusinessException
|
||||
import me.ash.reader.ui.ext.showToastLong
|
||||
import java.lang.Thread.UncaughtExceptionHandler
|
||||
|
||||
|
@ -23,10 +23,21 @@ class CrashHandler(private val context: Context) : UncaughtExceptionHandler {
|
|||
override fun uncaughtException(p0: Thread, p1: Throwable) {
|
||||
val causeMessage = getCauseMessage(p1)
|
||||
Log.e("RLog", "uncaughtException: $causeMessage", p1)
|
||||
context.startActivity(Intent(context, CrashReportActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
putExtra(CrashReportActivity.ERROR_REPORT_KEY, p1.stackTraceToString())
|
||||
})
|
||||
|
||||
when (p1) {
|
||||
is BusinessException -> {
|
||||
Looper.myLooper() ?: Looper.prepare()
|
||||
context.showToastLong(causeMessage)
|
||||
Looper.loop()
|
||||
}
|
||||
|
||||
else -> {
|
||||
context.startActivity(Intent(context, CrashReportActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
putExtra(CrashReportActivity.ERROR_REPORT_KEY, p1.stackTraceToString())
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCauseMessage(e: Throwable?): String? {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package me.ash.reader.infrastructure.exception
|
||||
|
||||
open class BusinessException : Exception {
|
||||
constructor() : super()
|
||||
constructor(message: String) : super(message)
|
||||
constructor(message: String, cause: Throwable) : super(message, cause)
|
||||
constructor(cause: Throwable) : super(cause)
|
||||
constructor(
|
||||
message: String,
|
||||
cause: Throwable,
|
||||
enableSuppression: Boolean,
|
||||
writableStackTrace: Boolean,
|
||||
) : super(message, cause, enableSuppression, writableStackTrace)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package me.ash.reader.infrastructure.exception
|
||||
|
||||
class FeverAPIException : BusinessException {
|
||||
constructor() : super()
|
||||
constructor(message: String) : super(message)
|
||||
constructor(message: String, cause: Throwable) : super(message, cause)
|
||||
constructor(cause: Throwable) : super(cause)
|
||||
constructor(
|
||||
message: String,
|
||||
cause: Throwable,
|
||||
enableSuppression: Boolean,
|
||||
writableStackTrace: Boolean,
|
||||
) : super(message, cause, enableSuppression, writableStackTrace)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package me.ash.reader.infrastructure.exception
|
||||
|
||||
class GoogleReaderAPIException : BusinessException {
|
||||
constructor() : super()
|
||||
constructor(message: String) : super(message)
|
||||
constructor(message: String, cause: Throwable) : super(message, cause)
|
||||
constructor(cause: Throwable) : super(cause)
|
||||
constructor(
|
||||
message: String,
|
||||
cause: Throwable,
|
||||
enableSuppression: Boolean,
|
||||
writableStackTrace: Boolean,
|
||||
) : super(message, cause, enableSuppression, writableStackTrace)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package me.ash.reader.infrastructure.exception
|
||||
|
||||
class RemoteCallException : BusinessException {
|
||||
constructor() : super()
|
||||
constructor(message: String) : super(message)
|
||||
constructor(message: String, cause: Throwable) : super(message, cause)
|
||||
constructor(cause: Throwable) : super(cause)
|
||||
constructor(
|
||||
message: String,
|
||||
cause: Throwable,
|
||||
enableSuppression: Boolean,
|
||||
writableStackTrace: Boolean,
|
||||
) : super(message, cause, enableSuppression, writableStackTrace)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package me.ash.reader.infrastructure.exception
|
||||
|
||||
class RetryException : BusinessException {
|
||||
constructor() : super()
|
||||
constructor(message: String) : super(message)
|
||||
constructor(message: String, cause: Throwable) : super(message, cause)
|
||||
constructor(cause: Throwable) : super(cause)
|
||||
constructor(
|
||||
message: String,
|
||||
cause: Throwable,
|
||||
enableSuppression: Boolean,
|
||||
writableStackTrace: Boolean,
|
||||
) : super(message, cause, enableSuppression, writableStackTrace)
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package me.ash.reader.infrastructure.rss.provider.fever
|
||||
|
||||
import me.ash.reader.infrastructure.exception.FeverAPIException
|
||||
import me.ash.reader.infrastructure.rss.provider.ProviderAPI
|
||||
import me.ash.reader.ui.ext.encodeBase64
|
||||
import me.ash.reader.ui.ext.md5
|
||||
|
@ -29,8 +30,8 @@ class FeverAPI private constructor(
|
|||
.executeAsync()
|
||||
|
||||
when (response.code) {
|
||||
401 -> throw Exception("Unauthorized")
|
||||
!in 200..299 -> throw Exception("Forbidden")
|
||||
401 -> throw FeverAPIException("Unauthorized")
|
||||
!in 200..299 -> throw FeverAPIException("Forbidden")
|
||||
}
|
||||
|
||||
return toDTO(response.body.string())
|
||||
|
@ -38,14 +39,14 @@ class FeverAPI private constructor(
|
|||
|
||||
private fun checkAuth(authMap: Map<String, Any>): Int = checkAuth(authMap["auth"] as Int?)
|
||||
|
||||
private fun checkAuth(auth: Int?): Int = auth?.takeIf { it > 0 } ?: throw Exception("Unauthorized")
|
||||
private fun checkAuth(auth: Int?): Int = auth?.takeIf { it > 0 } ?: throw FeverAPIException("Unauthorized")
|
||||
|
||||
@Throws
|
||||
suspend fun validCredentials(): Int = checkAuth(postRequest<FeverDTO.Common>(null).auth)
|
||||
|
||||
suspend fun getApiVersion(): Long =
|
||||
postRequest<Map<String, Any>>(null)["api_version"] as Long?
|
||||
?: throw Exception("Unable to get version")
|
||||
?: throw FeverAPIException("Unable to get version")
|
||||
|
||||
suspend fun getGroups(): FeverDTO.Groups =
|
||||
postRequest<FeverDTO.Groups>("groups").apply { checkAuth(auth) }
|
||||
|
@ -66,7 +67,7 @@ class FeverAPI private constructor(
|
|||
postRequest<FeverDTO.Items>("items&max_id=$id").apply { checkAuth(auth) }
|
||||
|
||||
suspend fun getItemsWith(ids: List<String>): FeverDTO.Items =
|
||||
if (ids.size > 50) throw Exception("Too many ids")
|
||||
if (ids.size > 50) throw FeverAPIException("Too many ids")
|
||||
else postRequest<FeverDTO.Items>("items&with_ids=${ids.joinToString(",")}").apply { checkAuth(auth) }
|
||||
|
||||
suspend fun getLinks(): FeverDTO.Links =
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package me.ash.reader.infrastructure.rss.provider.greader
|
||||
|
||||
import me.ash.reader.infrastructure.di.USER_AGENT_STRING
|
||||
import me.ash.reader.infrastructure.exception.GoogleReaderAPIException
|
||||
import me.ash.reader.infrastructure.exception.RetryException
|
||||
import me.ash.reader.infrastructure.rss.provider.ProviderAPI
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Request
|
||||
|
@ -32,11 +34,11 @@ class GoogleReaderAPI private constructor(
|
|||
private val authData = AuthData(null, null)
|
||||
|
||||
suspend fun validCredentials(): Boolean {
|
||||
reauthenticate()
|
||||
reAuthenticate()
|
||||
return authData.clientLoginToken?.isNotEmpty() ?: false
|
||||
}
|
||||
|
||||
private suspend fun reauthenticate() {
|
||||
private suspend fun reAuthenticate() {
|
||||
// Get client login token
|
||||
val clResponse = client.newCall(
|
||||
Request.Builder()
|
||||
|
@ -55,10 +57,10 @@ class GoogleReaderAPI private constructor(
|
|||
|
||||
val clBody = clResponse.body.string()
|
||||
when (clResponse.code) {
|
||||
400 -> throw Exception("BadRequest for CL Token")
|
||||
401 -> throw Exception("Unauthorized for CL Token")
|
||||
400 -> throw GoogleReaderAPIException("BadRequest for CL Token")
|
||||
401 -> throw GoogleReaderAPIException("Unauthorized for CL Token")
|
||||
!in 200..299 -> {
|
||||
throw Exception(clBody)
|
||||
throw GoogleReaderAPIException(clBody)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +71,7 @@ class GoogleReaderAPI private constructor(
|
|||
.split("\n")
|
||||
.find { it.startsWith("Auth=") }
|
||||
?.substring(5)
|
||||
?: throw Exception("body format error for CL Token:\n$clBody")
|
||||
?: throw GoogleReaderAPIException("body format error for CL Token:\n$clBody")
|
||||
}
|
||||
|
||||
// Get action token
|
||||
|
@ -88,8 +90,6 @@ class GoogleReaderAPI private constructor(
|
|||
authData.actionToken = actBody
|
||||
}
|
||||
|
||||
class RetryException(message: String) : Exception(message)
|
||||
|
||||
private suspend inline fun <reified T> retryableGetRequest(
|
||||
query: String,
|
||||
params: List<Pair<String, String>>? = null,
|
||||
|
@ -122,7 +122,7 @@ class GoogleReaderAPI private constructor(
|
|||
params: List<Pair<String, String>>? = null,
|
||||
): T {
|
||||
if (authData.clientLoginToken.isNullOrEmpty()) {
|
||||
reauthenticate()
|
||||
reAuthenticate()
|
||||
}
|
||||
|
||||
val response = client.newCall(
|
||||
|
@ -136,7 +136,7 @@ class GoogleReaderAPI private constructor(
|
|||
|
||||
val body = response.body.string()
|
||||
when (response.code) {
|
||||
400 -> throw Exception("BadRequest")
|
||||
400 -> throw GoogleReaderAPIException("BadRequest")
|
||||
401 -> throw RetryException("Unauthorized")
|
||||
!in 200..299 -> {
|
||||
val gReaderError = try {
|
||||
|
@ -144,7 +144,7 @@ class GoogleReaderAPI private constructor(
|
|||
} catch (ignore: Exception) {
|
||||
GoogleReaderDTO.GReaderError(listOf(body))
|
||||
}
|
||||
throw Exception(gReaderError.errors.joinToString(";\n "))
|
||||
throw GoogleReaderAPIException(gReaderError.errors.joinToString(";\n "))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ class GoogleReaderAPI private constructor(
|
|||
form: List<Pair<String, String>>? = null,
|
||||
): T {
|
||||
if (authData.clientLoginToken.isNullOrEmpty()) {
|
||||
reauthenticate()
|
||||
reAuthenticate()
|
||||
}
|
||||
val response = client.newCall(
|
||||
Request.Builder()
|
||||
|
@ -175,10 +175,10 @@ class GoogleReaderAPI private constructor(
|
|||
|
||||
val responseBody = response.body.string()
|
||||
when (response.code) {
|
||||
400 -> throw Exception("BadRequest")
|
||||
400 -> throw GoogleReaderAPIException("BadRequest")
|
||||
401 -> throw RetryException("Unauthorized")
|
||||
!in 200..299 -> {
|
||||
throw Exception(responseBody)
|
||||
throw GoogleReaderAPIException(responseBody)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue