title: After configuration change in Camera, returns to app with empty ImageView
body: <p>I have not found anything online that addresses this particular issue. I have an activity that takes a photo or video using the Android camera app. It then returns from the camera with the image or video, and shows it in a view. Both my video and image, capture and show, work fine when I am in the same configuration. <strong>But if I start the camera from my app in say, portrait, then when I am in the camera app I decide to change it to landscape, then once I come back from the camera app, my image shows a blank <code>ImageView</code>.</strong> It works fine if I stay in the same configuration. Like when I start in portrait, and use the camera app also in portrait, then my <code>ImageView</code> shows the image upon returning. Since I cannot write code for the camera app, not sure how to handle this.</p>
  
  <p>However, my video has no trouble if I change orientation during use of the camera video. It displays fine when it comes back into my app,  no matter which orientation I am in in either the app or the camera app.</p>
  
  <p>But why does the image have problems? I've tried to save state in <code>onSaveInstanceState</code> and <code>onRestoreInstanceState</code>, but this does not affect anything. I get null values for all my variables in those methods, when I log them (for video too). I think because it might have more to do with my Intent data? But that's just a guess. I looked over the <code>Intent</code> and see nothing missing. The image intent is a little different from the video intent, so maybe I'm missing something. </p>
  
  <p>I do have 2 different <code>xml</code> files for the portrait and landscape layout, but they are identical and in the right folders. Android auto-chooses them when I do a configuration change.</p>
  
  <p>If anyone has tips, thanks very much.</p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>I tried to add a line of code in my manifest: <code>android:configChanges="keyboardHidden|orientation|screenSize"</code></p>
  
  <p>and I overrode <code>onConfigurationChanged()</code>,  but now my image comes back as a black screen. Both layout files are in my <code>layout</code> folder.</p>
  
  <pre><code>@Override
  public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
  
      // Checks the orientation of the screen
      if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
          setContentView(R.layout.activity_make_photo_video_land);
      } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
          setContentView(R.layout.activity_make_photo_video);
      }
  }
  </code></pre>
  
  <p><strong>UPDATE 2:</strong></p>
  
  <p>I undid everything I tried in UPDATE 1. Since that gave me a black screen and other unfixable bugs.</p>
  
  <p>This time, I have added a configuration selector in <code>onCreate</code> to manually change the view:</p>
  
  <pre><code>// Checks the orientation of the screen
          if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
              setContentView(R.layout.activity_make_photo_video_land);
              mImageView = (ImageView) findViewById(R.id.taken_photo_land);
          } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
              setContentView(R.layout.activity_make_photo_video);
              mImageView = (ImageView) findViewById(R.id.taken_photo);
          }
  </code></pre>
  
  <p>After more logging, I have realized when I change the configuration <strong>in the camera app</strong>, the following methods execute in this order (listed from 1st activity start):</p>
  
  <ol>
  <li><p><code>onCreate()</code></p></li>
  <li><p><code>onSavedInstanceState()</code> - I leave my app to go to the camera</p></li>
  <li><p><code>onCreate()</code> - I return from app with a photo, a log on mImageBitmap is null.</p></li>
  <li><p><code>onRestoreInstanceState()</code></p></li>
  <li><p><code>inActivityResult()</code> - then it processes the photo that is captured from camera.</p></li>
  </ol>
  
  <p>The only thing I persist in <code>onSavedInstanceState()</code> is the <code>mCurrentPhotoPath</code>, which is needed to run the <code>setPic()</code> method in <code>inActivityResult()</code>. </p>
  
  <p>In <code>onSavedInstanceState()</code>:
  <code>outState.putString("FILE_PATH", mCurrentPhotoPath);</code></p>
  
  <p>In <code>onCreate()</code>:</p>
  
  <pre><code>if (savedInstanceState != null) {
              mCurrentPhotoPath = savedInstanceState.getString("FILE_PATH");
     }
  </code></pre>
  
  <p>This processes fine, and a log on the bitmap value is not null. So why doesn't the image post still??</p>
  
  <p><strong>MakePhotoVideo.java</strong></p>
  
  <pre><code>package org.azurespot.makecute;
  
  import android.content.Context;
  import android.content.Intent;
  import android.content.pm.ActivityInfo;
  import android.content.pm.PackageManager;
  import android.content.pm.ResolveInfo;
  import android.content.res.Configuration;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.Matrix;
  import android.net.Uri;
  import android.os.Bundle;
  import android.os.Environment;
  import android.provider.MediaStore;
  import android.support.v7.app.ActionBarActivity;
  import android.util.Log;
  import android.view.Gravity;
  import android.view.MenuItem;
  import android.view.MotionEvent;
  import android.view.View;
  import android.widget.Button;
  import android.widget.ImageView;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  import android.widget.Toast;
  import android.widget.VideoView;
  
  import org.azurespot.R;
  import org.azurespot.cutecollection.CuteCollection;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.List;
  import java.util.Random;
  
  public class MakePhotoVideo extends ActionBarActivity {
  
      private static final int ACTION_TAKE_PHOTO = 1;
      private static final int ACTION_TAKE_VIDEO = 2;
      private static final String BITMAP_STORAGE_KEY = "viewbitmap";
      private static final String IMAGEVIEW_VISIBILITY_STORAGE_KEY = "imageviewvisibility";
      private ImageView mImageView;
      private Bitmap mImageBitmap;
  
      private static final String VIDEO_STORAGE_KEY = "viewvideo";
      private static final String VIDEOVIEW_VISIBILITY_STORAGE_KEY = "videoviewvisibility";
      private VideoView mVideoView;
      private Uri mVideoUri;
      private File fileVideo;
  
      private String mCurrentPhotoPath;
      String videoPath;
      private int position = 0;
  
      private static final String JPEG_FILE_PREFIX = "IMG_";
      private static final String JPEG_FILE_SUFFIX = ".jpg";
  
      private PhotoStorageDirFactory mPhotoStorageDirFactory = null;
  
  
  
      /* Photo album for this application */
      private String getAlbumName() {
          return getString(R.string.album_name);
      }
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_make_photo_video);
  
          mImageView = (ImageView) findViewById(R.id.taken_photo);
          mVideoView = (VideoView) findViewById(R.id.video_view);
          mVideoView.setVisibility(View.INVISIBLE);
          mImageView.setSaveEnabled(true);
  
          Button photoBtn = (Button) findViewById(R.id.click);
          setBtnListenerOrDisable(photoBtn, mTakePicOnClickListener, MediaStore.ACTION_IMAGE_CAPTURE);
  
          Button videoBtn = (Button) findViewById(R.id.record_video);
          setBtnListenerOrDisable(videoBtn,mTakeVidOnClickListener, MediaStore.ACTION_VIDEO_CAPTURE);
  
          mPhotoStorageDirFactory = new BasePhotoDirFactory();
  
          // Shows the up carat near app icon in ActionBar
          getSupportActionBar().setDisplayUseLogoEnabled(false);
          getSupportActionBar().setDisplayHomeAsUpEnabled(true);
  
      }
  
  
      public void viewCollection(View v){
  
          // finishes/restarts the activity so the unsaved video does not corrupt
          Intent intent = getIntent();
          finish();
          startActivity(intent);
  
          // goes to Cute Collection activity
          Intent i = new Intent(this, CuteCollection.class);
          startActivity(i);
      }
  
      private File getAlbumDir() {
          File storageDir = null;
  
          if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
  
              storageDir = mPhotoStorageDirFactory.getAlbumStorageDir(getAlbumName());
  
              if (storageDir != null) {
                  if (! storageDir.mkdirs()) {
                      if (! storageDir.exists()){
                          Log.d("Camera", "failed to create directory");
                          return null;
                      }
                  }
              }
  
          } else {
              Log.v(getString(R.string.app_name), "External storage is not mounted READ/WRITE.");
          }
  
          return storageDir;
      }
  
      private File createImageFile() throws IOException {
          // Create an image file name
          String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
          String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
          File albumF = getAlbumDir();
          File imageF = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX, albumF);
          return imageF;
      }
  
      private File setUpPhotoFile() throws IOException {
  
          File f = createImageFile();
          mCurrentPhotoPath = f.getAbsolutePath();
  
          return f;
      }
  
      private void setPic() {
  
          /* There isn't enough memory to open up more than a couple camera photos */
          /* So pre-scale the target bitmap into which the file is decoded */
  
          /* Get the size of the ImageView */
          int targetW = mImageView.getWidth();
          int targetH = mImageView.getHeight();
  
          /* Get the size of the image */
          BitmapFactory.Options bmOptions = new BitmapFactory.Options();
          bmOptions.inJustDecodeBounds = true;
          BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
          int photoW = bmOptions.outWidth;
          int photoH = bmOptions.outHeight;
  
          /* Figure out which way needs to be reduced less */
          int scaleFactor = 1;
          if ((targetW &gt; 0) || (targetH &gt; 0)) {
              scaleFactor = Math.min(photoW/targetW, photoH/targetH);
          }
  
          /* Set bitmap options to scale the image decode target */
          bmOptions.inJustDecodeBounds = false;
          bmOptions.inSampleSize = scaleFactor;
          bmOptions.inPurgeable = true;
  
          /* Decode the JPEG file into a Bitmap */
          mImageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
  
  
          if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
              mImageBitmap = rotateBitmap(mImageBitmap, 90);
          }
  
          savePhoto(mImageBitmap);
  
          /* Associate the Bitmap to the ImageView, make sure the VideoView
           * is cleared to replace with ImageView */
          mImageView.setImageBitmap(mImageBitmap);
  
          Log.d("TAG", "Value of mImageBitmap inside setPic(): " + mImageBitmap);
          mVideoUri = null;
          mImageView.setVisibility(View.VISIBLE);
          mVideoView.setVisibility(View.INVISIBLE);
  
      }
  
      // save your photo to SD card
      private void savePhoto(final Bitmap bitmapPhoto){
          // set OnClickListener to save the photo
          mImageView.setOnClickListener(new View.OnClickListener() {
              public void onClick(View v) {
                  boolean success = false;
  
                  File photoDir = new File(Environment.getExternalStoragePublicDirectory
                          (Environment.DIRECTORY_PICTURES) + "/Cute Photos");
                  photoDir.mkdirs();
                  Random generator = new Random();
                  int n = 10000;
                  n = generator.nextInt(n);
                  String photoName = "Photo"+ n +".jpg";
                  File filePhoto = new File (photoDir, photoName);
  //                if (filePhoto.exists ()) filePhoto.delete ();
                  try {
                      FileOutputStream out = new FileOutputStream(filePhoto);
                      bitmapPhoto.compress(Bitmap.CompressFormat.JPEG, 100, out);
                      out.flush();
                      out.close();
                      success = true;
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
  
                  if (success) {
                      Toast toast = Toast.makeText(getApplicationContext(), "Cute photo saved!",
                              Toast.LENGTH_LONG);
                      LinearLayout toastLayout = (LinearLayout) toast.getView();
                      toastLayout.setBackgroundColor(getResources().getColor(R.color.toast_color));
                      TextView toastTV = (TextView) toastLayout.getChildAt(0);
                      toastTV.setTextSize(30);
                      toast.setGravity(Gravity.CENTER_VERTICAL, 0, 80);
                      toast.show();
                  } else {
                      Toast.makeText(getApplicationContext(),
                              "Error during image saving", Toast.LENGTH_SHORT).show();
                  }
  
              }
          });
      }
  
  
      // save your video to SD card
      protected void saveVideo(final Uri uriVideo){
  
          // click the video to save it
          mVideoView.setOnTouchListener(new View.OnTouchListener() {
  
              public boolean onTouch(View v, MotionEvent event) {
  
                  boolean success = false;
  
                  if(event.getAction() == MotionEvent.ACTION_UP) {
  
                      try {
                          // make the directory
                          File vidDir = new File(android.os.Environment.getExternalStoragePublicDirectory
                                  (Environment.DIRECTORY_MOVIES) + File.separator + "Cute Videos");
                          vidDir.mkdirs();
  
                          // create unique identifier
                          Random generator = new Random();
                          int n = 100;
                          n = generator.nextInt(n);
                          // create file name
                          String videoName = "Video" + n + ".mp4";
  
                          fileVideo = new File(vidDir.getAbsolutePath(), videoName);
  
                          videoPath = fileVideo.getAbsolutePath();
  
                          Log.d("TAG", "Value of videoPath:" + videoPath);
  
                          fileVideo.setWritable(true, false);
  
                          OutputStream out = new FileOutputStream(fileVideo);
                          InputStream in = getContentResolver().openInputStream(uriVideo);
  
                          byte buffer[] = new byte[1024];
                          int length = 0;
                          while ((length = in.read(buffer)) &gt; 0) {
                              out.write(buffer, 0, length);
                          }
  
                          out.close();
                          in.close();
  
                          success = true;
  
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
  
                      if (success) {
                          Toast toast = Toast.makeText(getApplicationContext(), "Cute video saved!",
                                  Toast.LENGTH_SHORT);
                          LinearLayout toastLayout = (LinearLayout) toast.getView();
                          toastLayout.setBackgroundColor(getResources().getColor(R.color.toast_color));
                          TextView toastTV = (TextView) toastLayout.getChildAt(0);
                          toastTV.setTextSize(30);
                          toast.setGravity(Gravity.CENTER_VERTICAL, 0, 80);
                          toast.show();
                      } else {
                          Toast.makeText(getApplicationContext(),
                                  "Error during video saving", Toast.LENGTH_SHORT).show();
                      }
                  }
  
                  return true;
              }
          });
      }
  
  
      public Bitmap rotateBitmap(Bitmap source, int angle)
      {
          Matrix matrix = new Matrix();
          matrix.set(matrix);
          matrix.setRotate(angle);
          return Bitmap.createBitmap(source, 0, 0, source.getWidth(),
                  source.getHeight(), matrix, false);
      }
  
      private void galleryAddPic() {
          Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
          File f = new File(mCurrentPhotoPath);
          Uri contentUri = Uri.fromFile(f);
          mediaScanIntent.setData(contentUri);
          this.sendBroadcast(mediaScanIntent);
      }
  
      private void dispatchTakePictureIntent(int actionCode) {
          Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  
          switch(actionCode) {
              case ACTION_TAKE_PHOTO:
                  File f;
  
                  try {
                      f = setUpPhotoFile();
                      mCurrentPhotoPath = f.getAbsolutePath();
                      takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                  } catch (IOException e) {
                      e.printStackTrace();
                      f = null;
                      mCurrentPhotoPath = null;
                  }
                  break;
  
              default:
                  break;
          } // switch
  
          startActivityForResult(takePictureIntent, actionCode);
      }
  
      // Captures video from Android camera component
      protected void dispatchTakeVideoIntent() {
          Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
          if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
              // set the video image quality to high
              takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
              startActivityForResult(takeVideoIntent, ACTION_TAKE_VIDEO);
          }
      }
  
      private void handleCameraPhoto() {
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
  
          Log.d("TAG", "Value of mCurrentPhotoPath: " + mCurrentPhotoPath);
  
  
          if (mCurrentPhotoPath != null) {
              setPic();
              galleryAddPic();
              mCurrentPhotoPath = null;
          }
  
      }
      // Post recorded video into VideoView
      private Uri handleCameraVideo(Intent intent) {
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
  
          mVideoUri = intent.getData();
          mVideoView.setVideoURI(mVideoUri);
  //        mImageBitmap = null;
          mVideoView.setVisibility(View.VISIBLE);
          mImageView.setVisibility(View.INVISIBLE);
          mVideoView.start();
          // saves video to file
          saveVideo(mVideoUri);
  
          return mVideoUri;
  
      }
  
      // click listener for the Android Camera button (not my app's button)
      Button.OnClickListener mTakePicOnClickListener =
              new Button.OnClickListener() {
                  @Override
                  public void onClick(View v) {
  //                    mImageBitmap = null;
                      dispatchTakePictureIntent(ACTION_TAKE_PHOTO);
                      // releases the orientation lock
                      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                  }
              };
      Button.OnClickListener mTakeVidOnClickListener =
              new Button.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      dispatchTakeVideoIntent();
                      // releases the orientation lock
                      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                  }
              };
  
  
      // Intent data is how the photo and video transfer into their views
      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          switch (requestCode) {
              case ACTION_TAKE_PHOTO: {
                  if (resultCode == RESULT_OK) {
                      handleCameraPhoto();
                  } else {
                      Log.d("TAG", "Result of photo not work.");
                  }
                  break;
              } // ACTION_TAKE_PHOTO
  
              case ACTION_TAKE_VIDEO: {
                  if (resultCode == RESULT_OK) {
                      handleCameraVideo(data);
                  }
                  break;
              } // ACTION_TAKE_VIDEO
          } // switch
      }
  
  
      // Some lifecycle callbacks so that the image can survive orientation change
      @Override
      protected void onSaveInstanceState(Bundle outState) {
          outState.putParcelable(BITMAP_STORAGE_KEY, mImageBitmap);
          outState.putParcelable(VIDEO_STORAGE_KEY, mVideoUri);
          outState.putBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY, (mImageBitmap != null) );
          outState.putBoolean(VIDEOVIEW_VISIBILITY_STORAGE_KEY, (mVideoUri != null) );
          outState.putString("FILE_PATH", mCurrentPhotoPath);
  
  
          if (mVideoUri != null) {
              // use onSaveInstanceState in order to store the video or photo
              outState.putInt("PositionVideo", mVideoView.getCurrentPosition());
              // playback position for orientation change
              mVideoView.pause();
          }
  
          // super should be last in this method
          super.onSaveInstanceState(outState);
  
      }
  
      @Override
      protected void onRestoreInstanceState(Bundle savedInstanceState) {
  
  
          mCurrentPhotoPath = savedInstanceState.getString("FILE_PATH");
  
          mImageView.setImageBitmap(mImageBitmap);
          mImageView.setVisibility(
                  savedInstanceState.getBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY) ?
                          ImageView.VISIBLE : ImageView.INVISIBLE
          );
  
  
          mVideoUri = savedInstanceState.getParcelable(VIDEO_STORAGE_KEY);
  
  
          mVideoView.setVideoURI(mVideoUri);
          mVideoView.setVisibility(
                  savedInstanceState.getBoolean(VIDEOVIEW_VISIBILITY_STORAGE_KEY) ?
                          ImageView.VISIBLE : ImageView.INVISIBLE
          );
  
  
          if (mVideoUri != null) {
              // for video, restores position it was playing
              position = savedInstanceState.getInt("PositionVideo");
              mVideoView.seekTo(position);
          }
  
  
          super.onRestoreInstanceState(savedInstanceState);
  
  
      }
  
      /**
       * Indicates whether the specified action can be used as an intent. This
       * method queries the package manager for installed packages that can
       * respond to an intent with the specified action. If no suitable package is
       * found, this method returns false.
       * http://android-developers.blogspot.com/2009/01/can-i-use-this-intent.html
       *
       * @param context The application's environment.
       * @param action The Intent action to check for availability.
       *
       * @return True if an Intent with the specified action can be sent and
       *         responded to, false otherwise.
       */
      public static boolean isIntentAvailable(Context context, String action) {
          final PackageManager packageManager = context.getPackageManager();
          final Intent intent = new Intent(action);
          List&lt;ResolveInfo&gt; list =
                  packageManager.queryIntentActivities(intent,
                          PackageManager.MATCH_DEFAULT_ONLY);
          return list.size() &gt; 0;
      }
  
      private void setBtnListenerOrDisable(Button btn, Button.OnClickListener onClickListener,
                                                                          String intentName) {
          if (isIntentAvailable(this, intentName)) {
              btn.setOnClickListener(onClickListener);
  
          } else {
              btn.setClickable(false);
          }
      }
  
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
  
          // Makes the UP caret go back to the previous fragment MakeCuteFragment
          switch (item.getItemId()) {
              case android.R.id.home:
                  android.app.FragmentManager fm= getFragmentManager();
                  fm.popBackStack();
                  finish();
  
                  return true;
              default:
                  return super.onOptionsItemSelected(item);
          }
      }
  
  }
  </code></pre>