mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 22:37:56 +01:00 
			
		
		
		
	Add Crash activity (#8216)
* Add Crash activity When the application crashes this sends them to a different activity with the cause message and an option to dump the crash logs * Review changes
This commit is contained in:
		
							
								
								
									
										25
									
								
								app/src/main/java/eu/kanade/tachiyomi/crash/CrashActivity.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/src/main/java/eu/kanade/tachiyomi/crash/CrashActivity.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package eu.kanade.tachiyomi.crash | ||||
|  | ||||
| import android.content.Intent | ||||
| import android.os.Bundle | ||||
| import eu.kanade.presentation.crash.CrashScreen | ||||
| import eu.kanade.tachiyomi.ui.base.activity.BaseActivity | ||||
| import eu.kanade.tachiyomi.ui.main.MainActivity | ||||
| import eu.kanade.tachiyomi.util.view.setComposeContent | ||||
|  | ||||
| class CrashActivity : BaseActivity() { | ||||
|  | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|         val exception = GlobalExceptionHandler.getThrowableFromIntent(intent) | ||||
|         setComposeContent { | ||||
|             CrashScreen( | ||||
|                 exception = exception, | ||||
|                 onRestartClick = { | ||||
|                     finishAffinity() | ||||
|                     startActivity(Intent(this@CrashActivity, MainActivity::class.java)) | ||||
|                 }, | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,80 @@ | ||||
| package eu.kanade.tachiyomi.crash | ||||
|  | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import eu.kanade.tachiyomi.util.system.logcat | ||||
| import kotlinx.serialization.KSerializer | ||||
| import kotlinx.serialization.descriptors.PrimitiveKind | ||||
| import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor | ||||
| import kotlinx.serialization.descriptors.SerialDescriptor | ||||
| import kotlinx.serialization.encoding.Decoder | ||||
| import kotlinx.serialization.encoding.Encoder | ||||
| import kotlinx.serialization.json.Json | ||||
| import logcat.LogPriority | ||||
| import kotlin.system.exitProcess | ||||
|  | ||||
| class GlobalExceptionHandler private constructor( | ||||
|     private val applicationContext: Context, | ||||
|     private val defaultHandler: Thread.UncaughtExceptionHandler, | ||||
|     private val activityToBeLaunched: Class<*>, | ||||
| ) : Thread.UncaughtExceptionHandler { | ||||
|  | ||||
|     object ThrowableSerializer : KSerializer<Throwable> { | ||||
|         override val descriptor: SerialDescriptor = | ||||
|             PrimitiveSerialDescriptor("Throwable", PrimitiveKind.STRING) | ||||
|  | ||||
|         override fun deserialize(decoder: Decoder): Throwable = | ||||
|             Throwable(message = decoder.decodeString()) | ||||
|  | ||||
|         override fun serialize(encoder: Encoder, value: Throwable) = | ||||
|             encoder.encodeString(value.stackTraceToString()) | ||||
|     } | ||||
|  | ||||
|     override fun uncaughtException(thread: Thread, exception: Throwable) { | ||||
|         try { | ||||
|             logcat(priority = LogPriority.ERROR, throwable = exception) | ||||
|             launchActivity(applicationContext, activityToBeLaunched, exception) | ||||
|             exitProcess(0) | ||||
|         } catch (_: Exception) { | ||||
|             defaultHandler.uncaughtException(thread, exception) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun launchActivity( | ||||
|         applicationContext: Context, | ||||
|         activity: Class<*>, | ||||
|         exception: Throwable, | ||||
|     ) { | ||||
|         val intent = Intent(applicationContext, activity).apply { | ||||
|             putExtra(INTENT_EXTRA, Json.encodeToString(ThrowableSerializer, exception)) | ||||
|             addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) | ||||
|             addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) | ||||
|         } | ||||
|         applicationContext.startActivity(intent) | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|         private const val INTENT_EXTRA = "Throwable" | ||||
|  | ||||
|         fun initialize( | ||||
|             applicationContext: Context, | ||||
|             activityToBeLaunched: Class<*>, | ||||
|         ) { | ||||
|             val handler = GlobalExceptionHandler( | ||||
|                 applicationContext, | ||||
|                 Thread.getDefaultUncaughtExceptionHandler() as Thread.UncaughtExceptionHandler, | ||||
|                 activityToBeLaunched, | ||||
|             ) | ||||
|             Thread.setDefaultUncaughtExceptionHandler(handler) | ||||
|         } | ||||
|  | ||||
|         fun getThrowableFromIntent(intent: Intent): Throwable? { | ||||
|             return try { | ||||
|                 Json.decodeFromString(ThrowableSerializer, intent.getStringExtra(INTENT_EXTRA)!!) | ||||
|             } catch (e: Exception) { | ||||
|                 logcat(LogPriority.ERROR, e) { "Wasn't able to retrive throwable from intent" } | ||||
|                 null | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user