Android 使用三星Galaxy SII拍摄的BitmapFactory.decodeByteArray期间发生OutOfMemory错误

Android 使用三星Galaxy SII拍摄的BitmapFactory.decodeByteArray期间发生OutOfMemory错误,android,android-camera,out-of-memory,Android,Android Camera,Out Of Memory,从相机拍摄的图片创建位图时,我遇到OutOfMemory错误。在得到异常之前,我的代码可以正常工作几次,所以我花了几个小时寻找内存泄漏 奇怪的是,我将代码追溯到PictureCallback只是为了检查字节数组的大小:当没有引发异常时,它大约是280k,但最终,我收到了一个超过1.2M的字节数组,这时decodeByteArray崩溃 我正在使用自定义的CameraActivity。初始化相机的代码如下所示 camera = Camera.open(); camera.setDisplayOri

从相机拍摄的图片创建位图时,我遇到OutOfMemory错误。在得到异常之前,我的代码可以正常工作几次,所以我花了几个小时寻找内存泄漏

奇怪的是,我将代码追溯到PictureCallback只是为了检查字节数组的大小:当没有引发异常时,它大约是280k,但最终,我收到了一个超过1.2M的字节数组,这时decodeByteArray崩溃

我正在使用自定义的CameraActivity。初始化相机的代码如下所示

camera = Camera.open();
camera.setDisplayOrientation(cameraOrientation);            
Camera.Parameters params = camera.getParameters();
Size size = getPreferredPictureSize();
params.setPictureSize(size.width, size.height);
params.setJpegQuality(JPEG_QUALITY);
params.setPictureFormat(ImageFormat.JPEG);
camera.stopPreview();
camera.setParameters(params);
camera.startPreview();
if (camera != null) {
    camera.stopPreview();
    camera.release();
    camera = null;
}
当我的相机活动暂停时,我会像这样释放相机

camera = Camera.open();
camera.setDisplayOrientation(cameraOrientation);            
Camera.Parameters params = camera.getParameters();
Size size = getPreferredPictureSize();
params.setPictureSize(size.width, size.height);
params.setJpegQuality(JPEG_QUALITY);
params.setPictureFormat(ImageFormat.JPEG);
camera.stopPreview();
camera.setParameters(params);
camera.startPreview();
if (camera != null) {
    camera.stopPreview();
    camera.release();
    camera = null;
}

为什么在相同的初始化条件下,返回的图片可以有如此不同的大小?我可以错过一些完全释放相机的方法吗?任何线索都值得赞赏:

我在这里发现了几个问题,但我通过每次拍照时重置相机参数,成功地停止了接收不同大小的阵列。这里是我的CameraUtils实现,以防有人发现它有用

import java.util.List;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;

public class CameraUtils implements Camera.AutoFocusCallback {
    private static CameraUtils singleton = null;
    private Camera camera = null;
    private boolean isFocusing;
    private PictureCallback pictureCallback;
    private int cameraOrientation = 90; 
    private Size pictureSize;
    private final String CAMERA_FLASH_MODE_ON = "on";
    private final String CAMERA_FLASH_MODE_OFF = "off";
    private final int PHOTO_HEIGHT_THRESHOLD = 960;
    private final int JPEG_QUALITY = 90;    
    private String cameraFlashMode;
    private float defaultCameraRatio;

    private CameraUtils() {
    }

    public static CameraUtils getInstance() {
        if (singleton == null) {
            singleton = new CameraUtils();
        }

        return singleton;
    }

    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        isFocusing = false;

        if (CAMERA_FLASH_MODE_ON.equals(cameraFlashMode)) {
            setFlashEnabled(true);
        }

        if (pictureCallback != null) {
            setupParameters();
            Application.getInstance().getCurrentActivity().showLoading();
            camera.takePicture(null, null, pictureCallback);
        }
    }

    public boolean checkCameraHardware() {
        if (Application.getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            return true;
        } else {
            return false;
        }
    }

    public Camera getCamera() throws Exception {
        if (camera == null) {
            isFocusing = false;
            pictureCallback = null;
            camera = Camera.open();
            camera.setDisplayOrientation(cameraOrientation);
            setupParameters();
        }
        return camera;
    }

    public void setupParameters() {
        Camera.Parameters params = camera.getParameters();
        defaultCameraRatio = (float) params.getPictureSize().width / (float) params.getPictureSize().height;
        Size size = getPreferredPictureSize();
        params.setPictureSize(size.width, size.height);
        params.setJpegQuality(JPEG_QUALITY);
        params.setPictureFormat(ImageFormat.JPEG);    
        camera.stopPreview();
        camera.setParameters(params);
        camera.startPreview();
        pictureSize = size;
    }

    public void autofocus(boolean forceAutofocus) {
        if (camera != null && (!isFocusing || forceAutofocus)) {
            camera.cancelAutoFocus();
            disableFlash();
            isFocusing = true;
            camera.autoFocus(this);
        }
    }

    public void releaseCamera() {
        if (camera != null) {
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    }

    public void setFlashEnabled(boolean enabled) {
        if (camera != null) {
            if (enabled) {
                if (camera.getParameters().getSupportedFlashModes().contains(CAMERA_FLASH_MODE_ON)) {
                    Camera.Parameters params = camera.getParameters();
                    params.setFlashMode(CAMERA_FLASH_MODE_ON);
                    camera.setParameters(params);

                    cameraFlashMode = CAMERA_FLASH_MODE_ON;
                }
            } else {
                if (camera.getParameters().getSupportedFlashModes().contains(CAMERA_FLASH_MODE_OFF)) {
                    Camera.Parameters params = camera.getParameters();
                    params.setFlashMode(CAMERA_FLASH_MODE_OFF);
                    camera.setParameters(params);

                    cameraFlashMode = CAMERA_FLASH_MODE_OFF;
                }
            }
        }
    }

    public void disableFlash() {
        Camera.Parameters params = camera.getParameters();
        params.setFlashMode(CAMERA_FLASH_MODE_OFF);
        camera.setParameters(params);
    }

    public void takePhoto(PictureCallback pictureCallback) throws Exception {
        this.pictureCallback = pictureCallback;
        autofocus(true);
    }

    private Size getPreferredPictureSize() {
        Size res = null;
        List<Size> sizes = camera.getParameters().getSupportedPictureSizes();

        for (Size s : sizes) {
            float ratio = (float) s.width / (float) s.height;
            if (ratio == defaultCameraRatio && s.height <= PHOTO_HEIGHT_THRESHOLD) {
                res = s;
                break;
            }
        }
        return res;
    }

    public Size getPictureSize() {
        return pictureSize;
    }   
}

谢谢@Raghunandan。我知道安卓文档用于显示位图,但我想我的问题与相机有关;仍然无法理解为什么产生的字节数组大小变化如此之大。@ssantos有什么解决方案吗?@Shawnreck,我已经有一段时间没有解决这个问题了,但是关于变化的图片大小问题,我记得我必须在每张图片之前设置相机参数。我正在发布我的CameraUtils课程,希望你会发现它很有用。