Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Activity being created twice on android

Tags:

java

android

First of all, I'm new to Android Development so please have patience with me.

I'll start from the UI, I have a button that once you tap it, starts an activity for a result.

public class GUIActivity extends Activity

    @Override
    public void onClick(....){
        Intent intent = new Intent(getApplicationContext(), GetImageActivity.class);
        intent.putExtra("action", FROM_CAMERA);
        startActivityForResult(intent, GET_IMAGE);
    }

    @Override
    onActivityResult(int requestCode, int resultCode, Intent data){
        Log(TAG, "onActivityResult");
        //handle result
    }

}

The GetImageActivity class is a wrapper for two other activities, one to capture an image from the camera and other to get it from the gallery. It returns and Uri object of the selected image.

public class GetImageActivity extends Activity{
    private Uri mediaUri;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        Bundle extras = getIntent().getExtras();
        int action =  extras.getInt("action");

        Log.d(TAG, "onCreate");

        switch(action){
            case FROM_CAMERA:
                mediaUri = Uri.fromFile(new File(....));
                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, mediaUri);

                Log.d(TAG, "Calling camera activity"
                startActivityForResult(intent, action);
                break;
            case FROM GALLERY:
                //...
        }            
    }

    @Override
    onActivityResult(int requestCode, int resultCode, Intent data){
        Log.d(TAG, "onActivityResult");

        switch(requestCode){
            case FROM_CAMERA:
                if(resultCode == Activity.RESULT_OK){
                    Intent data = new Intent();
                    data.putExtra("uri", mediaUri);
                    setResult(Activity.RESULT_OK, data);
                    finish();
                }else{
                    Log.e(TAG, "Camera activity failed!");
                    setResult(Activity.RESULT_CANCELED);
                    finish();
                }
                break;

            case FROM_GALLERY:
                //...

        }
    }
}

This is what is expected to happen when the user clicks on the button:

  • The camera activity should start.
  • Once the user takes a picture it should send back its URI to the GUI class.

Sometimes (it's usually a 50% chance) it works at expected, but other times this is what happens:

  • The camera activity starts.
  • The user takes a picture.
  • The camera activity starts AGAIN.
  • The user can either take another picture or go back.
  • Either case, the URI that gets back to the GUI class does not exist.

I've added a couple of debug log lines to follow the sequence of events. When I get the bad behaviour this is the output I get:

  • GetImageActivity - onCreate
  • GetImageActivity - Calling Camera Activity

The camera opens, and once I've taken a picture it says:

  • GetImageActivity - onCreate (again)
  • GetImageActivity - Calling Camera Activity
  • GetImageActivity - onActivityResult

The camera opens for the second time. The user takes another picture and:

  • GetImageActivity - onActivityResult
  • GUIActivity - onActivityResult

So my question is... what could cause the GetImageActivity to be called twice?

like image 928
Juan Enrique Muñoz Zolotoochin Avatar asked Mar 06 '12 00:03

Juan Enrique Muñoz Zolotoochin


1 Answers

The problem is improper handling of the Activity lifecycle.

The second call to onCreate is for handling the result.

Android may choose to destroy an Activity that is waiting for the call to onActivityResult; especially when free memory is running low. Some devices appear more aggressive about destroying Activitys that are on the task stack. I can reliably recreate the issue on a Samsung device set to a debugging mode called "strict mode".

You can verify whether this is your issue by logging calls to onCreate & onDestroy.

In the case of a destroyed activity, when the activity result needs to be processed, Android will recreate the Activity, passing a savedInstanceState to onCreate. So, the remedy is to check the value of savedInstanceState in your GetImageActivity.onCreate. If it is not null then don't make any calls to startActivity because your Activity is being recreated to call onActivityResult.

Optionally, if you need to preserve any state then override onSaveInstanceState(Bundle outState) and put data you need into outState.

like image 156
pzulw Avatar answered Nov 28 '22 01:11

pzulw