如何在飞行中切换后退/前置摄像头时结束预览并开始新的预览

时间:2015-05-06 13:01:38

标签: android camera android-camera

我已经实现了一个显示相机预览的活动,它工作正常。最初在活动开始时我用前置摄像头开始活动。该应用程序工作正常,但现在我正在尝试实现按钮切换相机的飞行。我的意思是它不应该重新启动整个活动,而是将摄像机从前向后切换,反之亦然。但是我遇到了以下问题:

我的问题是

  • 当我从前置摄像头切换到后置摄像头时,前置摄像头的预览会卡住,但摄像头后置摄像头会启动,预览永远不会出现 - 当我打开后置摄像头虽然它没有显示我预览时,当我点击拍照时,当我导航到画廊时,我看到了后置摄像头拍摄的照片。
  • 所以它向我保证相机正在切换,但唯一的问题是获得预览并结束最后一个预览。我该怎么办?

到目前为止我做了什么

这是我切换相机的方式:

public static Camera getCameraInstance2(Camera camera) {

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

    //swap the id of the camera to be used
    if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
        currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    } else  { 
        currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    }

    try {
        camera = Camera.open(currentCameraId);
        camera.startPreview();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return camera;
}

它正在打开相机,但没有显示其预览。

这是我的Surfaceview类

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

private Camera camera;
public static  SurfaceHolder holder;
private Activity activity;


public CameraPreview(Context context, AttributeSet attrs, Activity activity) {
    super(context, attrs);

}

public CameraPreview(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CameraPreview(Context context) {
    super(context);
}

public void init(Camera camera,Activity activity) {
    this.camera = camera;
    this.activity = activity;
    initSurfaceHolder();
}

@SuppressWarnings("deprecation") // needed for < 3.0
private void initSurfaceHolder() {
    holder = getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    initCamera(holder);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);



}

private void initCamera(SurfaceHolder holder) {
    try {

        Camera.Parameters param;
        param = camera.getParameters();

        Camera.Size bestSize = null;
        List<Camera.Size> sizeList = camera.getParameters().getSupportedPreviewSizes();
        bestSize = sizeList.get(0);
        for(int i = 1; i < sizeList.size(); i++){
            if((sizeList.get(i).width * sizeList.get(i).height) > (bestSize.width * bestSize.height)){
                bestSize = sizeList.get(i);
            }
        }

        List<Integer> supportedPreviewFormats = param.getSupportedPreviewFormats();
        Iterator<Integer> supportedPreviewFormatsIterator = supportedPreviewFormats.iterator();
        while(supportedPreviewFormatsIterator.hasNext()){
            Integer previewFormat =supportedPreviewFormatsIterator.next();
            if (previewFormat == ImageFormat.YV12) {
                param.setPreviewFormat(previewFormat);
            }
        }

        param.setPreviewSize(bestSize.width, bestSize.height);
        Log.v("Best Preview Size"+bestSize.width+":/::/:"+bestSize.height);
        param.setPictureSize(bestSize.width, bestSize.height);

        camera.setParameters(param);

        requestLayout();
        camera.setPreviewDisplay(holder);
        camera.startPreview();



    } catch (Exception e) {
        Log.d("Error setting camera preview", e);
    }
}

@Override
public void surfaceChanged(SurfaceHolder mHolder, int format, int width, int height) {


    //new work around

    Camera.Parameters param;
    param = camera.getParameters();

    Camera.Size bestSize = null;
    List<Camera.Size> sizeList = camera.getParameters().getSupportedPreviewSizes();
    bestSize = sizeList.get(0);
    for(int i = 1; i < sizeList.size(); i++){
        if((sizeList.get(i).width * sizeList.get(i).height) > (bestSize.width * bestSize.height)){
            bestSize = sizeList.get(i);
        }
    }

    List<Integer> supportedPreviewFormats = param.getSupportedPreviewFormats();
    Iterator<Integer> supportedPreviewFormatsIterator = supportedPreviewFormats.iterator();
    while(supportedPreviewFormatsIterator.hasNext()){
        Integer previewFormat =supportedPreviewFormatsIterator.next();
        if (previewFormat == ImageFormat.YV12) {
            param.setPreviewFormat(previewFormat);
        }
    }

    param.setPreviewSize(bestSize.width, bestSize.height);

    param.setPictureSize(bestSize.width, bestSize.height);

    camera.setParameters(param);

    Display display = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    if(display.getRotation() == Surface.ROTATION_0) {
        camera.setDisplayOrientation(90);
        param.setPreviewSize(bestSize.width, bestSize.height);
    } else if(display.getRotation() == Surface.ROTATION_270) {
        camera.setDisplayOrientation(180);
        param.setPreviewSize(bestSize.width, bestSize.height);
    }

    requestLayout();
    try {
        camera.setPreviewDisplay(holder);
    } catch (IOException e) {
        e.printStackTrace();
    }
    camera.startPreview();







}// end surfaceChanged





@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    Log.e("TABACT"+"surfaceDestroyed()");
    camera.stopPreview();
    camera.setPreviewCallback(null);
    camera.release();
    camera = null;

    this.getHolder().removeCallback(this);
  //  camera.release();
  //  camera.stopPreview();

}

public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio=(double)h / w;

    if (sizes == null) return null;

    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;
}

我添加了名为“CameraPreview”的表面预览类。

EDIT3

我已经检查了一件事,那就是当我写信获取相机实例并开始预览时,它的起始相机成功了。我的意思是第一次当Activity恢复它的启动前置摄像头,当它恢复第二次启动后置摄像头时,每一件事都很好。我正在使用上面分享的代码切换相机。 现在的问题是,当我从活动按钮尝试此代码时预览卡住了,而相机在最后一个相机预览的预览背景中切换。

因此,如何在切换后删除最后一个摄像头预览,并在活动中通过新打开的摄像头开始新预览。

**我在想什么**

当用户点击翻盖相机按钮时,我应该显示对话框,其中有一个按钮可以切换相机,这会将活动置于暂停状态,点击是按钮只需关闭将恢复活动的对话框,结果它将显示切换摄像头的预览。

上层方法可能有用,但这不是一个好方法。但可能是什么解决方案。请与我分享。

2 个答案:

答案 0 :(得分:0)

您需要从根布局中删除以前连接的CameraPreview,然后将此CameraPreview添加到已更改的摄像头。 举例来说,我使用FrameLayout来显示CameraPreview,然后如果我希望从前到后更改相机预览,反之亦然,我将删除附加到FrameLayout的视图(layout.removeAllViews()),然后添加CameraPreview改变了cameraId。

答案 1 :(得分:-1)

根据答案:Android: Switch camera when button clicked我让这段代码对我有用:

private void switchCamera() {
    if (mCamera != null) {
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
        try {
            if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
            }
            else {
                mCameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;
            }
            mCamera = Camera.open(mCameraFacing);
            mCamera.setPreviewDisplay(mPreview.getHolder());
            mCamera.startPreview();
        }
        catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

我这里的关键是stopPreview(),只需重置Camera并开始新的startPreview()