2017-01-11 4 views
1

일반적으로 PreviewCallback이있는 Android 카메라 api는 사진 촬영 후 카메라를 정지시키고 촬영 한 이미지의 승인 화면으로 사용할 수 있습니다. 제 문제는 삼성 S6 및 S6 가장자리와 같은 휴대폰의 동작이 아니라는 것입니다. 이 두 전화기는 사진을 찍은 후 실시간 미리보기를 계속합니다.특정 기기에서 촬영 한 이미지의 Android 카메라 미리보기

촬영 한 사진이 여전히 좋으며 나중에 사용하기도하지만 미리보기가 표시되지 않으며 내 앱이 설정된 방식으로 사용자가 방금 찍은 사진을 승인 할 수있는 체크 표시와 x 표시가 있습니다. 사진. 대신 그들은이 체크를위한 오버레이와 "x"와 백그라운드에서의 라이브 미리보기를 가지고 있습니다. 그리고 이것은 samsung s6/s6 가장자리에서만 발생합니다.

특정 기기에서 이와 같은 문제가 발생할 수있는 이유는 무엇입니까? 미리보기 및 사진 사방 일부 로깅을 복용에 사용

코드 :

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; 
    private List<Camera.Size> mSupportPictureSizes; 

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

     Log.d(TAG, "CameraPreview: "); 

     // 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() 
    { 
     Log.d(TAG, "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: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails 
     mCamera = camera; 
     mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
     mSupportPictureSizes = mCamera.getParameters().getSupportedPictureSizes(); 

     for(Camera.Size size : mSupportedPreviewSizes){ 
      Log.d(TAG, "supportedPreviewSizes width: " + size.width + " x " + size.height); 
     } 
     for(Camera.Size size : mSupportPictureSizes){ 
      Log.d(TAG, "mSupportPictureSizes width: " + size.width + " x " + size.height); 
     } 
     mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes(); 
     Camera.Parameters parameters = mCamera.getParameters(); 

     parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 

     // Set the camera to Auto Flash mode. 
     if (mSupportedFlashModes != null && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)){ 
      parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); 

     } 

     mCamera.setParameters(parameters); 
     requestLayout(); 
    } 

    /** 
    * The Surface has been created, now tell the camera where to draw the preview. 
    * @param holder 
    */ 
    public void surfaceCreated(SurfaceHolder holder) { 
     Log.d(TAG, "surfaceCreated: "); 
     try { 
      mCamera.setPreviewDisplay(holder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Dispose of the camera preview. 
    * @param holder 
    */ 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     Log.d(TAG, "surfaceDestroyed: "); 
     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) { 
     // 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 
      Log.d(TAG, "surfaceChanged: preview surface does not exist"); 
      return; 
     } 
     Log.d(TAG, "surfaceChanged: start & stop preview"); 
     // 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 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

     } catch (Exception e){ 
      Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
     } 

    } 

    @Override 
    public SurfaceHolder getHolder() { 
     return super.getHolder(); 
    } 

    /** 
    * Calculate the measurements of the layout 
    * @param widthMeasureSpec 
    * @param heightMeasureSpec 
    */ 
    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 

     // Source: http://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){ 
      Log.d(TAG, "onMeasure: w x h: " + width + " x " + height); 
      mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, 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) 
    { 
     Log.d(TAG, "onLayout: "); 
     // Source: http://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); 
         Log.d(TAG, "onLayout: rotation0"); 
         break; 
        case Surface.ROTATION_90: 
         previewWidth = mPreviewSize.width; 
         previewHeight = mPreviewSize.height; 
         Log.d(TAG, "onLayout: rotation90"); 
         break; 
        case Surface.ROTATION_180: 
         previewWidth = mPreviewSize.height; 
         previewHeight = mPreviewSize.width; 
         Log.d(TAG, "onLayout: rotation180"); 
         break; 
        case Surface.ROTATION_270: 
         previewWidth = mPreviewSize.width; 
         previewHeight = mPreviewSize.height; 
         mCamera.setDisplayOrientation(180); 
         Log.d(TAG, "onLayout: rotation270"); 
         break; 
       } 
      } 

      final int scaledChildHeight = previewHeight * width/previewWidth; 
      mCameraView.layout(0, height - scaledChildHeight, width, height); 
     } 
    } 

    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { 
     Log.d(TAG, "getOptimalPreviewSize: "); 
     final double ASPECT_TOLERANCE = 0.05; 
     double targetRatio = (double) w/h; 
     if (sizes == null) return null; 

     Camera.Size optimalSize = null; 
     double minDiff = Double.MAX_VALUE; 

     int targetHeight = h; 

     // Try to find an size match aspect ratio and size 
     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) { 
       Log.d(TAG, "getOptimalPreviewSize: found a match"); 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 

     // Cannot find the one match the aspect ratio, ignore the requirement 
     if (optimalSize == null) { 
      Log.d(TAG, "getOptimalPreviewSize: couldn't find match"); 
      minDiff = Double.MAX_VALUE; 
      for (Camera.Size size : sizes) { 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 
     } 
     Log.d(TAG, "getOptimalPreviewSize: " + optimalSize.width + " x HEIGHT: " + optimalSize.height); 
     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) { 
     Camera.Parameters parameters = camera.getParameters(); 
     Camera.Size mPictureTakenSize = parameters.getPictureSize(); 
     System.out.println("picture taken size: " + mPictureTakenSize.width + " x " + mPictureTakenSize.height); 
     if(data!=null){ 
      Log.d(TAG, "onPictureTaken: data not null, setting data to currentData"); 
//    currentData = data; 
      setPictureTakenData(data); 
      cameraViewModel.setPreview(true); 
     } 
     else{ 
      onProgress = false; 
      Log.d(TAG, "onPictureTaken: data is null"); 
     } 

    } 
}; 

답변

0

난 그냥 같은 문제 다 퉜다. PictureCallback의 onPictureTaken 메서드에서 camera.stopPreview()를 수동으로 호출하여 문제를 해결할 수있는 것 같습니다.

0
카메라는 사진 촬영 후 자동으로 미리보기를 멈추지 않을 것입니다, 그래서 당신은 수동으로) mCamera.stopPreview를 (호출 할 필요

: 후 뭔가를, 다음

if (mCamera != null) { 
    try { 
     mCamera.stopPreview(); 
     pauseFlash(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

// if current camera flash mode is TORCH, you need pause it. 
private void pauseFlash() { 
    if (currentFlashMode.equals(Camera.Parameters.FLASH_MODE_TORCH)) { 
     params = mCamera.getParameters(); 
     params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); 
     mCamera.setParameters(params); 
    } 
} 

그리고 및 카메라 미리보기로 다시 이동합니다

@Override 
public void startCameraPreview() { 
    if (mCamera != null) { 
     try { 
      mCamera.startPreview(); 
      resumeFlash(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      // TAKE CARE IF YOUR CAMERA HAS BEEN RELEASED 
     } 
    } 
} 

void resumeFlash() { 
    flashChange(currentFlashMode); 
} 

그리고 성능 팁이 있습니다. 사용자가 앱을 처음 사용할 때 가장 좋은 사진 크기와 미리보기 크기를 찾고 SharedPreferences에 저장하고 다시 caculate하지 않고 사용할 수 있습니다.

희망 도움말.