bursk
bursk

Reputation: 1667

Android finishActivity always causing onActivityResult to get RESULT_CANCELED

I have a main Activity A that can kick off sub-Activities B, C, or D. I start them using startActivityForResult(newIntent, REQUEST_CODE);

The user can choose to navigate between B, C, and D once one is displayed. Activity A controls that navigation. When they choose swap between screens 'A' first calls finishActivity(REQUEST_CODE); on the one displayed and then call startActivityForResult(newIntent, REQUEST_CODE); for the next one.

In my onActivityResult I've got

    protected void onActivityResult(int requestCode, int resultCode, Intent data)
   {
      // these logs are just for my debugging
      Log.w(this.toString(), "onActivityResult returned to by " + requestCode);
      Log.w(this.toString(), "result code = " + resultCode );

      // the Activity set this value if it was returning normally
      if (RESULT_OK == resultCode)
      {
         Log.i(this.toString(), "---- the sub-activity returned OK ----"); 
         // do some stuff    

      }// end if (RESULT_OK == resultCode)
      // Else we got here because the user hit the back button or something went
      // went wrong (RESULT_CANCELED).  Either way we do not want to display this
      // blank screen to the user.  Take them back to the device connection screen.
      else if (RESULT_CANCELED == resultCode)
      {    
         finish();
      }
    }

For some reason I'm getting back a zero or RESULT_CANCELED everytime even though in my sub-activities B,C,D I only set that result if the user chooses to hit the back button (I display an "are you sure" dialog and they choose to exit. In B,C,D I have the following in onPause. The userExiting is a flag I set from the Exit dialog.

protected void onPause()
   {
      Log.i(this.toString(), "onPause");

      // hack to try to setResult for an activity whose finishActivty was called
      if ( !this.exiting ) 
      {
         Log.i(this.toString(), "======== RESULT_OK ========"); 
         Intent returnIntent = new Intent();
         setResult(RESULT_OK, returnIntent);
         finish();
      }

      displayed = false;

      super.onPause();
   }

Any ideas?

Edit - to be clear the issue is that after calling finishActivty on the old Activity, since a result was never set, Activity A always thinks it should exit. One weird side items. This doesn't happen until the user navigates two times. In other words B is displayed and they choose to go to C. Works, but I can see in the log that onActivityResult hasn't been called. User selects to go from C to D, boom, I see two calls to onActivtyResult, 'A; exits and D is left displayed and the user is unable to nav away.

Update: Since this has been getting a lot of views I thought I'd post this update. The project evolved such that sometimes a single Activity is displays and sometimes a group are displayed as tabs. When the user packs out of the tab in some cases data needed to be returned to the Activity that kicked off the tabs. Before I added the code below RESULT_CANCELED would always be returned. Also make sure that setResult is called before finish.

 if (getParent() == null)
 {
    setResult(Activity.RESULT_OK, intent);
 }
 else
 {
    getParent().setResult(Activity.RESULT_OK, intent);
 }

Upvotes: 0

Views: 6352

Answers (1)

Cheryl Simon
Cheryl Simon

Reputation: 46844

I'm not quite following everything you are doing here, but it doesn't sound like you are navigating between activities properly. I would highly suggest reading through the notepad example thoroughly so that you understand the android way of moving between Activities.

Here is what I understand regarding what you are trying to accomplish: Activity A can navigate to B, C or D. From B, C or D you can navigate to any of the others.

You are somehow trying to using Activity A as a controller, having it finish other Activities. Don't do this. Each Activity should be responsible for finishing itself at the proper point.

If you want to go from having A -> B on the stack to A -> C, then I would do this:

A starts B for result. When user selects something in B asking to go to C you have a few choices. You could have B start C not for result, then finish. This would have the effect of B being removed from the stack when C exits. Or, you could have B finish itself, passing back a note that C should be loaded in the results intent. A could then load C for result.

I'm really not sure why you want this behavior though. As an Android user, if I go from A -> B -> C, I expect hitting back to take me back to B.

As an aside, your "is exiting" hack doesn't make any sense. By the time you get to onPause, the result has been set. You cannot change it here. You need to properly set the result when you are finishing, before onPause.

Upvotes: 2

Related Questions