将android摄像头切换回前端:app传递了NULL表面

时间:2016-05-03 09:35:22

标签: android null camera switch-statement surface

使用Android Camera框架我发现了一个问题:如果我尝试使用以下代码从后向前切换相机

                releaseMediaRecorder();
                releaseCamera();
                if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
                    currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
                }
                else {
                    currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
                }
                mCamera = Camera.open(currentCameraId);
                mCamera.setPreviewCallback(null);
                try {
                    mCamera.setPreviewDisplay(mPreview.getHolder());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mCamera.startPreview();

除预览尺寸外,一切正常。事实上,我已经在我的Preview类中实现了一个获得最佳预览大小的函数,但是在这段代码中没有调用,因为我应该像在onResume方法中那样得到一个新的Preview实例:

@Override
protected void onResume() {
    super.onResume();
    try {
        mCamera = Camera.open(currentCameraId);
        mCamera.setPreviewCallback(null);
        mPreview = new CameraPreview(this, mCamera);
        preview.addView(mPreview);
        mCamera.startPreview();
    } catch (Exception e) {
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }      
}

如果我执行onResume方法,一切正常,但如果我在切换摄像头代码中复制mPreview = new CameraPreview(this, mCamera);preview.addView(mPreview);,Log会告诉我“D / Camera:app传递NULL表面”。 为什么呢?

- 编辑 -

我在CameraPreview类中实现了SurfaceHolder.Callback

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private static final String TAG = CameraPreview.class.getName();
Camera.Parameters params;
private float mDist;

public CameraPreview(Context context, Camera camera) {
    super(context);
    mCamera = camera;

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = getHolder();
    // deprecated setting, but required on Android versions prior to 3.0
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    mHolder.addCallback(this);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // If your preview can change or rotate, take care of those events here.
    // Make sure to stop the preview before resizing or reformatting it.

    if (mHolder.getSurface() == null){
        // preview surface does not exist
        return;
    }

    // stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
    }

    // set preview size and make any resize, rotate or
    // reformatting changes here
    params = mCamera.getParameters();

    params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
    params.setExposureCompensation(0);

    mCamera.setParameters(params);

    // start preview with new settings
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

    } catch (Exception e){
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}

// When the surface is ready then we can build the camera and attach
// the camera preview output to the UI holder
public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, now tell the camera where to draw the preview.
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // empty. Take care of releasing the Camera preview in your activity.
    if (mCamera != null) {
        this.getHolder().removeCallback(this);
        mCamera.stopPreview();
        mCamera.setPreviewCallback(null);
        mCamera.release();
        mCamera = null;
    }
}

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null)
        return null;

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    // Try to find an size match aspect ratio and size
    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);
        }
    }
    // Cannot find the one match the aspect ratio, ignore the requirement
    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;
}

1 个答案:

答案 0 :(得分:0)

我添加了这行代码解决了这个问题

mPreview = new CameraPreview(context, mCamera);
preview.addView(mPreview);

之前

try {
         mCamera.setPreviewDisplay(mPreview.getHolder());
    } catch (IOException e) {
        e.printStackTrace();
     }

并将preview.removeView(mPreview);添加到releaseCamera()方法