Q:

Android app losing data during orientation change

I've got an app that I've copied from a tutorial that captures an image with MediaStore.ACTION_IMAGE_CAPTURE.  I've got some kind of weirdness going on when I run the app on my phone.
The camera app itself is flipping its orientation a couple times during operation even though I am not moving the phone.  It briefly goes into landscape mode before returning to the tutorial app.  Consequently, the tutorial app is flipping back to portrait mode after control is returned to it, and the image is lost.  I tried setting the camera activity's orientation to landscape, and the image is not lost.  
But the layout of the app is intended for portrait mode.  Or, if I hold my camera in landscape orientation while capturing the photo, I can turn the phone after my app has returned to focus, and not lose the image.
I did some poking around on the web.  Someone on Stackoverflow mentioned that the change in orientation caused additional calls to onCreate.  "The reason that onCreate() is called is because when you do call the camera activity during the portrait orientation, it will change the orientation and destroy your previous activity."  I ran the app in debugging mode with breakpoints set in onCreate and in the onActivityResult methods.  It is indeed true that onCreate is getting called when I take the photo in portrait mode.  The order of calls is onCreate, onActivityResult, onCreate.  If I take the photo in landscape mode (which is where my camera app ends up either way), onCreate does not get called.  Now that I have some idea what is going on, how do I keep that from being a problem?  Here's what the app looks like now:
package com.example.testapp;

import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;

public class CameraActivity extends Activity implements View.OnClickListener {

    ImageButton ib;
    Button b;
    ImageView iv;
    Intent i;
    final static int cameraData = 0;
    Bitmap bmp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_activity);
        initialize();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        // TODO Auto-generated method stub
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.photo_activity);
        initialize();
    }

    private void initialize() {
        iv = (ImageView)findViewById(R.id.imageViewReturnedPicture);
        ib = (ImageButton)findViewById(R.id.imageButtonTakePicture);
        b = (Button)findViewById(R.id.buttonSetWallpaper);
        b.setOnClickListener(this);
        ib.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {

        case R.id.buttonSetWallpaper:
            try {
                WallpaperManager wm = WallpaperManager.getInstance(getApplicationContext());
                wm.setBitmap(bmp);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;

        case R.id.imageButtonTakePicture:
            i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(i, cameraData);
            break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            bmp = (Bitmap)extras.get("data");
            iv.setImageBitmap(bmp);
        }
    }
}

And here's what I have in the manifest for this activity:

                android:name="com.example.testapp.CameraActivity"
                android:label="Camera Activity"
                android:configChanges="orientation"
                android:screenOrientation="portrait" 
I've done considerable searching, but much of what I find lacks concrete examples.  I need to know what the code looks like, not just what feature to use.
My phone is an LG Motion.  Has anyone else run into this problem?  How can it be fixed?

A:

In the manifest , In each activity I use configChanges:
 <activity
        android:name=".MainActivity"
        android:configChanges="screenLayout|orientation|screenSize">

I hope that this help you.

A:

You'll have to override onRetainNonConfigurationInstance and use getLastNonConfigurationInstance to save/restore the bitmap.
Like this:
// during onCreate(Bundle), after initialise()
bmp = getLastNonConfigurationInstance();
if(bmp!=null){ iv.setImageBitmap(bmp); }
else { /* the image was not taken yet */ }

then on your activity u override:
@Override
public Object onRetainNonConfigurationInstance (){
     return bmp;
}

That will 'save' the bitmap during rotation.
edit:
example using suggested onSaveInstanceState that will work but is not advisable because it will use a lot of memory and be very slow but you'll need for other situations soon:
public class SomethingSomething extends Activity{

    String name="";
    int page=0;

    // This is called when the activity is been created
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

            // if you saved something on outState you can recover them here
            if(savedInstanceState!=null){
                name = savedInstanceState.getString("name");
                page = savedInstanceState.getInt("page");
            }
    }

    // This is called before the activity is destroyed
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

            outState.putString("name", name);
            outState.putInt("page", page);
    }
}

as you can see, the reason this solution is not good for your case is because the Android Bundle used on for this is Android special type of serialization that can handle primitives, Strings and Classes that implements Parcelable (those classes really only parcel their primitives). And even thou Bitmaps do implement Parcelable, it will be taking a lot of time to do a copy of every byte on the Bitmap to the bundle and will be doubling the already big memory consumption of a Bitmap.
Now let's see at a solution using the setRetainInstance (slightly copied from the example you can find on \sdk\extras\android\support\samples\Support4Demos\src\com\example\android\supportv4\app\FragmentRetainInstanceSupport.Java.
Make sure to also check the examples as it shows some other fancy tricks.
// This fragment will be managed by the framework but we won't built a UI for it.
public class FragRetained extends Fragment{
   public static final String TAG = "TAG.FragRetained";
   private Bitmap bitmap;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Tell the framework to try to keep this fragment around
        // during a configuration change.
        setRetainInstance(true);
    }
    public Bitmap getBitmap() { return bitmap; }
    public void setBitmap(Bitmap bmp) { bitmap = bmp; }
}

public class MyActivity extends Activity{

    private FragRetained myFragRetained;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
            // set the content view
            img = (ImageView)findViewById(R.id.byImgV);

            myFragRetained = getFragmentManger.findFragmentByTag(FragRetained.TAG);
            if(myFragRetained == null){
                myFragRetained = new FragRetained ();
            }else{
               Bitmap b = myFragRetained.getBitmap();
               if(b==null){
                  // the user still did not choose the photo
               }else{
                  img.setImageBitmap(b);
               }
            }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            bmp = (Bitmap)extras.get("data");
            iv.setImageBitmap(bmp);
            myFragRetained.setBitmap(bmp);
        }
    }

}

and make sure to remove the line android:configChanges="orientation" from your manifest because it's probably doing more harm then good, a small quote about it:

Note: Using this attribute should be avoided and used only as a
  last-resort. Please read Handling Runtime Changes for more information
  about how to properly handle a restart due to a configuration change.

A:

I went to a mobile development group meeting on Monday and got a hint.  A programmer who writes apps for a variety of platforms for a major company suggested attaching the bitmap to the application object.  As I looked at how I might do that, I finally came up with a solution that works (new question at end of post) based on suggestions in the following blog post:
http://android-er.blogspot.com/2011/10/share-bitmap-between-activities-as.html
Basically, this entailed setting up the bitmap as a common resource in a location where any activity in the app can access it.  I created a new class as follows:
package com.example.testapp;
 
import android.graphics.Bitmap;
 
public class CommonResources {
        public static Bitmap cameraBmp = null;
}

I then changed all references to bmp in CameraActivity.java to CommonResources.cameraBmp.
During initialization, if CommonResources.cameraBmp is not null, then I use it to set the bitmap in the ImageView.
onCreate and initialize now look like this:
@Override
protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
              super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_activity);
        initialize();
}

private void initialize() {
        iv = (ImageView)findViewById(R.id.imageViewReturnedPicture);
        ib = (ImageButton)findViewById(R.id.imageButtonTakePicture);
        b = (Button)findViewById(R.id.buttonSetWallpaper);
        if (CommonResources.cameraBmp != null) {
                   iv.setImageBitmap(CommonResources.cameraBmp);
           }
        b.setOnClickListener(this);
        ib.setOnClickListener(this);
}

And then, to do a little cleanup, I added onPause as follows:
@Override
protected void onPause() {
        // TODO Auto-generated method stub
              super.onPause();
        if (isFinishing()) {
                   // Save the bitmap.
                        CommonResources.cameraBmp = null;
           }
}

My big question now is this:  Have I handled the memory properly or have I created garbage collection issues?

