1

This is my first post and while I am new to Android, this community has been great so far.

Here is the trouble I am having with my relatively simple application.

I have a image view on my main activity. onClick, the image view will open up the Camera application. I can take a picture and the camera application will return that picture and set it as the picture in the image view.

The main activity will crash when I start in one orientation and take a picture in another. Example: I open the main activity initially in a vertical orientation, open the camera application and switch to a horizontal view, and take a picture. When the camera application tries to return the picture the main activity crashes. The application does not crash when all activities are used in the same orientation.

I'm lead to believe it's either the way that I am saving the picture or that on onResume, the main activity doesn't have enough time to switch to the new orientation and receive the picture before it crashes.... or maybe that it simply destroys the picture when the main activity is resumed.

public class mainActivity extends Activity {

static final int REQUEST_IMAGE_CAPTURE = 1;

//Declares variable of mImageView
ImageView mImageView;
String mCurrentPhotoPath;
//String activityOrientation;

File photoFile = null;

Uri uriFile;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Setting mImageView to the UI ID of
    mImageView = (ImageView) findViewById(R.id.imageViewLicense); // making mImageView = the        license image view right now just to make sure the code works, I can add to later when adding the medical card 

}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState.containsKey("cameraImageUri")) {
        uriFile = Uri.parse(savedInstanceState.getString("cameraImageUri"));
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (uriFile != null) {
        outState.putString("cameraImageUri", uriFile.toString());
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}


//Initialized the camera to take a picture then return the result of the picture


public void dispatchTakePictureIntent(View view)
{
    //Create new intent
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    // Ensure that there's a camera activity to handle the intent
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        // Create the File where the photo should go

        try {
            photoFile = createImageFile();
        } catch (IOException ex) {

        }
        // Continue only if the File was successfully created
        if (photoFile != null) {

            uriFile = Uri.fromFile(photoFile);

            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                    uriFile);
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }
}

//Method for rotating the image of the bitmap to the corrected orientation
private Bitmap adjustImageOrientation(Bitmap image) {
    ExifInterface exif;
    try {
        exif = new ExifInterface(mCurrentPhotoPath);
        int exifOrientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        int rotate = 0;
        switch (exifOrientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotate = 90;
                break;

            case ExifInterface.ORIENTATION_ROTATE_180:
                rotate = 180;
                break;

            case ExifInterface.ORIENTATION_ROTATE_270:
                rotate = 270;
                break;
        }

        if (rotate != 0) {
            int w = image.getWidth();
            int h = image.getHeight();

            // Setting pre rotate
            Matrix mtx = new Matrix();
            mtx.preRotate(rotate);

            // Rotating Bitmap & convert to ARGB_8888, required by tess
            image = Bitmap.createBitmap(image, 0, 0, w, h, mtx, false);

        }
    } catch (IOException e) {
        return null;
    }
    return image.copy(Bitmap.Config.ARGB_8888, true);
}
//The photo taken in the takePicture method is returned here
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

            // Get the dimensions of the View
            int targetW = mImageView.getWidth();
            int targetH = mImageView.getHeight();

            // Get the dimensions of the bitmap
            BitmapFactory.Options bmOptions = new BitmapFactory.Options();
            bmOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
            int photoW = bmOptions.outWidth;
            int photoH = bmOptions.outHeight;

            // Determine how much to scale down the image
            int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

            // Decode the image file into a Bitmap sized to fill the View
            bmOptions.inJustDecodeBounds = false;
            bmOptions.inSampleSize = scaleFactor;



            bmOptions.inPurgeable = true;

            Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);


            //Rotates the image to the proper orientation
            Bitmap adjustedBitmap = adjustImageOrientation(bitmap);

            //Sets the original imageview as picture taken.
            mImageView.setImageBitmap(adjustedBitmap);


}

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}


}

2 Answers2

1

Android restarts the main activity when the orientation changes so you'll need to disable or handle that. You can find out more here: How do I disable orientation change on Android?

Community
  • 1
  • 1
Larry Borsato
  • 394
  • 3
  • 5
1

The accepted answer is bad practice, see Why not use always android:configChanges="keyboardHidden|orientation"?.

It would be a better idea to save your mCurrentPhotoPath variable.

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putString("filepath", mCurrentPhotoPath);
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle state) {
    mCurrentPhotoPath = state.getString("filepath");
    super.onRestoreInstanceState(state);
}
Community
  • 1
  • 1
tachyonflux
  • 19,305
  • 6
  • 43
  • 65