Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/224.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Camera2 Api仅在android 28 pie设备中显示摄像头上的白色屏幕_Java_Android_Android Camera2_Android 9.0 Pie - Fatal编程技术网

Java Camera2 Api仅在android 28 pie设备中显示摄像头上的白色屏幕

Java Camera2 Api仅在android 28 pie设备中显示摄像头上的白色屏幕,java,android,android-camera2,android-9.0-pie,Java,Android,Android Camera2,Android 9.0 Pie,我使用的是camera2 api,它在Pie之前的android版本上运行良好,但在android Pie设备上打开摄像头时,它会显示白色屏幕。我已经检查了模拟器,10台设备。 请帮帮我 应用程序build.gradle compileSdkVersion 29 defaultConfig { applicationId "xxx.xxx.xxx.xxx" minSdkVersion 23 targetSdkVersion 29 } 我还

我使用的是camera2 api,它在Pie之前的android版本上运行良好,但在android Pie设备上打开摄像头时,它会显示白色屏幕。我已经检查了模拟器,10台设备。 请帮帮我

应用程序build.gradle

compileSdkVersion 29
    defaultConfig {
        applicationId "xxx.xxx.xxx.xxx"
        minSdkVersion 23
        targetSdkVersion 29
}
我还声明了权限

   <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera2.full" /> 
    <uses-feature android:name="android.hardware.camera.autofocus" />
我也注意到有时它只在第一次工作,然后第二次显示白色屏幕。 下面是捕获活动代码


public class CCaptureActivity extends AppCompatActivity
{
  /**
   * Activity creation handler.
   * @param argSavedInstanceState Instance saved during previous session (unused).
   */
  @Override
  protected void onCreate ( final Bundle argSavedInstanceState )
  {
    super.onCreate ( argSavedInstanceState );
    // Fetch the UI elements which will be updated programatically during activity runtime.
    setContentView ( R.layout.activity_capture );

    m_objDocumentAreaView = (CDocumentAreaView) findViewById ( R.id.corners_view );
    m_objCameraView = (CCameraView) findViewById ( R.id.camera_view );
    // Select the camera to use and initialize it as well as its preview and the needed handlers.
    m_objPreviewImageListener = new CCaptureAnalysisRunner ();
    setupCameraViewListener ();
    setupCameraStatusCallback ();
    m_objPreviewThread = new HandlerThread ( "PreviewUpdate" );
    m_objCameraManager = (CameraManager) getSystemService ( Context.CAMERA_SERVICE );
    getCamera ();
    m_objHardwareStatus.onCreate ( this );
  }
  @Override
  protected void onResume ()
  {
    super.onResume ();

    m_objHardwareStatus.onResume ();
    m_objIdrsCapture.onResume ( this );
    openCamera ();
  }
  @Override
  protected void onPause ()
  {
    m_objIdrsCapture.onPause ();
    m_objHardwareStatus.onPause ();
    closeCamera ();
    super.onPause ();
  }

  private class CCaptureAnalysisRunner implements ImageReader.OnImageAvailableListener
  {

    public void onImageAvailable ( final ImageReader argImageReader )
    {
      final Image objCapturedImage = argImageReader.acquireLatestImage ();
      // The image may be null sometimes, so skip processing in such case
      if ( null != objCapturedImage )
      {
        final boolean bDocumentExposureOk = m_objHardwareStatus.isExposureOk ();
        final boolean bCameraFocusSet = ( bDocumentExposureOk && m_objHardwareStatus.isFocusSet ());
        final boolean bDeviceStable = ( bCameraFocusSet && m_objHardwareStatus.isDeviceStable ());

        final CIdrsCapture.CWorker objWorker = (( bDeviceStable || m_bForceCapture ) ? m_objIdrsCapture.tryLock () : null );
        if ( objWorker != null )
        {
          Log.i ( "CCaptureActivity", "An image is available and will be processed" );

          objWorker.setCurrentCapture ( objCapturedImage );
          objCapturedImage.close ();

          AsyncTask.execute ( new Runnable ()
          {
            @Override
            public void run ()
            {
              onImageAnalysisCompleted ( objWorker, objWorker.detectDocumentCorners ());
            }
          });
        }
        else
        {
          objCapturedImage.close ();
        }
        // In any case, the indicators must be updated
        runOnUiThread ( new Runnable ()
        {
          @Override
          public void run ()
          {

            if ( m_objDocumentAreaView.reduceIntensity ())
            {
              m_objCornersFlag.setChecked ( false );
              m_objAreaFlag.setChecked ( false );
            }
            m_objExposureFlag.setChecked ( bDocumentExposureOk );
            m_objFocusFlag.setChecked ( bCameraFocusSet );
            m_objStabilityFlag.setChecked ( bDeviceStable );
            m_objDocumentAreaView.invalidate ();
            m_objExposureFlag.invalidate ();
            m_objFocusFlag.invalidate ();
            m_objStabilityFlag.invalidate ();
          }
        });
      }
    }
    private void onImageAnalysisCompleted (final CIdrsCapture.CWorker argWorker, final CIdrsCapture.DocumentCorners argDocumentCorners)
    {

      if ( ! m_objIdrsCapture.isCaptureSelected ())
      {
        runOnUiThread(new Runnable()
        {
          @Override
          public void run()
          {
            m_objCornersFlag.setChecked(argDocumentCorners.bCornersFound);
            m_objAreaFlag.setChecked(argDocumentCorners.bTargetAreaOk);
            if (argDocumentCorners.bCornersFound)
            {
              m_objDocumentAreaView.setDetectedCorners(argDocumentCorners.xiCorners, argDocumentCorners.bTargetAreaOk);
            }
            m_objDocumentAreaView.invalidate();
            m_objCornersFlag.invalidate();
            m_objAreaFlag.invalidate();
          }
        });

        try
        {
          if (( argDocumentCorners.bCornersFound && argDocumentCorners.bTargetAreaOk ) || m_bForceCapture )
          {
     final int iCaptureQuality = m_bForceCapture ? 100 : argWorker.evaluateQuality ();

            boolean bCurrentCaptureSelected = false;
            boolean bCurrentCaptureForced = false;
            synchronized ( m_objCaptureSelectionLock )
            {
              if (iCaptureQuality >= CAPTURE_QUALITY_THRESHOLD && ! m_objIdrsCapture.isCaptureSelected ())
              {
                argWorker.selectCapture();
                bCurrentCaptureSelected = true;
                if ( m_bForceCapture )
                {
                  bCurrentCaptureForced = true;
                  m_bForceCapture = false;
                }
              }
            }
            // Update the controls only if no capture are currently selected or if this capture is the one selected
            final boolean bCurrentCaptureSelectedFinal = bCurrentCaptureSelected;
            final boolean bCurrentCaptureForcedFinal = bCurrentCaptureForced;
            if ( bCurrentCaptureSelected || ! m_objIdrsCapture.isCaptureSelected ())
            {
              runOnUiThread(new Runnable()
              {
                @Override
                public void run()
                {
                  if ( ! bCurrentCaptureForcedFinal )
                  {
                    m_objImageQualityBar.setProgress(iCaptureQuality);
                  }
                  if ( bCurrentCaptureSelectedFinal )
                  {
                    m_objDocumentAreaView.setCaptureValidated();
                  }
                  m_objImageQualityBar.invalidate();
                  m_objCameraView.invalidate();
                }
              });

              if ( bCurrentCaptureSelected )
              {

                final String strSelectedImagePath = CPathProvider.getInternalPathSelectedImage ();
                argWorker.saveSelectedCapture ( strSelectedImagePath );

                final Intent objCaptureCorrectionIntent = new Intent ( CCaptureActivity.this, CAdjustmentActivity.class );
                objCaptureCorrectionIntent.putExtra ( "EXTRA_CAPTURED_IMAGE", strSelectedImagePath );
                if ( argDocumentCorners.bCornersFound )
                {
                  objCaptureCorrectionIntent.putExtra ( "EXTRA_DETECTED_CORNERS", argDocumentCorners.xiCorners );
                }
                CCaptureActivity.this.startActivity ( objCaptureCorrectionIntent );
              }
            }
          }
        }
        finally
        {
          // Unlock the worker before exiting
          argWorker.unlock ();
        }
      }
    }
  }
  /**
   * Setup the listener class that links the view to the camera.
   */
  private void setupCameraViewListener ()
  {
    m_objCameraView.setSurfaceTextureListener ( new TextureView.SurfaceTextureListener ()
    {
      /**
       * Surface texture available handler.
       * @param argSurfaceTexture The surface texture (unused)
       * @param iWidth Surface texture width (unused)
       * @param iHeight Surface texture height (unused)
       */
      @Override
      public void onSurfaceTextureAvailable ( final SurfaceTexture argSurfaceTexture, final int iWidth, final int iHeight )
      {
        // No need to use the provided parameters - simply open the camera.
        openCamera ();
      }

      @Override
      public void onSurfaceTextureSizeChanged ( final SurfaceTexture argSurfaceTexture, final int iWidth, final int iHeight )
      {

      }

      @Override
      public boolean onSurfaceTextureDestroyed ( final SurfaceTexture argSurfaceTexture )
      {
        return true;
      }

      @Override
      public void onSurfaceTextureUpdated ( final SurfaceTexture argSurfaceTexture )
      {

      }
    });
  }
  /**
   * Setup the camera status callback listener.
   */
  private void setupCameraStatusCallback ()
  {
    m_objCameraStateCallback = new CameraDevice.StateCallback ()
    {
      /**
       * Camera open handler.
       * @param argCameraDevice The camera opened.
       */
      @Override
      public void onOpened ( final CameraDevice argCameraDevice )
      {
        m_objCameraDevice = argCameraDevice;
        startCamera ();
      }

      @Override
      public void onDisconnected ( final CameraDevice argCameraDevice )
      {
      }

      @Override
      public void onError ( final CameraDevice argCameraDevice, final int iError )
      {
        if ( m_objCameraDevice != null && m_objCameraDevice.getId ().equals ( argCameraDevice.getId ()))
        {
          Log.e ( "CCaptureActivity", "The camera encountered an error: " + iError );
        }
      }
    };
  }

  private void getCamera ()
  {
    try
    {
      // Parse all available cameras and select the first rear-facing found.
      m_strCameraId = null;
      CameraCharacteristics objCameraCharacteristics = null;
      final String[] xstrCameraIds = m_objCameraManager.getCameraIdList ();
      for ( final String strCurrentCameraId : xstrCameraIds )
      {
        objCameraCharacteristics = m_objCameraManager.getCameraCharacteristics ( strCurrentCameraId );
        if ( objCameraCharacteristics.get ( CameraCharacteristics.LENS_FACING ) == CameraCharacteristics.LENS_FACING_BACK )
        {
          m_strCameraId = strCurrentCameraId;
          break;
        }
      }
      if (m_strCameraId == null)
      {
        Log.e("CCaptureActivity", "Could not find device back camera");
      }

      final StreamConfigurationMap objStreamConfigurationMap = objCameraCharacteristics.get ( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP );
      m_iCameraOrientation = objCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
      // Finally, retrieve the capture and preview sizes.
      m_objCaptureSize = selectCaptureSize ( objStreamConfigurationMap.getOutputSizes ( ImageFormat.YUV_420_888 ), m_iCameraOrientation );
      m_objPreviewSize = selectPreviewSize ( objStreamConfigurationMap.getOutputSizes ( SurfaceTexture.class ), m_objCaptureSize );
      Log.i ("CCaptureActivity", "Capture size selected: " + m_objCaptureSize.getHeight () + " x " + m_objCaptureSize.getWidth ());
      m_objIdrsCapture.setCharacteristics ( m_objCaptureSize, m_iCameraOrientation );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred while retrieving the device camera", argException );
    }
  }

  private void openCamera ()
  {
    try
    {
      // Start or restart the preview handler if needed
      if ( ! m_objPreviewThread.isAlive() || m_objPreviewThread.isInterrupted ())
      {
        m_objPreviewThread.start();
      }
      m_objPreviewThreadHandler = new Handler ( m_objPreviewThread.getLooper ());
      m_objImageReader = ImageReader.newInstance ( m_objCaptureSize.getWidth (), m_objCaptureSize.getHeight (), ImageFormat.YUV_420_888, 2 );
      m_objImageReader.setOnImageAvailableListener ( m_objPreviewImageListener, m_objPreviewThreadHandler );

      m_objDocumentAreaView.setCaptureSize ( m_objCaptureSize, m_iCameraOrientation );
      m_objCameraView.setCaptureSize ( m_objCaptureSize );
      m_objCameraManager.openCamera ( m_strCameraId, m_objCameraStateCallback,null );
      m_bCameraOpen = true;
    }
    catch ( final SecurityException argSecurityException )
    {
      Log.e ( "CCaptureActivity", "A security exception occurred while opening the device camera", argSecurityException );
    }
    catch (final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred while opening the device camera", argException );
    }
  }

  private void startCamera ()
  {

    if ( m_objCameraDevice == null || ! m_objCameraView.isAvailable () || m_objPreviewSize == null )
    {
      return;
    }
    final SurfaceTexture argSurfaceTexture = m_objCameraView.getSurfaceTexture ();
    if ( argSurfaceTexture == null )
    {
      return;
    }

    argSurfaceTexture.setDefaultBufferSize ( m_objPreviewSize.getWidth (), m_objPreviewSize.getHeight ());
    final Surface argSurface = new Surface ( argSurfaceTexture );
    try
    {
      m_objCaptureRequestBuilder = m_objCameraDevice.createCaptureRequest ( CameraDevice.TEMPLATE_PREVIEW );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred when creating the capture request", argException );
    }
    m_objCaptureRequestBuilder.addTarget ( argSurface );
    m_objCaptureRequestBuilder.addTarget ( m_objImageReader.getSurface ());

    try
    {
      m_objCameraDevice.createCaptureSession ( Arrays.asList ( argSurface, m_objImageReader.getSurface ()),
        new CameraCaptureSession.StateCallback ()
        {

          @Override
          public void onConfigured ( final CameraCaptureSession argCameraCaptureSession )
          {
            m_objCameraCaptureSession = argCameraCaptureSession;
            onCaptureSessionConfigured ();
          }

          @Override
          public void onConfigureFailed ( final CameraCaptureSession argCameraCaptureSession )
          {
            Log.e ("CCaptureActivity", "The camera capture session could not be successfully created." );
          }
        },
        null );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred when creating the capture session", argException );
    }
  }
  /**
   * Callback that will start capture session once it is configured.
   */
  private void onCaptureSessionConfigured ()
  {
    if ( m_objCameraDevice == null )
    {
      return;
    }
    m_objCaptureRequestBuilder.set ( CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO );
    try
    {
      m_objCameraCaptureSession.setRepeatingRequest ( m_objCaptureRequestBuilder.build (),
        m_objHardwareStatus,
        m_objPreviewThreadHandler );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occured while starting capture session", argException );
    }
  }
  private void closeCamera ()
  {
    if ( m_bCameraOpen )
    {
      m_objCameraDevice.close ();
      m_bCameraOpen = false;
    }
    if( m_objCameraCaptureSession != null )
    {
      m_objCameraCaptureSession.close();
    }
  }

  private Size selectCaptureSize ( final Size [] xargSizes, final int iCameraOrientation )
  {
    // Retrieve the screen dimensions to know its aspect ratio
    final DisplayMetrics objDisplayMetrics = new DisplayMetrics ();
    getWindowManager().getDefaultDisplay ().getMetrics ( objDisplayMetrics );
    final float fScreenRatio = (float) objDisplayMetrics.widthPixels / objDisplayMetrics.heightPixels;
    Size objMaxSizeSameRatio = null;
    Size objMaxSizeAnyRatio = null;
    // Now iterates on the list to find the largest (in area) below the accepted limit
    for (final Size objCurrent : xargSizes )
    {
      final int iAreaSize = objCurrent.getHeight () * objCurrent.getWidth ();
      final float fSizeRatio;
      if ( iCameraOrientation == 0 || iCameraOrientation == 180)
      {
        fSizeRatio = (float) objCurrent.getWidth () / objCurrent.getHeight ();
      }
      else
      {
        fSizeRatio = (float) objCurrent.getHeight () / objCurrent.getWidth ();
      }
      if ( iAreaSize < CAPTURE_SIZE_MAX_PIXELS )
      {
        // Search with same ratio
        if ( fSizeRatio == fScreenRatio &&
          ( objMaxSizeSameRatio == null || ( objMaxSizeSameRatio.getWidth () * objMaxSizeSameRatio.getHeight () < iAreaSize )))
        {
          objMaxSizeSameRatio = objCurrent;
        }
        // Search as well without taking the ratio into account
        if ( objMaxSizeAnyRatio == null || ( objMaxSizeAnyRatio.getWidth () * objMaxSizeAnyRatio.getHeight () < iAreaSize ))
        {
          objMaxSizeAnyRatio = objCurrent;
        }
      }
    }
    return objMaxSizeSameRatio != null ? objMaxSizeSameRatio : objMaxSizeAnyRatio;
  }



公共类CCaptureActivity扩展了AppCompativity
{
/**
*活动创建处理程序。
*@param argSavedInstanceState实例在上一个会话期间保存(未使用)。
*/
@凌驾
创建时受保护的void(最终绑定argSavedInstanceState)
{
super.onCreate(argSavedInstanceState);
//获取将在活动运行时以编程方式更新的UI元素。
setContentView(R.layout.activity_捕获);
m_objDocumentAreaView=(CDocumentAreaView)findviewbyd(R.id.corners_视图);
m_objCameraView=(CCameraView)findViewById(R.id.camera_视图);
//选择要使用和初始化的摄影机及其预览和所需的处理程序。
m_objPreviewImageListener=新的CCaptureAnalysisRunner();
setupCameraViewListener();
setupCameraStatusCallback();
m_objPreviewThread=新的HandlerThread(“PreviewUpdate”);
m_objCameraManager=(CameraManager)getSystemService(Context.CAMERA_服务);
getCamera();
m_objHardwareStatus.onCreate(本);
}
@凌驾
恢复时受保护的无效()
{
super.onResume();
m_objHardwareStatus.onResume();
m_objidrscature.onResume(本文件);
openCamera();
}
@凌驾
受保护的void onPause()
{
m_objIdrsCapture.onPause();
m_objHardwareStatus.onPause();
闭式摄像机();
super.onPause();
}
私有类CCaptureAnalysisRunner实现ImageReader.OnImageAvailableListener
{
公共无效onImageAvailable(最终图像阅读器argImageReader)
{
最终图像objCapturedImage=argImageReader.acquireLatestImage();
//图像有时可能为空,因此在这种情况下跳过处理
if(null!=objCapturedImage)
{
最终布尔值bDocumentExposureOk=m_objHardwareStatus.isExposureOk();
最终布尔值bCameraFocusSet=(bDocumentExposureOk&m_objHardwareStatus.isFocusSet());
最终布尔值bDeviceStable=(bCameraFocusSet&m_objHardwareStatus.isDeviceStable());
final cidrscapt.CWorker objWorker=((bDeviceStable | | | m| u bForceCapture)?m_objidrscature.tryLock():null);
if(objWorker!=null)
{
Log.i(“CCaptureActivity”,“图像可用并将被处理”);
objWorker.setCurrentCapture(objCapturedImage);
objCapturedImage.close();
AsyncTask.execute(新的可运行()
{
@凌驾
公开作废运行()
{
onImageAnalysisCompleted(objWorker,objWorker.detectDocumentCorners());
}
});
}
其他的
{
objCapturedImage.close();
}
//在任何情况下,都必须更新指标
runOnUiThread(新的可运行()
{
@凌驾
公开作废运行()
{
if(m_objDocumentAreaView.reduceIntensity())
{
m_objCornersFlag.setChecked(false);
m_objAreaFlag.setChecked(false);
}
m_objeexposureflag.setChecked(bDocumentExposureOk);
m_objFocusFlag.setChecked(bCameraFocusSet);
m_objStabilityFlag.setChecked(bDeviceStable);
m_objDocumentAreaView.invalidate();
m_objeexposureflag.invalidate();
m_objFocusFlag.invalidate();
m_objStabilityFlag.invalidate();
}
});
}
}
私有void onImageAnalysisCompleted(最终CIdrsCapture.CWorker argWorker,最终CIdrsCapture.DocumentCorners argDocumentCorners)
{
如果(!m_objidrscature.isCaptureSelected())
{
runOnUiThread(新的Runnable()
{
@凌驾
公开募捐
{
m_objCornersFlag.setChecked(argDocumentCorners.bCornersFound);
m_objAreaFlag.setChecked(argDocumentCorners.bTargetAreaOk);
if(argDocumentCorners.bCornersFound)
{
m_objDocumentAreaView.setDetectedCorners(argDocumentCorners.xicorner,argDocumentCorners.bTargetAreaOk);
}
m_objDocumentAreaView.invalidate();
m_objCornersFlag.invalidate();
m_objAreaFlag.invalidate();
}
});
尝试
{
if((argDocumentCorners.bCornersFound&&argDocumentCorners.bTargetAreaOk)| | m| bForceCapture)
{
final int iCaptureQuality=m_bForceCapture?100:argWorker.evaluateQuality();
布尔bCurrentCaptureSelected=false;
布尔bCurrentCaptureForced=false;
已同步(m_objCaptureSelectionLock)
{
如果(iCaptureQuality>=CAPTURE_QUALITY_THRESHOLD&&!m_objidrscature.isCaptureSelected())
{
argWorker.selectCapture();
bCurrentCaptureSelected=true;
如果(m_b力容)
{
bCurrentCaptureForced=真;
m_bForceCapture=假;
}
}
}
//仅当当前未选择捕获或此捕获是选定的捕获时,才更新控件
最终布尔值bCurrentCaptureSelectedFinal=bCurrentCaptureSelected;
最终布尔值bCurrentCaptureForcedFinal=bCurrentCaptureForced;
如果(bCurrentCaptureSelected | | |!m_objidrscature.isCaptureSelected())
{
runOn

public class CCaptureActivity extends AppCompatActivity
{
  /**
   * Activity creation handler.
   * @param argSavedInstanceState Instance saved during previous session (unused).
   */
  @Override
  protected void onCreate ( final Bundle argSavedInstanceState )
  {
    super.onCreate ( argSavedInstanceState );
    // Fetch the UI elements which will be updated programatically during activity runtime.
    setContentView ( R.layout.activity_capture );

    m_objDocumentAreaView = (CDocumentAreaView) findViewById ( R.id.corners_view );
    m_objCameraView = (CCameraView) findViewById ( R.id.camera_view );
    // Select the camera to use and initialize it as well as its preview and the needed handlers.
    m_objPreviewImageListener = new CCaptureAnalysisRunner ();
    setupCameraViewListener ();
    setupCameraStatusCallback ();
    m_objPreviewThread = new HandlerThread ( "PreviewUpdate" );
    m_objCameraManager = (CameraManager) getSystemService ( Context.CAMERA_SERVICE );
    getCamera ();
    m_objHardwareStatus.onCreate ( this );
  }
  @Override
  protected void onResume ()
  {
    super.onResume ();

    m_objHardwareStatus.onResume ();
    m_objIdrsCapture.onResume ( this );
    openCamera ();
  }
  @Override
  protected void onPause ()
  {
    m_objIdrsCapture.onPause ();
    m_objHardwareStatus.onPause ();
    closeCamera ();
    super.onPause ();
  }

  private class CCaptureAnalysisRunner implements ImageReader.OnImageAvailableListener
  {

    public void onImageAvailable ( final ImageReader argImageReader )
    {
      final Image objCapturedImage = argImageReader.acquireLatestImage ();
      // The image may be null sometimes, so skip processing in such case
      if ( null != objCapturedImage )
      {
        final boolean bDocumentExposureOk = m_objHardwareStatus.isExposureOk ();
        final boolean bCameraFocusSet = ( bDocumentExposureOk && m_objHardwareStatus.isFocusSet ());
        final boolean bDeviceStable = ( bCameraFocusSet && m_objHardwareStatus.isDeviceStable ());

        final CIdrsCapture.CWorker objWorker = (( bDeviceStable || m_bForceCapture ) ? m_objIdrsCapture.tryLock () : null );
        if ( objWorker != null )
        {
          Log.i ( "CCaptureActivity", "An image is available and will be processed" );

          objWorker.setCurrentCapture ( objCapturedImage );
          objCapturedImage.close ();

          AsyncTask.execute ( new Runnable ()
          {
            @Override
            public void run ()
            {
              onImageAnalysisCompleted ( objWorker, objWorker.detectDocumentCorners ());
            }
          });
        }
        else
        {
          objCapturedImage.close ();
        }
        // In any case, the indicators must be updated
        runOnUiThread ( new Runnable ()
        {
          @Override
          public void run ()
          {

            if ( m_objDocumentAreaView.reduceIntensity ())
            {
              m_objCornersFlag.setChecked ( false );
              m_objAreaFlag.setChecked ( false );
            }
            m_objExposureFlag.setChecked ( bDocumentExposureOk );
            m_objFocusFlag.setChecked ( bCameraFocusSet );
            m_objStabilityFlag.setChecked ( bDeviceStable );
            m_objDocumentAreaView.invalidate ();
            m_objExposureFlag.invalidate ();
            m_objFocusFlag.invalidate ();
            m_objStabilityFlag.invalidate ();
          }
        });
      }
    }
    private void onImageAnalysisCompleted (final CIdrsCapture.CWorker argWorker, final CIdrsCapture.DocumentCorners argDocumentCorners)
    {

      if ( ! m_objIdrsCapture.isCaptureSelected ())
      {
        runOnUiThread(new Runnable()
        {
          @Override
          public void run()
          {
            m_objCornersFlag.setChecked(argDocumentCorners.bCornersFound);
            m_objAreaFlag.setChecked(argDocumentCorners.bTargetAreaOk);
            if (argDocumentCorners.bCornersFound)
            {
              m_objDocumentAreaView.setDetectedCorners(argDocumentCorners.xiCorners, argDocumentCorners.bTargetAreaOk);
            }
            m_objDocumentAreaView.invalidate();
            m_objCornersFlag.invalidate();
            m_objAreaFlag.invalidate();
          }
        });

        try
        {
          if (( argDocumentCorners.bCornersFound && argDocumentCorners.bTargetAreaOk ) || m_bForceCapture )
          {
     final int iCaptureQuality = m_bForceCapture ? 100 : argWorker.evaluateQuality ();

            boolean bCurrentCaptureSelected = false;
            boolean bCurrentCaptureForced = false;
            synchronized ( m_objCaptureSelectionLock )
            {
              if (iCaptureQuality >= CAPTURE_QUALITY_THRESHOLD && ! m_objIdrsCapture.isCaptureSelected ())
              {
                argWorker.selectCapture();
                bCurrentCaptureSelected = true;
                if ( m_bForceCapture )
                {
                  bCurrentCaptureForced = true;
                  m_bForceCapture = false;
                }
              }
            }
            // Update the controls only if no capture are currently selected or if this capture is the one selected
            final boolean bCurrentCaptureSelectedFinal = bCurrentCaptureSelected;
            final boolean bCurrentCaptureForcedFinal = bCurrentCaptureForced;
            if ( bCurrentCaptureSelected || ! m_objIdrsCapture.isCaptureSelected ())
            {
              runOnUiThread(new Runnable()
              {
                @Override
                public void run()
                {
                  if ( ! bCurrentCaptureForcedFinal )
                  {
                    m_objImageQualityBar.setProgress(iCaptureQuality);
                  }
                  if ( bCurrentCaptureSelectedFinal )
                  {
                    m_objDocumentAreaView.setCaptureValidated();
                  }
                  m_objImageQualityBar.invalidate();
                  m_objCameraView.invalidate();
                }
              });

              if ( bCurrentCaptureSelected )
              {

                final String strSelectedImagePath = CPathProvider.getInternalPathSelectedImage ();
                argWorker.saveSelectedCapture ( strSelectedImagePath );

                final Intent objCaptureCorrectionIntent = new Intent ( CCaptureActivity.this, CAdjustmentActivity.class );
                objCaptureCorrectionIntent.putExtra ( "EXTRA_CAPTURED_IMAGE", strSelectedImagePath );
                if ( argDocumentCorners.bCornersFound )
                {
                  objCaptureCorrectionIntent.putExtra ( "EXTRA_DETECTED_CORNERS", argDocumentCorners.xiCorners );
                }
                CCaptureActivity.this.startActivity ( objCaptureCorrectionIntent );
              }
            }
          }
        }
        finally
        {
          // Unlock the worker before exiting
          argWorker.unlock ();
        }
      }
    }
  }
  /**
   * Setup the listener class that links the view to the camera.
   */
  private void setupCameraViewListener ()
  {
    m_objCameraView.setSurfaceTextureListener ( new TextureView.SurfaceTextureListener ()
    {
      /**
       * Surface texture available handler.
       * @param argSurfaceTexture The surface texture (unused)
       * @param iWidth Surface texture width (unused)
       * @param iHeight Surface texture height (unused)
       */
      @Override
      public void onSurfaceTextureAvailable ( final SurfaceTexture argSurfaceTexture, final int iWidth, final int iHeight )
      {
        // No need to use the provided parameters - simply open the camera.
        openCamera ();
      }

      @Override
      public void onSurfaceTextureSizeChanged ( final SurfaceTexture argSurfaceTexture, final int iWidth, final int iHeight )
      {

      }

      @Override
      public boolean onSurfaceTextureDestroyed ( final SurfaceTexture argSurfaceTexture )
      {
        return true;
      }

      @Override
      public void onSurfaceTextureUpdated ( final SurfaceTexture argSurfaceTexture )
      {

      }
    });
  }
  /**
   * Setup the camera status callback listener.
   */
  private void setupCameraStatusCallback ()
  {
    m_objCameraStateCallback = new CameraDevice.StateCallback ()
    {
      /**
       * Camera open handler.
       * @param argCameraDevice The camera opened.
       */
      @Override
      public void onOpened ( final CameraDevice argCameraDevice )
      {
        m_objCameraDevice = argCameraDevice;
        startCamera ();
      }

      @Override
      public void onDisconnected ( final CameraDevice argCameraDevice )
      {
      }

      @Override
      public void onError ( final CameraDevice argCameraDevice, final int iError )
      {
        if ( m_objCameraDevice != null && m_objCameraDevice.getId ().equals ( argCameraDevice.getId ()))
        {
          Log.e ( "CCaptureActivity", "The camera encountered an error: " + iError );
        }
      }
    };
  }

  private void getCamera ()
  {
    try
    {
      // Parse all available cameras and select the first rear-facing found.
      m_strCameraId = null;
      CameraCharacteristics objCameraCharacteristics = null;
      final String[] xstrCameraIds = m_objCameraManager.getCameraIdList ();
      for ( final String strCurrentCameraId : xstrCameraIds )
      {
        objCameraCharacteristics = m_objCameraManager.getCameraCharacteristics ( strCurrentCameraId );
        if ( objCameraCharacteristics.get ( CameraCharacteristics.LENS_FACING ) == CameraCharacteristics.LENS_FACING_BACK )
        {
          m_strCameraId = strCurrentCameraId;
          break;
        }
      }
      if (m_strCameraId == null)
      {
        Log.e("CCaptureActivity", "Could not find device back camera");
      }

      final StreamConfigurationMap objStreamConfigurationMap = objCameraCharacteristics.get ( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP );
      m_iCameraOrientation = objCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
      // Finally, retrieve the capture and preview sizes.
      m_objCaptureSize = selectCaptureSize ( objStreamConfigurationMap.getOutputSizes ( ImageFormat.YUV_420_888 ), m_iCameraOrientation );
      m_objPreviewSize = selectPreviewSize ( objStreamConfigurationMap.getOutputSizes ( SurfaceTexture.class ), m_objCaptureSize );
      Log.i ("CCaptureActivity", "Capture size selected: " + m_objCaptureSize.getHeight () + " x " + m_objCaptureSize.getWidth ());
      m_objIdrsCapture.setCharacteristics ( m_objCaptureSize, m_iCameraOrientation );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred while retrieving the device camera", argException );
    }
  }

  private void openCamera ()
  {
    try
    {
      // Start or restart the preview handler if needed
      if ( ! m_objPreviewThread.isAlive() || m_objPreviewThread.isInterrupted ())
      {
        m_objPreviewThread.start();
      }
      m_objPreviewThreadHandler = new Handler ( m_objPreviewThread.getLooper ());
      m_objImageReader = ImageReader.newInstance ( m_objCaptureSize.getWidth (), m_objCaptureSize.getHeight (), ImageFormat.YUV_420_888, 2 );
      m_objImageReader.setOnImageAvailableListener ( m_objPreviewImageListener, m_objPreviewThreadHandler );

      m_objDocumentAreaView.setCaptureSize ( m_objCaptureSize, m_iCameraOrientation );
      m_objCameraView.setCaptureSize ( m_objCaptureSize );
      m_objCameraManager.openCamera ( m_strCameraId, m_objCameraStateCallback,null );
      m_bCameraOpen = true;
    }
    catch ( final SecurityException argSecurityException )
    {
      Log.e ( "CCaptureActivity", "A security exception occurred while opening the device camera", argSecurityException );
    }
    catch (final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred while opening the device camera", argException );
    }
  }

  private void startCamera ()
  {

    if ( m_objCameraDevice == null || ! m_objCameraView.isAvailable () || m_objPreviewSize == null )
    {
      return;
    }
    final SurfaceTexture argSurfaceTexture = m_objCameraView.getSurfaceTexture ();
    if ( argSurfaceTexture == null )
    {
      return;
    }

    argSurfaceTexture.setDefaultBufferSize ( m_objPreviewSize.getWidth (), m_objPreviewSize.getHeight ());
    final Surface argSurface = new Surface ( argSurfaceTexture );
    try
    {
      m_objCaptureRequestBuilder = m_objCameraDevice.createCaptureRequest ( CameraDevice.TEMPLATE_PREVIEW );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred when creating the capture request", argException );
    }
    m_objCaptureRequestBuilder.addTarget ( argSurface );
    m_objCaptureRequestBuilder.addTarget ( m_objImageReader.getSurface ());

    try
    {
      m_objCameraDevice.createCaptureSession ( Arrays.asList ( argSurface, m_objImageReader.getSurface ()),
        new CameraCaptureSession.StateCallback ()
        {

          @Override
          public void onConfigured ( final CameraCaptureSession argCameraCaptureSession )
          {
            m_objCameraCaptureSession = argCameraCaptureSession;
            onCaptureSessionConfigured ();
          }

          @Override
          public void onConfigureFailed ( final CameraCaptureSession argCameraCaptureSession )
          {
            Log.e ("CCaptureActivity", "The camera capture session could not be successfully created." );
          }
        },
        null );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occurred when creating the capture session", argException );
    }
  }
  /**
   * Callback that will start capture session once it is configured.
   */
  private void onCaptureSessionConfigured ()
  {
    if ( m_objCameraDevice == null )
    {
      return;
    }
    m_objCaptureRequestBuilder.set ( CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO );
    try
    {
      m_objCameraCaptureSession.setRepeatingRequest ( m_objCaptureRequestBuilder.build (),
        m_objHardwareStatus,
        m_objPreviewThreadHandler );
    }
    catch ( final Exception argException )
    {
      Log.e ( "CCaptureActivity", "An exception occured while starting capture session", argException );
    }
  }
  private void closeCamera ()
  {
    if ( m_bCameraOpen )
    {
      m_objCameraDevice.close ();
      m_bCameraOpen = false;
    }
    if( m_objCameraCaptureSession != null )
    {
      m_objCameraCaptureSession.close();
    }
  }

  private Size selectCaptureSize ( final Size [] xargSizes, final int iCameraOrientation )
  {
    // Retrieve the screen dimensions to know its aspect ratio
    final DisplayMetrics objDisplayMetrics = new DisplayMetrics ();
    getWindowManager().getDefaultDisplay ().getMetrics ( objDisplayMetrics );
    final float fScreenRatio = (float) objDisplayMetrics.widthPixels / objDisplayMetrics.heightPixels;
    Size objMaxSizeSameRatio = null;
    Size objMaxSizeAnyRatio = null;
    // Now iterates on the list to find the largest (in area) below the accepted limit
    for (final Size objCurrent : xargSizes )
    {
      final int iAreaSize = objCurrent.getHeight () * objCurrent.getWidth ();
      final float fSizeRatio;
      if ( iCameraOrientation == 0 || iCameraOrientation == 180)
      {
        fSizeRatio = (float) objCurrent.getWidth () / objCurrent.getHeight ();
      }
      else
      {
        fSizeRatio = (float) objCurrent.getHeight () / objCurrent.getWidth ();
      }
      if ( iAreaSize < CAPTURE_SIZE_MAX_PIXELS )
      {
        // Search with same ratio
        if ( fSizeRatio == fScreenRatio &&
          ( objMaxSizeSameRatio == null || ( objMaxSizeSameRatio.getWidth () * objMaxSizeSameRatio.getHeight () < iAreaSize )))
        {
          objMaxSizeSameRatio = objCurrent;
        }
        // Search as well without taking the ratio into account
        if ( objMaxSizeAnyRatio == null || ( objMaxSizeAnyRatio.getWidth () * objMaxSizeAnyRatio.getHeight () < iAreaSize ))
        {
          objMaxSizeAnyRatio = objCurrent;
        }
      }
    }
    return objMaxSizeSameRatio != null ? objMaxSizeSameRatio : objMaxSizeAnyRatio;
  }