La previsualización en vivo de la cámara se congela en el interruptor de la cámara

Estoy creando una aplicación de cámara personalizada. El problema al que me enfrento es que la vista previa de la cámara se congela cuando cambia entre la cámara frontal y la trasera. Al iniciar la actividad con la cámara delantera o trasera llamando al

boolean opened = safeCameraOpenInView(view, Camera.CameraInfo.CAMERA_FACING_BACK) 

en el método OnCreateView del fragmento, ambas cámaras se mostrarán en el inicio como se esperaba. Tan pronto como llame al mismo método en el oyente de clic de mi botón de conmutación, la cámara se congela inmediatamente.

Esta es una nueva implementación que he intentado donde todo el código está dentro del mismo fragmento en lugar de una clase personalizada basada en la pregunta aquí: La cámara de clase personalizada de la previsualización en vivo se congela en el interruptor de la cámara pero el resultado es exactamente el mismo. Estoy bastante seguro de que tengo que hacer algo con la vista de la superficie para vincularlo a la nueva cámara, pero estoy en una pérdida de cómo hacer esto. ¿Alguien tiene algunos indicadores?

Mi actividad:

 public class Camera2ActivityFragment extends Fragment { // Native camera. private Camera mCamera; // View to display the camera output. private CameraPreview mPreview; // Reference to the containing view. private View mCameraView; /** * Default empty constructor. */ public Camera2ActivityFragment(){ super(); } /** * Static factory method * @param sectionNumber * @return */ public static Camera2ActivityFragment newInstance(int sectionNumber) { Camera2ActivityFragment fragment = new Camera2ActivityFragment(); //Bundle args = new Bundle(); //args.putInt(ARG_SECTION_NUMBER, sectionNumber); //fragment.setArguments(args); return fragment; } /** * OnCreateView fragment override * @param inflater * @param container * @param savedInstanceState * @return */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_camera2, container, false); boolean opened = safeCameraOpenInView(view, Camera.CameraInfo.CAMERA_FACING_BACK); if(opened == false){ Log.d("CameraGuide","Error, Camera failed to open"); return view; } // Trap the capture button. Button captureButton = (Button) view.findViewById(R.id.btnCameraStart); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // get an image from the camera mCamera.takePicture(null, null, mPicture); } } ); Button switchCameraButton = (Button) view.findViewById(R.id.btnSwitchCamera); switchCameraButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { safeCameraOpenInView(getView(), Camera.CameraInfo.CAMERA_FACING_FRONT); //ISSUE OCCURS HERE! } } ); return view; } /** * Recommended "safe" way to open the camera. * @param view * @return */ private boolean safeCameraOpenInView(View view, int camID) { boolean qOpened = false; releaseCameraAndPreview(); //mCamera = getCameraInstance(Camera.CameraInfo.CAMERA_FACING_BACK); mCamera = getCameraInstance(camID); mCameraView = view; qOpened = (mCamera != null); if(qOpened == true){ mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera,view); FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_view); preview.addView(mPreview); mPreview.startCameraPreview(); } return qOpened; } /** * Safe method for getting a camera instance. * @return */ public static Camera getCameraInstance(int camID){ Camera c = null; try { c = Camera.open(camID); // attempt to get a Camera instance } catch (Exception e){ e.printStackTrace(); } return c; // returns null if camera is unavailable } @Override public void onPause() { super.onPause(); } @Override public void onDestroy() { super.onDestroy(); releaseCameraAndPreview(); } /** * Clear any existing preview / camera. */ private void releaseCameraAndPreview() { if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } if(mPreview != null){ mPreview.destroyDrawingCache(); mPreview.mCamera = null; } } /** * Surface on which the camera projects it's capture results. This is derived both from Google's docs and the * excellent StackOverflow answer provided below. * * Reference / Credit: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails */ class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { // SurfaceHolder private SurfaceHolder mHolder; // Our Camera. private Camera mCamera; // Parent Context. private Context mContext; // Camera Sizing (For rotation, orientation changes) private Camera.Size mPreviewSize; // List of supported preview sizes private List<Camera.Size> mSupportedPreviewSizes; // Flash modes supported by this camera private List<String> mSupportedFlashModes; // View holding this camera. private View mCameraView; public CameraPreview(Context context, Camera camera, View cameraView) { super(context); // Capture the context mCameraView = cameraView; mContext = context; setCamera(camera); // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); mHolder.setKeepScreenOn(true); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } /** * Begin the preview of the camera input. */ public void startCameraPreview() { try{ mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch(Exception e){ e.printStackTrace(); } } /** * Extract supported preview and flash modes from the camera. * @param camera */ private void setCamera(Camera camera) { // Source: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails mCamera = camera; mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes(); // Set the camera to Auto Flash mode. if (mSupportedFlashModes != null && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)){ Camera.Parameters parameters = mCamera.getParameters(); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); parameters.setRotation(90); //parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); mCamera.setParameters(parameters); mCamera.setDisplayOrientation(90); } requestLayout(); } /** * The Surface has been created, now tell the camera where to draw the preview. * @param holder */ public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); //mCam = Camera.open(); //mCam.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } } /** * Dispose of the camera preview. * @param holder */ public void surfaceDestroyed(SurfaceHolder holder) { if (mCamera != null){ mCamera.stopPreview(); } } /** * React to surface changed events * @param holder * @param format * @param w * @param h */ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { //Log.e(TAG, "surfaceChanged => w=" + w + ", h=" + 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(); //mCamera.release(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or reformatting changes here // start preview with new settings try { Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); parameters.setRotation(90); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); mCamera.setParameters(parameters); mCamera.setDisplayOrientation(90); mCamera.setPreviewDisplay(mHolder); mCamera.enableShutterSound(true); mCamera.startPreview(); } catch (Exception e){ //Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } /** * Calculate the measurements of the layout * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /* // Source: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width, height); if (mSupportedPreviewSizes != null){ mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); } */ final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); if (mSupportedPreviewSizes != null) { mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); } float ratio; if(mPreviewSize.height >= mPreviewSize.width) ratio = (float) mPreviewSize.height / (float) mPreviewSize.width; else ratio = (float) mPreviewSize.width / (float) mPreviewSize.height; // One of these methods should be used, second method squishes preview slightly setMeasuredDimension(width, (int) (width * ratio)); // setMeasuredDimension((int) (width * ratio), height); } /** * Update the layout based on rotation and orientation changes. * @param changed * @param left * @param top * @param right * @param bottom */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // Source: https://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails if (changed) { final int width = right - left; final int height = bottom - top; int previewWidth = width; int previewHeight = height; if (mPreviewSize != null){ Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); switch (display.getRotation()) { case Surface.ROTATION_0: previewWidth = mPreviewSize.height; previewHeight = mPreviewSize.width; mCamera.setDisplayOrientation(90); break; case Surface.ROTATION_90: previewWidth = mPreviewSize.width; previewHeight = mPreviewSize.height; break; case Surface.ROTATION_180: previewWidth = mPreviewSize.height; previewHeight = mPreviewSize.width; break; case Surface.ROTATION_270: previewWidth = mPreviewSize.width; previewHeight = mPreviewSize.height; mCamera.setDisplayOrientation(180); break; } } final int scaledChildHeight = previewHeight * width / previewWidth; mCameraView.layout(0, height - scaledChildHeight, width, height); } } /** * * @param sizes * @param width * @param height * @return */ private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) height / width; if (sizes == null) return null; Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = height; for (Camera.Size size : sizes) { double ratio = (double) size.height / size.width; 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; } } /** * Picture Callback for handling a picture capture and saving it out to a file. */ private Camera.PictureCallback mPicture = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(); if (pictureFile == null){ Toast.makeText(getActivity(), "Image retrieval failed.", Toast.LENGTH_SHORT) .show(); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; /** * Used to return the camera File output. * @return */ private File getOutputMediaFile(){ File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "Pocket Booth"); if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ Log.d("Camera Guide", "Required media storage does not exist"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); //DialogHelper.showDialog( "Success!","Your picture has been saved!",getActivity()); return mediaFile; } } 

Bueno, aquí voy a escribir un tutorial para usted sobre cómo capturar una imagen usando Cámara habilitando algunas características comunes de la cámara.

Paso 1: Crear una clase de vista previa

 /** * A basic Camera preview class */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private static final String TAG = "CameraPreview"; private SurfaceHolder mHolder; private Camera mCamera; 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(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } 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. } 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 // start preview with new settings startPreview(); } public void resetCamera(Camera camera) { mCamera = camera; } public void startPreview() { try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e) { Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } } 

Paso 2: Utilice FrameLayout para mantener la vista previa.

  <FrameLayout android:id="@+id/cameraPreview" android:layout_width="match_parent" android:layout_height="match_parent"/> 

Paso 3: Obtener la camera y enviar a la clase de vista previa. puede que tenga que establecer los parámetros que necesita antes de pasar la cámara.

  /** * Create our Preview view and set it as the content of UI. */ private void initCameraPreview(final int cameraId, final boolean createPreview) { mCamera = getCameraInstance(cameraId); setupCameraParameters(cameraId); if (createPreview) { mPreview = new CameraPreview(this, mCamera); mPreviewHolder.addView(mPreview); } mReadyToCapture = true; } /** * A safe way to get an instance of the Camera object. */ private Camera getCameraInstance(int cameraId) { Camera c = null; try { c = Camera.open(cameraId); // attempt to get a Camera instance } catch (Exception e) { e.printStackTrace(); // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable } /** * Measure and Setup the camera parameters. */ private void setupCameraParameters(int cameraId) { boolean hasFlash; Camera.Parameters parameters = mCamera.getParameters(); mPreviewSize = determineBestPreviewSize(parameters); parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); Camera.Size bestPictureSize = determineBestPictureSize(parameters); parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height); hasFlash = Util.hasSystemFeature(this, PackageManager.FEATURE_CAMERA_FLASH); if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) { hasFlash = Util.hasFrontCameraFlash(parameters); } else { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } if (hasFlash) parameters.setFlashMode(mFlashMode); int[] orientations = Util.getCameraDisplayOrientation(this, cameraId); mDisplayOrientation = orientations[0]; mLayoutOrientation = orientations[1]; mCamera.setDisplayOrientation(mDisplayOrientation); mCamera.setParameters(parameters); } private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) { List<Camera.Size> sizes = parameters.getSupportedPreviewSizes(); return determineBestSize(sizes); } private Camera.Size determineBestPictureSize(Camera.Parameters parameters) { List<Camera.Size> sizes = parameters.getSupportedPictureSizes(); return determineBestSize(sizes); } private Camera.Size determineBestSize(List<Camera.Size> sizes) { Camera.Size bestSize = null; for (Camera.Size currentSize : sizes) { boolean isDesiredRatio = (currentSize.width / 4) == (currentSize.height / 3); boolean isBetterSize = (bestSize == null || currentSize.width > bestSize.width); boolean isInBounds = currentSize.width <= PICTURE_SIZE_MAX_WIDTH; if (isDesiredRatio && isInBounds && isBetterSize) { bestSize = currentSize; } } if (bestSize == null) { return sizes.get(0); } return bestSize; } 

Paso 4: Método de escritura para cambiar la cámara

  /** * Swapping between system cameras */ private void swapCamera() { if (!(Camera.getNumberOfCameras() > 1)) { /* No front facing camera to switch.*/ return; } mReadyToCapture = false; mCamera.stopPreview(); releaseCamera(false); if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT; else mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK; initCameraPreview(mCurrentCameraId, false); mPreview.resetCamera(mCamera); mPreview.startPreview(); } 

Paso 5: Método para alternar el flash

  /** * Toggling camera flash to ON/OFF */ private void toggleFlash() { if (Util.hasSystemFeature(this, PackageManager.FEATURE_CAMERA_FLASH)) { Camera.Parameters parameters = mCamera.getParameters(); if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) { if (!Util.hasFrontCameraFlash(parameters)) { /* Front facing camera doesn\'t supported flash. */ return; } } mReadyToCapture = false; if (Camera.Parameters.FLASH_MODE_ON.equals(parameters.getFlashMode())) { mFlashMode = Camera.Parameters.FLASH_MODE_OFF; } else { mFlashMode = Camera.Parameters.FLASH_MODE_ON; } mCameraHandler.post(new Runnable() { @Override public void run() { mCamera.stopPreview(); releaseCamera(false); initCameraPreview(mCurrentCameraId, false); mPreview.resetCamera(mCamera); mPreview.startPreview(); } }); } else { /* warning_no_flash */ } } 

Paso 6: Métodos para manejar la cámara durante los cambios de estado de una pantalla

  /** * Release the camera for other applications */ private void releaseCamera(boolean remove) { if (mCamera != null) { if (remove) mPreview.getHolder().removeCallback(mPreview); mCamera.release(); mCamera = null; } } 

Paso 7: Clases de utilidades.

  /** * Check whether the given feature available in s/m * * @return Returns true if the devices supports the feature, else * false. */ public static boolean hasSystemFeature(Context context, String feature) { return context.getPackageManager().hasSystemFeature(feature); } /** * Check whether front camera flash feature available in s/m */ public static boolean hasFrontCameraFlash(Camera.Parameters cameraParameters) { boolean result = true; if (cameraParameters.getFlashMode() == null) { result = false; } List<String> supportedFlashModes = cameraParameters.getSupportedFlashModes(); if (supportedFlashModes == null || supportedFlashModes.isEmpty() || supportedFlashModes.size() == 1 && supportedFlashModes.get(0).equals(Camera.Parameters.FLASH_MODE_OFF)) { result = false; } return result; } /** * Showing camera in the same orientation as the display */ public static int[] getCameraDisplayOrientation(Activity activity, int cameraId) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } return new int[]{result, degrees}; } 

Paso 8: Captura

  // Get an image from the camera if (null != mCamera && mReadyToCapture) { mCameraOrientationListener.rememberOrientation(); mCamera.takePicture(mShutter, null, mPicture) } /** * Camera shutter sound callback, * used to enable sound while capture */ private Camera.ShutterCallback mShutter = new Camera.ShutterCallback() { @Override public void onShutter() { } }; /** * Camera picture callback */ private Camera.PictureCallback mPicture = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { mReadyToCapture = false; Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); int rotation = ((mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK ? mDisplayOrientation : ((360 - mDisplayOrientation) % 360)) + mCameraOrientationListener.getRememberedOrientation() + mLayoutOrientation) % 360; if (rotation != 0) { Matrix matrix = new Matrix(); matrix.postRotate(rotation); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); } } }; 

Paso 9: Escucha de orientación de la cámara para manejar la rotación de la imagen

 /** * Orientation listener to remember the device's orientation when the user presses * the shutter button. * <p/> * The orientation will be normalized to return it in steps of 90 degrees * (0, 90, 180, 270). */ public class CameraOrientationListener extends OrientationEventListener { private int currentNormalizedOrientation; private int rememberedNormalizedOrientation; public CameraOrientationListener(Context context) { super(context, SensorManager.SENSOR_DELAY_NORMAL); } @Override public void onOrientationChanged(int orientation) { if (orientation != ORIENTATION_UNKNOWN) { currentNormalizedOrientation = normalize(orientation); } } private int normalize(int degrees) { if (degrees > 315 || degrees <= 45) { return 0; } if (degrees > 45 && degrees <= 135) { return 90; } if (degrees > 135 && degrees <= 225) { return 180; } if (degrees > 225 && degrees <= 315) { return 270; } throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies."); } public void rememberOrientation() { rememberedNormalizedOrientation = currentNormalizedOrientation; } public int getRememberedOrientation() { return rememberedNormalizedOrientation; } } 

Paso 10: Manejo de los estados

  @Override public void onPause() { super.onPause(); mReadyToCapture = false; releaseCamera(true); } @Override public void onResume() { super.onResume(); removePreview(); mReadyToCapture = false; smoothCameraLoading(); } private void removePreview() { mPreviewHolder.removeAllViews(); } private void smoothCameraLoading() { mCameraHandler.post(new Runnable() { @Override public void run() { initCameraPreview(mCurrentCameraId, true); } }); } 

Paso 11: Variable de instancia utilizada

  private String mFlashMode = Camera.Parameters.FLASH_MODE_OFF; private int mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK; private int mDisplayOrientation; private int mLayoutOrientation; private boolean mReadyToCapture = false; private Camera.Size mPreviewSize; private FrameLayout mPreviewHolder; private Camera mCamera; private CameraPreview mPreview; private Handler mCameraHandler; private CameraOrientationListener mCameraOrientationListener; private FrameLayout mRootView; 

En mi aplicación de cámara, funciona con algo diferente a la tuya: 1. Abra la cámara al crear una superficie. 2. StartPreview y no stopPreview en surfaceChanged. 3. Libere la cámara en superficieDestoryed.

Para cambiar la cámara, simplemente coloque el surfaceView en INVISIBLE, luego ajuste los parámetros de su cámara, luego vuelva a ajustar el surfaceView a VISIBLE. En mi aplicación, sólo lo hago así:

  mbtCamera.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub if(cameraMax > 1){ mSurfaceView.setVisibility(View.INVISIBLE); if(mCameraParam.isZoomSupported()) cameraZoomRatios.clear(); if(cameraUsing == 0) cameraUsing = 1; else cameraUsing = 0; mCameraOverlayView.setScaleFactor(1.0f); mSurfaceView.setVisibility(View.VISIBLE); } } }); 

Espero que esto ayude!

La devolución de llamada completa:

  class CameraSurfaceHolderCallback implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { mCamera = Camera.open(cameraUsing); mCameraParam = mCamera.getParameters(); supportFlashMode = mCameraParam.getSupportedFlashModes(); if(supportFlashMode == null) mbtFlash.setVisibility(View.INVISIBLE); android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraUsing, info); int rotation = 0; if (info.facing == CameraInfo.CAMERA_FACING_FRONT){ rotation = (info.orientation - rt + 360) % 360; if(mCameraParam.getSupportedFlashModes() == null) mbtFlash.setVisibility(View.INVISIBLE); } else{ // back-facing camera rotation = (info.orientation + rt) % 360; mbtFlash.setVisibility(View.VISIBLE); if(flashMode.equals(Camera.Parameters.FLASH_MODE_AUTO)) icons[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_flash_automatic); else if(flashMode.equals(Camera.Parameters.FLASH_MODE_OFF)) icons[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_flash_off); else if(flashMode.equals(Camera.Parameters.FLASH_MODE_ON)) icons[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_flash_on); Matrix rot = new Matrix(); rot.setRotate(360-rt, icons[0].getWidth()/2, icons[0].getHeight()/2); icons[0] = Bitmap.createBitmap(icons[0], 0, 0, icons[0].getWidth(), icons[0].getHeight(), rot, true); mbtFlash.setImageBitmap(icons[0]); mCameraParam.setFlashMode(flashMode); } if(mCameraParam.isZoomSupported()){ cameraZoomRatios = mCameraParam.getZoomRatios(); mCameraOverlayView.setMaxScaleFactor(cameraZoomRatios.get(mCameraParam.getMaxZoom())/100f); }else mCameraOverlayView.setMaxScaleFactor(1.0f); List<Size> ss = mCameraParam.getSupportedPictureSizes(); Size maxResolution = ss.get(0); long pixel1, pixel2; pixel1 = maxResolution.width * maxResolution.height; for(int i=0; i<ss.size(); i++){ pixel2 = ss.get(i).width * ss.get(i).height; if(pixel2 > pixel1){ maxResolution = ss.get(i); pixel1 = pixel2; } } mCameraParam.setPictureSize(maxResolution.width, maxResolution.height); mCameraParam.setJpegQuality(100); LayoutParams rlParams = (LayoutParams) mSurfaceView.getLayoutParams(); WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); Display dp = wm.getDefaultDisplay(); DisplayMetrics dm = new DisplayMetrics(); dp.getMetrics(dm); float dpiScale = dm.density; float wScaleFactor = (dm.widthPixels-10*dpiScale)/maxResolution.height; float hScaleFactor = (dm.heightPixels-mllTopButtons.getHeight()-mllBotButtons.getHeight()-10*dpiScale)/maxResolution.width; if(wScaleFactor < hScaleFactor){ rlParams.width = (int) (dm.widthPixels - 10*dpiScale); rlParams.height = (int) (maxResolution.width * wScaleFactor); }else{ rlParams.width = (int) (maxResolution.height * hScaleFactor); rlParams.height = (int) (dm.heightPixels-mllTopButtons.getHeight()-mllBotButtons.getHeight()-10*dpiScale); } mSurfaceView.setLayoutParams(rlParams); mCameraOverlayView.setLayoutParams(rlParams); ss = mCameraParam.getSupportedJpegThumbnailSizes(); float photoAspectRatio, thumbAspectRatio; photoAspectRatio = (float)maxResolution.width / maxResolution.height; thumbAspectRatio = 0; pixel1 = 0; for(int i=0; i<ss.size(); i++){ if(ss.get(i).height != 0) thumbAspectRatio = (float)ss.get(i).width / ss.get(i).height; if(thumbAspectRatio == photoAspectRatio){ if(pixel1 == 0) { maxResolution = ss.get(i); pixel1 = ss.get(i).width * ss.get(i).height; }else{ pixel2 = ss.get(i).width * ss.get(i).height; if((pixel2 < pixel1)&&(pixel2 != 0)){ maxResolution = ss.get(i); pixel1 = pixel2; } } } } if(pixel1 != 0){ mCameraParam.setJpegThumbnailSize(maxResolution.width, maxResolution.height); mCameraParam.setJpegThumbnailQuality(100); } List<String> focusModes = mCameraParam.getSupportedFocusModes(); if(focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)){ mCameraParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); focusingColor = Color.YELLOW; } int minEv = mCameraParam.getMinExposureCompensation(); int maxEv = mCameraParam.getMaxExposureCompensation(); if((minEv == 0)&&(maxEv == 0)) mCameraOverlayView.setEVCompensate(false); else mCameraOverlayView.setEVCompensate(minEv, maxEv); mCameraParam.setRotation(rotation); mCamera.setParameters(mCameraParam); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { try { mCamera.setDisplayOrientation(90); mCamera.setPreviewDisplay(mSurfaceView.getHolder()); List<Size> ss = mCameraParam.getSupportedPreviewSizes(); Size maxResolution = ss.get(0); long pixel1, pixel2; float photoAspectRatio, previewAspectRatio; photoAspectRatio = (float)mCameraParam.getPictureSize().width / mCameraParam.getPictureSize().height; previewAspectRatio = 0; pixel1 = 0; for(int i=0; i<ss.size(); i++){ if(ss.get(i).height != 0) previewAspectRatio = (float)ss.get(i).width / ss.get(i).height; if(previewAspectRatio == photoAspectRatio){ if(pixel1 == 0) { maxResolution = ss.get(i); pixel1 = ss.get(i).width * ss.get(i).height; }else{ pixel2 = ss.get(i).width * ss.get(i).height; if(pixel2 > pixel1){ maxResolution = ss.get(i); pixel1 = pixel2; } } } } if(pixel1 != 0) mCameraParam.setPreviewSize(maxResolution.width, maxResolution.height); mCamera.setParameters(mCameraParam); mCamera.startPreview(); } catch(Exception e){} } @Override public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview(); mCamera.release(); } } 

Lo usé en actividad y sin fragmentos. No estoy seguro de que esto haga algo diferente.

Creo que hay un pequeño problema en el método safeCameraOpenInView y que es:

Su nueva vista de cámara se hace bajo la imagen congelada.

Así que deberías editar esta línea: preview.addView(mPreview);

como esto: preview.addView(mPreview, preview.getChildCount());

O bien, puede borrar la vista anterior de la cámara y luego añadir una nueva:

 preview.removeAllViews(); preview.addView(mPreview); 

Espero que esto funcione.

  • Cámara: la función setDisplayOrientation no funciona para Samsung Galaxy ACE con Android 2.3.6
  • Procesamiento de imágenes con Android Camera
  • Phonegap / Cordova cámara plugin - cómo obtener la fecha de la foto / hora?
  • ¿Cómo puedo abrir la "cámara frontal" en la plataforma Android?
  • Error de la cámara 100 Detalle
  • Abra la cámara nativa de Android con OpenCV
  • Parte del objeto de cámara del tiempo es nulo durante la inicialización
  • Camera parameters.setFocusMode no funciona
  • Android - Cómo recortar la previsualización de la cámara con TextureView
  • Android hace que las aplicaciones de Cordova se reinicien cuando se usan los complementos de Cámara y Captura de Cordova
  • ¿Cómo funciona un obturador remoto para trabajar con la cámara en Android / iOS?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.