zircles-android/app/src/main/java/cash/z/ecc/android/ZcashWalletApp.kt

95 lines
3.3 KiB
Kotlin
Raw Normal View History

2019-11-26 12:29:16 -08:00
package cash.z.ecc.android
import android.app.Application
2019-11-26 12:29:16 -08:00
import android.content.Context
import android.os.Build
import androidx.camera.camera2.Camera2Config
import androidx.camera.core.CameraXConfig
import cash.z.ecc.android.di.component.AppComponent
import cash.z.ecc.android.di.component.DaggerAppComponent
2020-01-09 07:53:48 -08:00
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
2020-01-09 23:53:16 -08:00
import kotlinx.coroutines.*
2020-01-09 07:53:48 -08:00
import javax.inject.Inject
2019-11-26 12:29:16 -08:00
class ZcashWalletApp : Application(), CameraXConfig.Provider {
2019-11-26 12:29:16 -08:00
2020-01-09 07:53:48 -08:00
@Inject
2020-01-13 16:09:22 -08:00
lateinit var coordinator: FeedbackCoordinator
2020-01-09 07:53:48 -08:00
var creationTime: Long = 0
private set
var creationMeasured: Boolean = false
2020-01-09 23:53:16 -08:00
/**
* Intentionally private Scope for use with launching Feedback jobs. The feedback object has the
* longest scope in the app because it needs to be around early in order to measure launch times
* and stick around late in order to catch crashes. We intentionally don't expose this because
* application objects can have odd lifecycles, given that there is no clear onDestroy moment in
* many cases.
*/
private var feedbackScope: CoroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
2019-11-26 12:29:16 -08:00
override fun onCreate() {
2020-01-13 16:09:22 -08:00
Thread.setDefaultUncaughtExceptionHandler(ExceptionReporter(Thread.getDefaultUncaughtExceptionHandler()))
creationTime = System.currentTimeMillis()
2019-11-26 12:29:16 -08:00
instance = this
// Setup handler for uncaught exceptions.
super.onCreate()
component = DaggerAppComponent.factory().create(this)
2020-01-09 07:53:48 -08:00
component.inject(this)
2020-01-09 23:53:16 -08:00
feedbackScope.launch {
2020-01-13 16:09:22 -08:00
coordinator.feedback.start()
2020-01-09 23:53:16 -08:00
}
2019-11-26 12:29:16 -08:00
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
// MultiDex.install(this)
}
override fun getCameraXConfig(): CameraXConfig {
return Camera2Config.defaultConfig()
}
2019-11-26 12:29:16 -08:00
companion object {
lateinit var instance: ZcashWalletApp
lateinit var component: AppComponent
2019-11-26 12:29:16 -08:00
}
2020-01-09 07:53:48 -08:00
/**
* @param feedbackCoordinator inject a provider so that if a crash happens before configuration
* 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.
*/
2020-01-13 16:09:22 -08:00
inner class ExceptionReporter(private val ogHandler: Thread.UncaughtExceptionHandler) : Thread.UncaughtExceptionHandler {
2019-11-26 12:29:16 -08:00
override fun uncaughtException(t: Thread?, e: Throwable?) {
2020-01-13 16:09:22 -08:00
twig("Uncaught Exception: $e caused by: ${e?.cause}")
// these are the only reported crashes that are considered fatal
coordinator.feedback.report(e, true)
2020-01-09 07:53:48 -08:00
coordinator.flush()
// can do this if necessary but first verify that we need it
runBlocking {
2020-01-13 16:09:22 -08:00
coordinator.await()
coordinator.feedback.stop()
2020-01-09 07:53:48 -08:00
}
2019-11-26 12:29:16 -08:00
ogHandler.uncaughtException(t, e)
2020-01-13 16:09:22 -08:00
Thread.sleep(2000L)
2019-11-26 12:29:16 -08:00
}
}
}
fun ZcashWalletApp.isEmulator(): Boolean {
val goldfish = Build.HARDWARE.contains("goldfish");
val emu = (System.getProperty("ro.kernel.qemu", "")?.length ?: 0) > 0;
val sdk = Build.MODEL.toLowerCase().contains("sdk")
return goldfish || emu || sdk;
}