2016-06-15 4 views
4

Я создаю пользовательское приложение для камеры. Проблема, с которой я сталкиваюсь, заключается в том, что предварительный просмотр камеры зависает, когда я переключаюсь между передней и задней камерами. При запуске деятельность с передней или задней камеры, вызвавПредварительный просмотр камеры в реальном времени зависает на переключателе камеры

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

в методе OnCreateView фрагмента, обе камеры будут отображаться при запуске, как ожидалось. Как только я вызываю тот же самый метод в нажатом клике на кнопке переключателя, камера мгновенно замораживается.

Это новая реализация, которую я пробовал, где весь код находится внутри одного и того же фрагмента вместо пользовательского класса, основанного на вопросе здесь: Custom class camera live preview freezes on camera switch, но результат точно такой же. Я почти уверен, что мне нужно что-то сделать с видом поверхности, чтобы привязать его к новой камере, но я не понимаю, как это сделать. У кого-нибудь есть указатели?

Моя активность:

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

Путь к переключению должен заключаться в том, чтобы сделать это в потоке, то есть выполняемом ... отставание, которое вы видите, связано с тем, что вы переключаете камеры. Я вижу, могу ли я выкопать какой-то код. – yUdoDis

+0

Отлично. Я попробую добавить его в асинтезу. Я предполагаю, что это должно работать (нормальное внедрение async-задачи и вызов этого метода?). Любой образец кода будет высоко оценен. –

+0

Такая же проблема при запуске safeCameraOpenInView (view, Camera.CameraInfo.CAMERA_FACING_BACK); из AsyncTask –

ответ

5

Ну, вот я собираюсь написать учебник для вас о захвате изображения с помощью Camera, позволяя некоторые общие черты камеры.

Шаг 1: Создайте предварительный класс

/** 
* 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()); 
     } 
    } 
} 

Шаг 2: Используйте FrameLayout провести предварительный просмотр.

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

Шаг 3: Получить camera и отправить в класс просмотра. вам может потребоваться установить необходимые параметры перед передачей камеры.

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

Шаг 4: Способ записи для замены камеры

/** 
    * 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(); 
    } 

Шаг 5: Метод для переключения вспышки

/** 
    * 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 */ 
     } 

    } 

Шаг 6: Методы обработки камеры во время состояний изменения экрана

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

Шаг 7: Классы полезности.

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

Шаг 8: Захват

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


     } 
    }; 

Шаг 9: Камера ориентации слушателя для обработки поворот изображения

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

Шаг 10: States обработки

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

Шаг 11: Используемая переменная экземпляра

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; 
+0

Ты СПАСИБО ЖИЗНЬ! Только одна путаница; что такое PICTURE_SIZE_MAX_WIDTH на шаге 3? –

+0

Поскольку подразумевается имя переменной. Это максимальный размер изображения, используйте разрешение HD 'private static final int PICTURE_SIZE_MAX_WIDTH = 1280;'. –

+0

Спасибо, человек! @Anoop –

2

В моем приложении камеры, она работает с нечто отличается от вашей: 1. Откройте камеру, когда surfaceCreated. 2. StartPreview и no stopPreview в surfaceChanged. 3. Отпустите камеру на поверхности.

Чтобы изменить камеру, просто установите для параметра surfaceView значение INVISIBLE, затем установите параметры вашей камеры, а затем снова установите на поверхностьView VISIBLE. В моем приложении я делаю это только так:

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

Надеюсь, это поможет!

Полные обратный вызов:

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

Я использовал его в деятельности и без фрагмента. Я не уверен, что это сделает что-то другое.

+0

попытался установить видимость обзора поверхности, но безрезультатно. не могли бы вы поделиться общим классом камеры/деятельностью, чтобы я мог сравнить порядок, в котором все происходит? –

1

Я думаю, что есть небольшая проблема в методе safeCameraOpenInView и что:

Ваш новый вид камеры выполнен под СТОПКАДР.

Таким образом, вы должны изменить эту строку: preview.addView(mPreview);

как это: preview.addView(mPreview, preview.getChildCount());

Или вы можете сначала удалить предыдущий вид камеры, а затем добавить новый:

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

надеюсь, что это Работа.

Смежные вопросы