Two options:
1) Use MainActivity as a "dispatcher". When C wants to launch D, it should do it like this:
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("launchD", true);
startActivity(intent);
This code will clear all activities on top of MainActivity, and causeonNewIntent() to be called on MainActivity.
In MainActivity, override onNewIntent():
@Override
protected void onNewIntent(Intent intent) {
if (intent.hasExtra("launchD")) {
// Need to launch Activity D
Intent launchIntent = new Intent(this, D.class);
startActivity(launchIntent);
}
}
MainActivity will now launch D after the stack is cleared. Pressing BACK in D will return to MainActivity.
2) Launch D from C as usual:
Intent intent = new Intent(this, D.class);
startActivity(intent);
At this point, the stack is A->B->C->D
In D, override onBackPressed():
@Override
public void onBackPressed() {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
In this case, pressing BACK while in D will cause D, C and B to be removed from the stack and the user will return to MainActivity.
Note: Using the combination of flags FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP ensures that the existing instance of MainActivity will be reused. Android won't create a new instance.