In English | 中文
GBU is an Android library that tries to fix your app when it crashes. You will never get the hated "X has stopped" dialog.
You can download an apk of the demo project.
The Gradle Dependency is available via jCenter
Add dependencies directly
implementation 'god.bless.you:gbu:0.0.2'
Integrate with kotlin
class App : Application() {
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
Gbu.init(this)
.setDebug(true)
.enableLifecycleCrash(true)
.enableOtherCrash(false)
.install()
}
}
GBU 'fix' the crash in the Activity lifecycle by hooking ActivityThread
's field mInstrumentation
.
GbuInstrumentationImpl.kt
override fun callActivityOnCreate(activity: Activity?, icicle: Bundle?) {
try {
super.callActivityOnCreate(activity, icicle)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnCreate(activity: Activity?, icicle: Bundle?, persistentState: PersistableBundle?) {
try {
super.callActivityOnCreate(activity, icicle, persistentState)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnNewIntent(activity: Activity?, intent: Intent?) {
try {
super.callActivityOnNewIntent(activity, intent)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnRestart(activity: Activity?) {
try {
super.callActivityOnRestart(activity)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnStart(activity: Activity?) {
try {
super.callActivityOnStart(activity)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnResume(activity: Activity?) {
try {
super.callActivityOnResume(activity)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnPause(activity: Activity?) {
try {
super.callActivityOnPause(activity)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnStop(activity: Activity?) {
try {
super.callActivityOnStop(activity)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnDestroy(activity: Activity?) {
try {
super.callActivityOnDestroy(activity)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnPostCreate(activity: Activity?, icicle: Bundle?) {
try {
super.callActivityOnPostCreate(activity, icicle)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnPostCreate(activity: Activity?, icicle: Bundle?, persistentState: PersistableBundle?) {
try {
super.callActivityOnPostCreate(activity, icicle, persistentState)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnSaveInstanceState(activity: Activity?, outState: Bundle?) {
try {
super.callActivityOnSaveInstanceState(activity, outState)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnSaveInstanceState(activity: Activity?, outState: Bundle?, outPersistentState: PersistableBundle?) {
try {
super.callActivityOnSaveInstanceState(activity, outState, outPersistentState)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnRestoreInstanceState(activity: Activity?, savedInstanceState: Bundle?) {
try {
super.callActivityOnRestoreInstanceState(activity, savedInstanceState)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun callActivityOnRestoreInstanceState(activity: Activity?, savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
try {
super.callActivityOnRestoreInstanceState(activity, savedInstanceState, persistentState)
} catch (e: Throwable) {
e.printStackTrace()
}
}
GBU 'fix' the crash in the Service and BroadcastReceiver lifecycle by hooking Instrumentation
's method onException
.
GbuInstrumentationImpl.kt
class GbuInstrumentationImpl(base: Instrumentation) : GbuInstrumentationWrapper(base) {
/**
* If true is returned, the system will proceed as if the exception didn't happen.
*/
override fun onException(obj: Any?, e: Throwable?): Boolean {
GbuActivityThread.handleException(obj)
return true
}
}
GbuActivityThread.kt
object GbuActivityThread {
/**
* Prevent incomplete lifecycle leads to anr.
*/
fun handleException(obj: Any?) {
if (Gbu.debug) {
GbuLog.d(codeToString(mMsg?.what!!))
}
if (obj is Service) {
when (mMsg?.what) {
CREATE_SERVICE -> handleCreateService(obj)
SERVICE_ARGS -> handleServiceArgs(obj)
STOP_SERVICE -> handleStopService(obj)
BIND_SERVICE -> handleBindService(obj)
UNBIND_SERVICE -> handleUnbindService(obj)
}
} else if (obj is BroadcastReceiver) {
GbuBroadcastReceiver.setPendingResult(obj, null)
}
}
}
object Gbu {
init {
Handler(Looper.getMainLooper()).post {
// Do not let the main thread exit.
while (true) {
try {
Looper.loop()
} catch (e: Throwable) {
e.printStackTrace()
}
}
}
// Catch all threads crashes
Thread.setDefaultUncaughtExceptionHandler { _: Thread, throwable: Throwable ->
throwable.printStackTrace()
}
}
}
Pengfeng Wang(王鹏锋)
email: ximsfei@gmail.com