I did a bit of coding to test out Thread.UncaughtExceptionHandler for a specific use case (explained below).
Firstly, I have a BaseActivity
implemented this way.
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
Log.e("CRASH_REPORT", "Activity crashed!");
System.exit(0);
}
});
}
}
By extending BaseActivity
, any uncaught exception will end up being caught by the handler. System.exit(0)
will terminate the VM belongs to the app.
Now, I created 2 activities with this hierarchy (both extending BaseActivity
).
ParentActivity -> SubActivity
In ParentActivity
, I have only 1 button that will start SubActivity
on clicked (code omitted).
In SubActivity.onCreate(...)
, I purposely inject an exception to trigger uncaughtException(...)
.
public class SubActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int crash = 1 / 0;
}
}
When SubActivity
executed, uncaughtException(...)
triggered and the app stopped (obviously without the well known app stopped dialog).
What I want to know is whether its possible to just terminate the triggered Activity (SubActivity
in this case) and app will roll-back (sort of) to its previous state (ParentActivity
)?
Any advice is appreciated. Thank you.
After some research, I believe there is NO WAY to return to previous Activity
when uncaughtException(...)
triggered as main thread has been stopped since.
Here, I will list down the ideas I have on "countermeasure" this issue.
Activity
in different process (not recommended)In the manifest file, add android:process=dedicated_process_name
under each activity
tag. Doing this will make each Activity
running in its own process, thus ensuring crashing on 1 process does not affect another. This is not recommended, though.
<activity
android:name=".ParentActivity"
android:process="::parent_process" />
System.exit(code)
) and provide a callback where each Activity
can define its own handling.Create a BaseActivity
with a onCrashed(...)
callback.
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
Log.e("CRASH_REPORT", "Activity crashed!");
onCrashed(thread, throwable);
System.exit(0);
}
});
}
protected void onCrashed(Thread thread, Throwable throwable) {
// space for rent
}
}
All Activity
extending from BaseActivity
can decide what they want to do on crash. An example is to schedule to start the application again.
public class SubActivity extends BaseActivity
@Override
protected void onCrashed(Thread thread, Throwable throwable) {
Intent i = new Intent(this, ParentActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pi);
}
Alternatively, we can choose to implement uncaughtException(...) at Application
level and Application
will decide what to do next. (eg. restart current Activity
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With