我在我的应用中实现了自定义相机活动。相机在我的nexus 5上工作得很好。但是在阿尔卡特One Touch Star上,当我停止预览以显示快照时,我得到了这个预览
此外,PictureCallback
的字节数组是正确的。事实上,如果我将数组解码为Bitmap
,我可以正确看到它。
以下是SurfaceView
作为相机预览的实现。
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private int mPhotoRotation;
public CameraPreview(Context context) {
super(context);
}
@SuppressLint("InlinedApi")
@SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
Camera.Parameters parameters = camera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes != null && focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
else if (focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
if (parameters.getSupportedFlashModes() != null && parameters.getSupportedFlashModes().contains(Parameters.FLASH_MODE_AUTO))
parameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
camera.setParameters(parameters);
mHolder = getHolder();
mHolder.addCallback(this);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mCamera != null) {
mCamera.stopPreview();
Parameters parameters = mCamera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
Camera.Size size = getOptimalPreviewSize(previewSizes, width, height);
parameters.setPreviewSize(size.width, size.height);
mCamera.setParameters(parameters);
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mPhotoRotation = 0;
if (display.getRotation() == Surface.ROTATION_0) {
mPhotoRotation = 90;
} else if (display.getRotation() == Surface.ROTATION_270) {
mPhotoRotation = 180;
}
mCamera.setDisplayOrientation(mPhotoRotation);
mCamera.startPreview();
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public int getPhotoRotation() {
return mPhotoRotation;
}
}
当用户拍摄照片时,执行此代码
mCamera.takePicture(null, null, mPictureCallback);
并且回调只是保留字节数组的备份并停止预览。
mPictureCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
mPhotoJpeg = data;
mCamera.stopPreview();
}
};
那么这种行为的原因是什么?为什么只在阿尔卡特而不是在nexus 5上?