public static void setBestPreviewFPS(Camera.Parameters parameters, int minFPS, int maxFPS) {
   List<int[]> supportedPreviewFpsRanges = parameters.getSupportedPreviewFpsRange();
   Log.i(TAG, "Supported FPS ranges: " + toString(supportedPreviewFpsRanges));
   if (supportedPreviewFpsRanges != null && !supportedPreviewFpsRanges.isEmpty()) {
     int[] suitableFPSRange = null;
     for (int[] fpsRange : supportedPreviewFpsRanges) {
       int thisMin = fpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX];
       int thisMax = fpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
       if (thisMin >= minFPS * 1000 && thisMax <= maxFPS * 1000) {
         suitableFPSRange = fpsRange;
         break;
       }
     }
     if (suitableFPSRange == null) {
       Log.i(TAG, "No suitable FPS range?");
     } else {
       int[] currentFpsRange = new int[2];
       parameters.getPreviewFpsRange(currentFpsRange);
       if (Arrays.equals(currentFpsRange, suitableFPSRange)) {
         Log.i(TAG, "FPS range already set to " + Arrays.toString(suitableFPSRange));
       } else {
         Log.i(TAG, "Setting FPS range to " + Arrays.toString(suitableFPSRange));
         parameters.setPreviewFpsRange(
             suitableFPSRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
             suitableFPSRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
       }
     }
   }
 }
  /**
   * Opens a camera, and attempts to establish preview mode at the specified width and height.
   *
   * <p>Sets mCameraPreviewWidth and mCameraPreviewHeight to the actual width/height of the preview.
   */
  private void openCamera(int desiredWidth, int desiredHeight) {
    if (mCamera != null) {
      throw new RuntimeException("camera already initialized");
    }

    Camera.CameraInfo info = new Camera.CameraInfo();

    // Try to find a back-facing camera (e.g. for videoconferencing).
    int numCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numCameras; i++) {
      Camera.getCameraInfo(i, info);
      //            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {  //TODO: front
      // facing
      if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
        mCamera = Camera.open(i);
        break;
      }
    }
    if (mCamera == null) {
      Log.d(TAG, "No front-facing camera found; opening default");
      mCamera = Camera.open(); // opens first back-facing camera
    }
    if (mCamera == null) {
      throw new RuntimeException("Unable to open camera");
    }
    mCamera.setDisplayOrientation(90); // TODO: set according to front or back facing

    Camera.Parameters parms = mCamera.getParameters();
    //        parms.setRotation(180);

    CameraUtils.choosePreviewSize(parms, desiredWidth, desiredHeight);

    // Give the camera a hint that we're recording video.  This can have a big
    // impact on frame rate.
    parms.setRecordingHint(true);

    // leave the frame rate set to default
    mCamera.setParameters(parms);

    int[] fpsRange = new int[2];
    Camera.Size mCameraPreviewSize = parms.getPreviewSize();
    parms.getPreviewFpsRange(fpsRange);
    String previewFacts = mCameraPreviewSize.width + "x" + mCameraPreviewSize.height;
    if (fpsRange[0] == fpsRange[1]) {
      previewFacts += " @" + (fpsRange[0] / 1000.0) + "fps";
    } else {
      previewFacts += " @[" + (fpsRange[0] / 1000.0) + " - " + (fpsRange[1] / 1000.0) + "] fps";
    }
    TextView text = (TextView) findViewById(R.id.cameraParams_text);
    text.setText(previewFacts);

    mCameraPreviewWidth = mCameraPreviewSize.width;
    mCameraPreviewHeight = mCameraPreviewSize.height;
  }
  /**
   * Opens a camera, and attempts to establish preview mode at the specified width and height.
   *
   * <p>Sets mCameraPreviewWidth and mCameraPreviewHeight to the actual width/height of the preview.
   */
  private void openCamera(int desiredWidth, int desiredHeight) {
    if (mCamera != null) {
      throw new RuntimeException("camera already initialized");
    }

    Camera.CameraInfo info = new Camera.CameraInfo();

    // Try to find a front-facing camera (e.g. for videoconferencing).
    int numCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numCameras; i++) {
      Camera.getCameraInfo(i, info);
      if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        mCamera = Camera.open(i);
        break;
      }
    }
    if (mCamera == null) {
      Log.d(TAG, "No front-facing camera found; opening default");
      mCamera = Camera.open(); // opens first back-facing camera
    }
    if (mCamera == null) {
      throw new RuntimeException("Unable to open camera");
    }

    Camera.Parameters parms = mCamera.getParameters();

    choosePreviewSize(parms, desiredWidth, desiredHeight);
    // leave the frame rate set to default
    mCamera.setParameters(parms);

    int[] fpsRange = new int[2];
    Camera.Size mCameraPreviewSize = parms.getPreviewSize();
    parms.getPreviewFpsRange(fpsRange);
    String previewFacts = mCameraPreviewSize.width + "x" + mCameraPreviewSize.height;
    if (fpsRange[0] == fpsRange[1]) {
      previewFacts += " @" + (fpsRange[0] / 1000.0) + "fps";
    } else {
      previewFacts += " @[" + (fpsRange[0] / 1000.0) + " - " + (fpsRange[1] / 1000.0) + "] fps";
    }
    TextView text = (TextView) findViewById(R.id.cameraParams_text);
    text.setText(previewFacts);

    mCameraPreviewWidth = mCameraPreviewSize.width;
    mCameraPreviewHeight = mCameraPreviewSize.height;
  }