Fix: prevent black screen after failed initialization.
If a crash occurs before feedback is started then attempting to report that crash will, itself, crash because the lateinit feedback instance is not initialized. The result is a black screen on launch! This fixes that by catching everything while trying to report an error.
This commit is contained in:
parent
953aeb32ea
commit
1577b3223d
|
@ -7,10 +7,8 @@ import androidx.camera.camera2.Camera2Config
|
||||||
import androidx.camera.core.CameraXConfig
|
import androidx.camera.core.CameraXConfig
|
||||||
import cash.z.ecc.android.di.component.AppComponent
|
import cash.z.ecc.android.di.component.AppComponent
|
||||||
import cash.z.ecc.android.di.component.DaggerAppComponent
|
import cash.z.ecc.android.di.component.DaggerAppComponent
|
||||||
|
import cash.z.ecc.android.ext.tryWithWarning
|
||||||
import cash.z.ecc.android.feedback.FeedbackCoordinator
|
import cash.z.ecc.android.feedback.FeedbackCoordinator
|
||||||
import cash.z.ecc.android.sdk.ext.SilentTwig
|
|
||||||
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
|
|
||||||
import cash.z.ecc.android.sdk.ext.Twig
|
|
||||||
import cash.z.ecc.android.sdk.ext.twig
|
import cash.z.ecc.android.sdk.ext.twig
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -68,19 +66,34 @@ class ZcashWalletApp : Application(), CameraXConfig.Provider {
|
||||||
* is complete, we can lazily initialize all the feedback objects at this moment so that we
|
* is complete, we can lazily initialize all the feedback objects at this moment so that we
|
||||||
* don't have to add any time to startup.
|
* don't have to add any time to startup.
|
||||||
*/
|
*/
|
||||||
inner class ExceptionReporter(private val ogHandler: Thread.UncaughtExceptionHandler) : Thread.UncaughtExceptionHandler {
|
inner class ExceptionReporter(private val ogHandler: Thread.UncaughtExceptionHandler) :
|
||||||
|
Thread.UncaughtExceptionHandler {
|
||||||
override fun uncaughtException(t: Thread?, e: Throwable?) {
|
override fun uncaughtException(t: Thread?, e: Throwable?) {
|
||||||
twig("Uncaught Exception: $e caused by: ${e?.cause}")
|
twig("Uncaught Exception: $e caused by: ${e?.cause}")
|
||||||
// these are the only reported crashes that are considered fatal
|
// Things can get pretty crazy during a fatal exception
|
||||||
coordinator.feedback.report(e, true)
|
// so be cautious here to avoid freezing the app
|
||||||
coordinator.flush()
|
tryWithWarning("Unable to report fatal crash") {
|
||||||
// can do this if necessary but first verify that we need it
|
// note: these are the only reported crashes that set isFatal=true
|
||||||
runBlocking {
|
coordinator.feedback.report(e, true)
|
||||||
coordinator.await()
|
}
|
||||||
coordinator.feedback.stop()
|
tryWithWarning("Unable to flush the feedback coordinator") {
|
||||||
|
coordinator.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// can do this if necessary but first verify that we need it
|
||||||
|
runBlocking {
|
||||||
|
coordinator.await()
|
||||||
|
coordinator.feedback.stop()
|
||||||
|
}
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
twig("WARNING: failed to wait for the feedback observers to complete.")
|
||||||
|
} finally {
|
||||||
|
// it's important that this always runs so we use the finally clause here
|
||||||
|
// rather than another tryWithWarning block
|
||||||
|
ogHandler.uncaughtException(t, e)
|
||||||
|
Thread.sleep(2000L)
|
||||||
}
|
}
|
||||||
ogHandler.uncaughtException(t, e)
|
|
||||||
Thread.sleep(2000L)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
package cash.z.ecc.android.ext
|
package cash.z.ecc.android.ext
|
||||||
|
|
||||||
fun Boolean.asString(ifTrue: String = "", ifFalse: String = "") = if(this) ifTrue else ifFalse
|
import cash.z.ecc.android.sdk.ext.twig
|
||||||
|
|
||||||
|
fun Boolean.asString(ifTrue: String = "", ifFalse: String = "") = if(this) ifTrue else ifFalse
|
||||||
|
|
||||||
|
inline fun <R> tryWithWarning(message: String = "", block: () -> R): R? {
|
||||||
|
return try {
|
||||||
|
block()
|
||||||
|
} catch (error: Throwable) {
|
||||||
|
twig("WARNING: $message")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue