Android 使用三星Galaxy SII拍摄的BitmapFactory.decodeByteArray期间发生OutOfMemory错误
从相机拍摄的图片创建位图时,我遇到OutOfMemory错误。在得到异常之前,我的代码可以正常工作几次,所以我花了几个小时寻找内存泄漏 奇怪的是,我将代码追溯到PictureCallback只是为了检查字节数组的大小:当没有引发异常时,它大约是280k,但最终,我收到了一个超过1.2M的字节数组,这时decodeByteArray崩溃 我正在使用自定义的CameraActivity。初始化相机的代码如下所示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
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课程,希望你会发现它很有用。