Mobile Development 11 min read

Using Bandage to Prevent Android App Crashes by Intercepting Activity Lifecycle Exceptions

Bandage is an Android library that intercepts exceptions thrown in activity‑lifecycle callbacks and other main‑thread code via a reflective replacement of ActivityThread’s handler, allowing the app to finish the faulty activity or continue running, with configurable black‑/white‑listing, Bugly integration, and developer‑friendly warnings.

Youzan Coder
Youzan Coder
Youzan Coder
Using Bandage to Prevent Android App Crashes by Intercepting Activity Lifecycle Exceptions

Android crashes are a common pain point: code that works fine in testing may crash immediately after release, forcing a hot‑fix even for trivial bugs. In many cases developers prefer the app to stay alive even if a specific feature (e.g., viewing a large image) fails. The Bandage library provides a way to achieve this.

What is Bandage? Bandage is a generic “bandage” for Android apps. It aims to keep the app usable by preventing any Java exception from terminating the process. When an exception occurs during the app’s lifecycle, Bandage tries to rescue the app instead of letting it crash. Some exceptions must still terminate the app (e.g., those that could cause serious financial loss), and a black‑/white‑list mechanism can decide which exceptions to swallow.

How Bandage works

Bandage intercepts exceptions thrown in Activity lifecycle callbacks (such as onCreate , onResume , etc.). The interception is done by replacing the ActivityThread.mH.mCallback field via reflection. All lifecycle methods are ultimately dispatched through mH.handleMessage , so by providing a custom mCallback we can catch any exception before the system shows a black screen.

// mhHandler is ActivityThread.mH, callbackField is the mCallback field inside mH
callbackField.set(mhHandler, new Handler.Callback() {
// intercept lifecycle‑related messages
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY:
try {
// call ActivityThread.mH.handleMessage
mhHandler.handleMessage(msg);
return true;
} catch (Throwable throwable) {
// handle lifecycle exception, e.g., finish the offending Activity
return false;
});

Finishing the faulty Activity is performed via ActivityManager.finishActivity . The exact parameters (e.g., mToken ) differ across Android versions, so developers need to inspect the corresponding finish implementation for each API level.

ActivityManager.getService().finishActivity(mToken, resultCode, resultData, finishTask)

Intercepting other main‑thread exceptions can be done by wrapping Looper.loop() in a while (true) loop with a try‑catch block. This ensures that every time the main thread throws, the exception is caught and the loop continues, without causing ANR because Looper.loop() resumes message processing after each catch.

while (true) {
try {
Looper.loop();
} catch (Throwable e) {
// handle or log the exception
}
}

Other uncaught exceptions can be captured via Thread.setDefaultUncaughtExceptionHandler :

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
// custom handling
}
});

Exception classification – not all exceptions need to kill the process. Developers can use a black‑/white‑list (e.g., based on MD5 of ActivityClassName + stackTrace ) to decide whether to ignore an exception or terminate the app. Exceptions from ViewRootImpl are usually fatal and should cause a process kill to avoid black screens.

Integration with Bugly – Bugly also sets a default uncaught‑exception handler. To let Bugly report exceptions before Bandage handles them, initialize Bandage before Bugly. Activity‑lifecycle exceptions captured by Bandage will not be auto‑uploaded to Bugly; they must be reported manually if needed.

Practical advice – During development, it is recommended to disable Bandage to surface bugs. If it must be enabled, show a warning UI (e.g., a green banner) so developers know a crash was intercepted.

For visual reference, the original article includes screenshots and a link to the source code repository: https://github.com/android-notes/Cockroach/tree/X .

mobile developmentAndroidCrash HandlingBandageException Interception
Youzan Coder
Written by

Youzan Coder

Official Youzan tech channel, delivering technical insights and occasional daily updates from the Youzan tech team.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.