1

我正在OutOfMemoryErrorBitmapCamera. 我的代码运行良好几次,直到我得到异常,所以我花了几个小时寻找内存泄漏。

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

我正在使用自定义CameraActivity. 初始化代码Camera如下所示

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();

当我暂停时,我像这样CameraActivity释放 deCamera

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

为什么在相同的初始化条件下返回的图片可以有如此不同的大小?我可以错过一些完全释放这些Camera东西的方法吗?任何线索表示赞赏:)

4

1 回答 1

0

我实际上在这里发现了几个问题,但我设法通过每次拍照时重置相机参数来停止接收不同大小的数组。这是我的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;
    }   
}
于 2014-02-06T09:10:00.413 回答