在飞行中切换后/前摄像头

如果我只使用CAMERA_FACING_BACKCAMERA_FACING_FRONT一切正常。

CAMERA_FACING_BACK切换到CAMERA_FACING_BACKCAMERA_FACING_FRONT

我的代码片段:

 public class PhotoCameraActivity extends Activity implements OnClickListener { private SurfaceView cameraView; private Button turnButton; private Camera camera = null; private Callback listener; private static int camId = Camera.CameraInfo.CAMERA_FACING_BACK; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.photo_camera_main); prepareActivity(); } private void prepareActivity() { cameraView = (SurfaceView) findViewById(R.id.photo_camera_surface_view); turnButton = (ImageButton) findViewById(R.id.turn_button); turnButton.setOnClickListener(this); } @Override public void onClick(View v) { if (v.equals(turnButton)) { if (Camera.getNumberOfCameras() > 1 && camId < Camera.getNumberOfCameras() - 1) { startCamera(camId + 1); } else { startCamera(Camera.CameraInfo.CAMERA_FACING_BACK); } } } @Override protected void onResume() { startCamera(camId); super.onResume(); } @Override protected void onPause() { stopCamera(); super.onPause(); } private void startCamera(int cameraId) { if (camera != null) { stopCamera(); } holder = cameraView.getHolder(); listener = new Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} }; holder.addCallback(listener); camId = cameraId; camera = Camera.open(cameraId); Camera.Parameters params = camera.getParameters(); if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) { params.setPreviewSize(1280, 800); } else { params.setPreviewSize(640, 480); } camera.setParameters(params); } private void stopCamera(){ System.out.println("stopCamera method"); if (camera != null){ camera.stopPreview(); camera.setPreviewCallback(null); camera.release(); camera = null; holder.removeCallback(listener); holder = null; } } } 

在我的活动的onCreate()中,我将以下onClick监听器添加到覆盖在我的预览SurfaceView上的按钮(Web上有许多用于预览的示例):

 ImageButton useOtherCamera = (ImageButton) findViewById(R.id.useOtherCamera); //if phone has only one camera, hide "switch camera" button if(Camera.getNumberOfCameras() == 1){ useOtherCamera.setVisibility(View.INVISIBLE); } else { useOtherCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (inPreview) { camera.stopPreview(); } //NB: if you don't release the current camera before switching, you app will crash camera.release(); //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; } camera = Camera.open(currentCameraId); //Code snippet for this method from somewhere on android developers, i forget where setCameraDisplayOrientation(CameraActivity.this, currentCameraId, camera); try { //this step is critical or preview on new camera will no know where to render to camera.setPreviewDisplay(previewHolder); } catch (IOException e) { e.printStackTrace(); } camera.startPreview(); } 

在我的测试设备上,后置摄像头的ID为0,前置的ID为1.我建议使用Camera.CameraInfo静态variables作为摄像机ID,而不是硬编码值。 我相信这只会导致其他设备出现问题。

我用cameraId = 2重新启动Activity,这是有效的。

我在我的布局中删除并重新添加了SurfaceView,因此它有效。

 public void switchCamera(int cameraType) { if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) { if(Camera.getNumberOfCameras() > cameraType) { // Set selected camera this.cameraType = cameraType; } else { // Set default camera (Rear) this.cameraType = Camera.CameraInfo.CAMERA_FACING_BACK; } if(mCamera != null) { // Destroy previuos Holder surfaceDestroyed(holder); holder.removeCallback(this); // Remove and re-Add SurfaceView ViewGroup rootLayout = (ViewGroup) surface.getParent(); rootLayout.removeView(surface); surface = new SurfaceView(context); holder = surface.getHolder(); holder.addCallback(this); rootLayout.addView(surface, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } } } 

我必须在添加新表面之前删除表面预览:

 if (mPreview != null) { mPreview.surfaceDestroyed(mPreview.getHolder()); mPreview.getHolder().removeCallback(mPreview); mPreview.destroyDrawingCache(); FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_frame); preview.removeView(mPreview); mPreview.mCamera = null; mPreview = null; } //then add your preview 

使用此代码:

 if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = 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 { mCamera = Camera.open(currentCameraId); mCamera.setDisplayOrientation(90); mCamera.setPreviewDisplay(surfaceHolder); mCamera.startPreview(); } catch (Exception e) { e.printStackTrace(); }