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