【问题标题】:How to end preview and start new preview when Switch Back/Front camera on fly动态切换后/前摄像头时如何结束预览并开始新预览
【发布时间】:2015-05-06 13:01:37
【问题描述】:

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

我的问题是

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

到目前为止我做了什么

这是我切换相机的方式:

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”的表面预览类。

编辑3

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

那么如何在切换后删除最后一个相机预览并通过新打开的相机在活动中开始新的预览。

**我在想什么**

当用户单击翻转相机按钮时,我应该显示带有按钮的对话框以切换相机,这将使活动处于暂停状态,单击“是”按钮只需关闭将恢复活动的对话框,结果它将显示切换相机的预览。

上面的方法可能会奏效,但这不是一个好的技术。但有什么解决办法。请与我分享。

【问题讨论】:

  • 这对我没有帮助
  • 你能不能告诉我如何才能杀死最后一个预览连同相机
  • 好吧,评论您的SurfaceView 代码(希望它可能会有所帮助):我onSurfaceChanged() 中设置相机参数,我在@ 中什么也不做987654326@。您的“新工作”不会被多次调用吗?

标签: android camera android-camera


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    基于该答案: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()

    【讨论】:

    • 我也在做同样的事情。停止预览,它确实停止了预览,但它在第一台相机的预览之后开始了预览。
    • 您的问题可能与您的SurfaceView 有关。请发布它的代码。
    猜你喜欢
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    相关资源
    最近更新 更多