相机在方向上崩溃

时间:2014-12-22 19:05:04

标签: android image camera orientation config

我正在使用https://github.com/jdamcd/android-crop中的裁剪图像库来获取图库和相机中的图像。如果我从相机获取图像后没有改变方向,它在相机上工作正常。但是当我在裁剪之前单击图像后更改方向时,应用程序崩溃。很少有博客告诉我使用android:configChanges="orientation|keyboardHidden|screenSize",但却没有成功。即使我已经将Manifest文件的方向锁定在我称之为裁剪方法的活动上。我的代码和错误堆栈如下:

package eu.janmuller.android.simplecropimage.example;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import eu.janmuller.android.simplecropimage.CropImage;

public class MainActivity extends Activity {

    public static final String TAG = "MainActivity";

    public static final String TEMP_PHOTO_FILE_NAME = "temp_photo.jpg";
    private File      mFileTemp;
    public static final int REQUEST_CODE_GALLERY      = 0x1;
    public static final int REQUEST_CODE_TAKE_PICTURE = 0x2;
    public static final int REQUEST_CODE_CROP_IMAGE   = 0x3;

    private ImageView mImageView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);    //To change body of overridden methods use File | Settings | File Templates.
        setContentView(R.layout.main);

        findViewById(R.id.gallery).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                openGallery();
            }
        });

        findViewById(R.id.take_picture).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                takePicture();
            }
        });

        mImageView = (ImageView) findViewById(R.id.image);

        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            mFileTemp = new File(Environment.getExternalStorageDirectory(), TEMP_PHOTO_FILE_NAME);
        }
        else {
            mFileTemp = new File(getFilesDir(), TEMP_PHOTO_FILE_NAME);
        }

    }

    private void takePicture() {

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        try {
            Uri mImageCaptureUri = null;
            String state = Environment.getExternalStorageState();
            if (Environment.MEDIA_MOUNTED.equals(state)) {
                mImageCaptureUri = Uri.fromFile(mFileTemp);
            }
            else {
                /*
                 * The solution is taken from here: http://stackoverflow.com/questions/10042695/how-to-get-camera-result-as-a-uri-in-data-folder
                 */
                mImageCaptureUri = InternalStorageContentProvider.CONTENT_URI;
            }   
            intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
            intent.putExtra("return-data", true);
            startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);
        } catch (ActivityNotFoundException e) {

            Log.d(TAG, "cannot take picture", e);
        }
    }

    private void openGallery() {

        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
        photoPickerIntent.setType("image/*");
        startActivityForResult(photoPickerIntent, REQUEST_CODE_GALLERY);
    }

    private void startCropImage() {

        Intent intent = new Intent(this, CropImage.class);
        intent.putExtra(CropImage.IMAGE_PATH, mFileTemp.getPath());
        intent.putExtra(CropImage.SCALE, true);
        intent.putExtra(CropImage.ASPECT_X, 3);
        intent.putExtra(CropImage.ASPECT_Y, 3);

        startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode != RESULT_OK) {

            return;
        }

        Bitmap bitmap;

        switch (requestCode) {

            case REQUEST_CODE_GALLERY:

                try {

                    InputStream inputStream = getContentResolver().openInputStream(data.getData());
                    FileOutputStream fileOutputStream = new FileOutputStream(mFileTemp);
                    copyStream(inputStream, fileOutputStream);
                    fileOutputStream.close();
                    inputStream.close();

                    startCropImage();

                } catch (Exception e) {

                    Log.e(TAG, "Error while creating temp file", e);
                }

                break;
            case REQUEST_CODE_TAKE_PICTURE:

                startCropImage();
                break;
            case REQUEST_CODE_CROP_IMAGE:

                String path = data.getStringExtra(CropImage.IMAGE_PATH);
                if (path == null) {

                    return;
                }

                bitmap = BitmapFactory.decodeFile(mFileTemp.getPath());
                mImageView.setImageBitmap(bitmap);
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }


    public static void copyStream(InputStream input, OutputStream output)
            throws IOException {

        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = input.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
        }
    }

}

错误堆栈如下:

12-22 23:11:03.372: E/AndroidRuntime(3617): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41bd8728
12-22 23:11:03.372: E/AndroidRuntime(3617):     at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)
12-22 23:11:03.372: E/AndroidRuntime(3617):     at android.graphics.Canvas.drawBitmap(Canvas.java:1096)
12-22 23:11:03.372: E/AndroidRuntime(3617):     at android.graphics.Bitmap.createBitmap(Bitmap.java:625)
12-22 23:11:03.372: E/AndroidRuntime(3617):     at eu.janmuller.android.simplecropimage.CropImage$1.prepareBitmap(CropImage.java:572)
12-22 23:11:03.372: E/AndroidRuntime(3617):     at eu.janmuller.android.simplecropimage.CropImage$1.run(CropImage.java:578)
12-22 23:11:03.372: E/AndroidRuntime(3617):     at eu.janmuller.android.simplecropimage.CropImage$6.run(CropImage.java:285)
12-22 23:11:03.372: E/AndroidRuntime(3617):     at eu.janmuller.android.simplecropimage.Util$BackgroundJob.run(Util.java:175)
12-22 23:11:03.372: E/AndroidRuntime(3617):     at java.lang.Thread.run(Thread.java:838)

提前致谢。

1 个答案:

答案 0 :(得分:1)

您正在尝试绘制已经回收的位图。看起来它意味着你用来裁剪图像 - 它重写了一个已被破坏的位图。我的猜测是库有一个错误,它在onStop中回收位图以提高效率,但是没有意识到Bitmap仍然可以被库中的AsyncTask或Thread使用,而且它们不会检查看它是否先回收。您可以通过添加一些isRecycled()检查来修复他的库,但我的猜测还有其他竞争条件。您可以通过将configChanges行添加到他的图书馆活动中来修复它,这样他们就不会在轮换中进行活动重建。

但问题出在他的图书馆,而不是你的代码。