Android startActivityForResult and onActivityResult has unpredictable behaviours
<p>I have an application in which multiple activities are shown in a certain order, which can change based on events in the current activity.  I have a "master" activity which manages which activities are shown.  Each ativity is started with <code>startActivityForResult()</code> with a <code>requestCode</code> unique to that activity.</p>

<p>When the activity finsishes, I set the <code>resultCode</code> to a value which will have meaning to the master activity. In the master activity's <code>onActivityResult</code> method, I have a <code>switch (requestCode)</code>, which will tell me which activity has returned, and in each case block I work with the <code>resultCode</code> to determine which activity to start next.</p>

<p>The problem I'm having, is that at times, seemingly randomly, the application behaves quite erratically, showing activities out of sequence.</p>

<p>I've been unable to replicate the issue while debugging, so all the information I have looks good, but the end users are constantly complaining about the erratic behaviour.</p>

<p>How can I test to see where the problem is?</p>

<hr>

<p>The code from the master activity's onActivityResult:</p>

<pre><code>
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
    case Settings.SCREEN_UPDATE:
        ShowActivity(LoginActivity.class, Settings.SCREEN_LOGIN);
        break;
    case Settings.SCREEN_LOGIN: 
        if (resultCode == RESULT_OK) {
            Settings.CurrentReport = new Report();
            Settings.CurrentReport.setUserId(data.getIntExtra("userId", -1));

            selectStore();
        } else {
            finish();
        }
        break;
    case Settings.SCREEN_PRODUCT: // Coming back from the product selection screen
        if (resultCode == RESULT_OK) {
            ShowActivity(ActionActivity.class, Settings.SCREEN_ACTION);
        } else if (resultCode == RESULT_CANCELED){
            ShowActivity(OptionsActivity.class, Settings.SCREEN_OPTIONS);
        }
        break;
    case Settings.SCREEN_ACTION: // Coming back from the action screen, regardless of result, show options screen.
        ShowActivity(OptionsActivity.class, Settings.SCREEN_OPTIONS);
        break;
    case Settings.SCREEN_OPTIONS: // All choices return result_ok.  Check the "mode" extra
        String mode = data.getStringExtra("mode");
        processOption(mode);
        break;
    case Settings.SCREEN_SESSION:
        if (resultCode == RESULT_CANCELED) {
            ShowActivity(OptionsActivity.class, Settings.SCREEN_OPTIONS);
        } else if (resultCode == RESULT_OK ){
            ShowActivity(ActionActivity.class, Settings.SCREEN_ACTION);
        }
        break;
    } // switch (requestCode)
} // protected void onActivityResult(int requestCode, int resultCode, Intent data) {

private void processOption(String mode) {
    if (mode.equals("select")) {
        ShowActivity(ProductActivity.class, Settings.SCREEN_PRODUCT);
    } else if (mode.equals("repeat")) {
        Settings.CurrentReport.repeatItem();
        ShowActivity(ActionActivity.class, Settings.SCREEN_ACTION);
    } else if (mode.equals("session")) {
        ShowActivity(SessionActivity.class, Settings.SCREEN_SESSION);
    } else { // mode equals "end"
        confirmFinish();
    }
}

private void ShowActivity(Class cls, int requestCode) {
    Intent activity = new Intent(this, cls);
    startActivityForResult(activity, requestCode);
}
</code></pre>

<hr>

<p>Then, the code from one of the other activities handling the finish() event:</p>

<pre><code>
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    setContentView(R.layout.options);

    Button btn;

    btn = (Button)findViewById(R.id.btnSelect);
    btn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = getIntent();
            intent.putExtra("mode", "select");
            setResult(RESULT_OK, intent);
            finish();
        }
    });

    btn = (Button)findViewById(R.id.btnRepeat);
    btn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = getIntent();
            intent.putExtra("mode", "repeat");
            setResult(RESULT_OK, intent);
            finish();
        }
    });
    btn.setEnabled(Settings.CurrentReport.hasPreviousItem());

    btn = (Button)findViewById(R.id.btnSession);
    btn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = getIntent();
            intent.putExtra("mode", "session");
            setResult(RESULT_OK, intent);
            finish();
        }
    });

    btn = (Button)findViewById(R.id.btnEnd);
    btn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = getIntent();
            intent.putExtra("mode", "end");
            setResult(RESULT_OK, intent);
            finish();
        }
    });

}

public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
            Intent i = getIntent();
            i.putExtra("mode", "end");
            setResult(RESULT_OK, i);
            finish();
            break;

    }
    return super.onKeyDown(keyCode, event);
}</code></pre>
