Activity being created twice on 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:

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

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:

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

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

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

Upvotes: 11

Views: 16813

Answers (4)

nzala
nzala

Reputation: 372

Add this to your Activity definition in AndroidManifest.xml:

android:launchMode = "singleTask"

Upvotes: 8

Sifundo Moyo
Sifundo Moyo

Reputation: 185

Add this to your Activity definition in AndroidManifest.xml:

android:launchMode = "singleInstance"

Upvotes: 2

pzulw
pzulw

Reputation: 1756

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.

Upvotes: 10

Cody Caughlan
Cody Caughlan

Reputation: 32758

When you call startActivityForResult it is telling Android that you want the result to be delivered to the Activity which is making that call. Which explains what you see when you logged GetImageActivity - onCreate (again).

Since you call startActivityForResult in your first activity, that is, GUIActivity than you should be calling setResult in GetImageActivity to properly pass back the result.

So in GetImageActivity.onActivityResult() right before you call finish() you should call setResult so that when you return back to GUIActivity it can handle the expected result.

Upvotes: 0

Related Questions