¿Por qué la cámara automática de enfoque automático con el manipulador no permiten cambiar el flash de la cámara?

Lo que he hecho hasta ahora:

He implementado la cámara de encargo para la lectura del código del qr que necesita continuar foco la cámara para una mejor lectura del qr.

Mi problema es cuando utilizo para enfocar en cada segundo con el manejador el flash de la cámara en el botón de apagado no funciona o se tarda demasiado tiempo para encender y apagar la luz del flash de la cámara. Cada cosa funciona muy bien cuando se quita el código de enfoque automático de la cámara cada segundo (El runnable y el manejador).

Lo que quiero es enfocar automáticamente y rápidamente cada vez que la cámara se mueve y también puede encender y apagar el flash a petición rápidamente sin usar Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE porque no está disponible para API<14 .

He utilizado Camera.Parameters.FOCUS_MODE_AUTO pero su único enfoque de la cámara una vez cuando se inició thats por qué utiliza handler para enfocar la cámara cada segundo.

Min SDK Versión del proyecto es 9.

Mi actividad de cámara es

 public class CameraActivityNew extends Activity implements OnClickListener, Camera.PreviewCallback { CameraPreviewNew mPreview; FrameLayout flCameraPreview; ImageButton ibFlashButton; Boolean isFlashOn = false; Camera mCamera; private Handler mAutoFocusHandler; private boolean mPreviewing = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); mAutoFocusHandler = new Handler(); setContentView(R.layout.activity_camera); findSetupViews(); mPreview = new CameraPreviewNew(getApplicationContext(), this, autoFocusCB); flCameraPreview.addView(mPreview); } private Runnable doAutoFocus = new Runnable() { public void run() { if (mCamera != null && mPreviewing) { mCamera.autoFocus(autoFocusCB); } } }; Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() { public void onAutoFocus(boolean success, Camera camera) { mAutoFocusHandler.postDelayed(doAutoFocus, 1000); } }; @Override protected void onResume() { super.onResume(); try { mCamera = Camera.open(); if (mCamera == null) { return; } } catch (Exception e) { e.printStackTrace(); return; } mPreview.setCamera(mCamera); mPreview.showSurfaceView(); mPreviewing = true; } @Override protected void onPause() { super.onPause(); if (mCamera != null) { mPreview.setCamera(null); mCamera.cancelAutoFocus(); mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mPreview.hideSurfaceView(); mPreviewing = false; mCamera = null; } } private void findSetupViews() { flCameraPreview = (FrameLayout) findViewById(R.id.flCameraPreview); ibFlashButton = (ImageButton) findViewById(R.id.ibFlash); ibFlashButton.setOnClickListener(this); if (getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA_FLASH)) { ibFlashButton.setVisibility(View.VISIBLE); ibFlashButton.setOnClickListener(this); } else { ibFlashButton.setVisibility(View.GONE); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.ibFlash: if (isFlashOn) { mPreview.setCameraFlashLight(false); isFlashOn = false; ibFlashButton.setImageResource(R.drawable.flashoff); } else { mPreview.setCameraFlashLight(true); ibFlashButton.setImageResource(R.drawable.flashon); isFlashOn = true; } break; } } @Override public void onPreviewFrame(final byte[] data, final Camera camera) { // processed here qr code and works fine if camera focus //now removed to narrow the code for posting the question } } 

Y la clase de vista previa de cámara es:

 public class CameraPreviewNew extends ViewGroup implements Callback { public static final int CAMERA_BACK = 0; public static final int CAMERA_FRONT = 1; public Camera mCamera = null; private Context context = null; SurfaceView mSurfaceView; SurfaceHolder mSurfaceHolder; Size mPreviewSize; List<Size> mSupportedPreviewSizes; PreviewCallback mPreviewCallback; AutoFocusCallback mAutoFocusCallback; public CameraPreviewNew(Context context, PreviewCallback previewCallback, AutoFocusCallback autoFocusCb) { super(context); mPreviewCallback = previewCallback; mAutoFocusCallback = autoFocusCb; this.context = context; mSurfaceView = new SurfaceView(context); addView(mSurfaceView); mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.addCallback(this); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } } public void setCamera(Camera camera) { mCamera = camera; if (mCamera != null) { mSupportedPreviewSizes = mCamera.getParameters() .getSupportedPreviewSizes(); requestLayout(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width, height); } public void hideSurfaceView() { mSurfaceView.setVisibility(View.INVISIBLE); } public void showSurfaceView() { mSurfaceView.setVisibility(View.VISIBLE); } public void surfaceCreated(SurfaceHolder holder) { try { if (mCamera != null) { mCamera.setPreviewDisplay(holder); } } catch (IOException exception) { Log.e("logtag", "IOException caused by setPreviewDisplay()", exception); } } public void surfaceDestroyed(SurfaceHolder holder) { if (mCamera != null) { mCamera.cancelAutoFocus(); mCamera.stopPreview(); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (holder.getSurface() == null) { return; } if (mCamera != null) { Camera.Parameters parameters = mCamera.getParameters(); mPreviewSize = getBestPreviewSize(mCamera.getParameters(), w, h); parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); requestLayout(); mCamera.setParameters(parameters); mCamera.setPreviewCallback(mPreviewCallback); mCamera.startPreview(); mCamera.autoFocus(mAutoFocusCallback); setCameraDisplayOrientation(0); } } private void setCameraDisplayOrientation(int cameraId) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int rotation = ((WindowManager) context .getSystemService(Context.WINDOW_SERVICE)).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; } mCamera.setDisplayOrientation(result); } protected static Comparator<Size> newSizeComparator() { return new Comparator<Size>() { @Override public int compare(Size lhs, Size rhs) { return Integer.valueOf(rhs.height * rhs.width).compareTo( lhs.height * lhs.width); } }; } private Size getBestPreviewSize(Parameters parameters, int screenWidth, int screenHeight) { List<Size> supportedSizes = parameters.getSupportedPreviewSizes(); Collections.sort(supportedSizes, newSizeComparator()); int previewHeight = screenHeight; int previewWidth = screenWidth; if (previewHeight > previewWidth) { int swap = previewWidth; previewWidth = previewHeight; previewHeight = swap; } Size bestSize = null; float bestRatio = 999; for (Size s : supportedSizes) { if (s.height > s.width) { int swap = s.width; s.width = s.height; s.height = swap; } float cameraRatio = ((float) s.height / (float) s.width); float screenRatio = ((float) previewHeight) / ((float) previewWidth); if ((s.height >= previewHeight) && (s.width >= previewWidth)) { float ratioDiff = cameraRatio - screenRatio; if ((ratioDiff < 0.19) && (ratioDiff > -0.19) && (Math.abs(bestRatio) > Math.abs(ratioDiff))) { bestSize = s; bestRatio = ratioDiff; } } } return bestSize; } public void setCameraFlashLight(Boolean setFlash) { Parameters _parameters = mCamera.getParameters(); if (setFlash) { _parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); } else { _parameters.setFlashMode(Parameters.FLASH_MODE_OFF); } mCamera.setParameters(_parameters); mCamera.startPreview(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (changed && getChildCount() > 0) { final View child = getChildAt(0); final int width = r - l; final int height = b - t; int previewWidth = width; int previewHeight = height; if (mPreviewSize != null) { previewWidth = mPreviewSize.width; previewHeight = mPreviewSize.height; } if (width * previewHeight > height * previewWidth) { final int scaledChildWidth = previewWidth * height / previewHeight; child.layout((width - scaledChildWidth) / 2, 0, (width + scaledChildWidth) / 2, height); } else { final int scaledChildHeight = previewHeight * width / previewWidth; child.layout(0, (height - scaledChildHeight) / 2, width, (height + scaledChildHeight) / 2); } } } } 

Veo algún problema con el código de manejo de AutoFocus.
Resultado de analisis

Hay un ciclo en su autofoco.

Explicación

A) Clase de previsualización de la cámara mAutoFocusCallback se establece con el autoFocusCb de la actividad de la cámara .

  public CameraPreviewNew(Context context,...,AutoFocusCallback autoFocusCb) { super(context); mAutoFocusCallback = autoFocusCb; ... } 

B) surfaceChanged se llama una vez, en el momento de cargar la actividad. Se solicita la cámara al enfoque automático.

  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (mCamera != null) { ... mCamera.startPreview(); /*Auto focus camera and call <code>mAutoFocusCallback</code> after autofocus.*/ mCamera.autoFocus(mAutoFocusCallback); ... } } 

C) Al finalizar el autofoco se mAutoFocusCallback devolución de llamada mAutoFocusCallback . mAutoFocusCallback->autoFocusCb->onAutoFocus()
Actividad de la cámara

  Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() { public void onAutoFocus(boolean success, Camera camera) { mAutoFocusHandler.postDelayed(doAutoFocus, 1000); } }; 

D) onAutoFocus programa un autofoco más después de 1000 milisegundos, 1 seg.
Actividad de la cámara

  public void onAutoFocus(boolean success, Camera camera) { mAutoFocusHandler.postDelayed(doAutoFocus, 1000); } 

E) Después de un segundo, los mensajes se pasan al manejador que llama al doAutoFocus puede doAutoFocus solicitando que la cámara se enfoque automáticamente, similar a b) anterior.

  private Runnable doAutoFocus = new Runnable() { public void run() { if (mCamera != null && mPreviewing) { mCamera.autoFocus(autoFocusCB); } } }; 

F) Después de la finalización del autofoco, el autoFocusCB se llama de nuevo, similar a c) anterior. Y el ciclo continúa.

  Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() { public void onAutoFocus(boolean success, Camera camera) { mAutoFocusHandler.postDelayed(doAutoFocus, 1000); } }; 

Solución

Estoy confundido por qué tal aplicación. El ciclo puede ser motivo detrás de no escuchar las llamadas de habilitación / desactivación de flash. Usted necesita quitar el código abajo y hacer algo significativo más deje el onAutoFocus () vacío.

 Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() { public void onAutoFocus(boolean success, Camera camera) { /*REMOVE LINE BELOW*/ mAutoFocusHandler.postDelayed(doAutoFocus, 1000); } }; 

Para el enfoque automático cada vez que la cámara se mueve, necesita tomar la ayuda de los sensores de movimiento proporcionados con el teléfono. Puedes google

Espero que ayude.
Codificación feliz

Parece que no necesitas usar AutoFocusCallBack para tu aplicación, porque no hiciste nada más que delay 1 second .

Lo que puedes hacer para enfocar todo el tiempo es usar FOCUS_MODE_CONTINUOUS_PICTURE (leer más aquí ) así (el método setFocus está en CameraPreview , no en Activity ):

 public void setFocus() { Camera.Parameters p = mCamera.getParameters(); p.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); mCamera.setParameters(p); mCamera.startPreview(); } 

Y lo llaman en SurfaceChanged :

 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = mCamera.getParameters(); List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes(); // You need to choose the most appropriate previewSize for your app Camera.Size previewSize = previewSizes.get(0); parameters.setPreviewSize(previewSize.width, previewSize.height); parameters.setRotation(90); mCamera.setParameters(parameters); mCamera.startPreview(); setFlash(true); setZoomLevel(5); setFocus(); Log.w(TAG, "surfaceChanged()"); } 

Para flash , puede utilizar este método desde CameraPreview :

 public void setFlash(boolean isFlashOn) { Camera.Parameters p = mCamera.getParameters(); if (isFlashOn) { p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); mCamera.setParameters(p); mCamera.startPreview(); } else { p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); mCamera.setParameters(p); mCamera.startPreview(); } Log.w(TAG, "setFlash()"); } 

Espero que te ayude! Si tiene alguna pregunta sobre mi respuesta, no dude en comentar.

  • Android: ¿Cómo guardar un marco de vista previa como imagen jpeg?
  • Orientar correctamente los datos de la cámara en bruto
  • El brillo de la cámara de visión Android (móvil) es muy bajo
  • Cámara androide: onActivityResult () la intención es nula si tenía extras
  • Cámara Android - A veces, cuando tomo fotos, la aplicación se congela y la cámara no es utilizable
  • Snooker Aplicación para Android
  • Error 1001 de la cámara del androide - qué diablos es ése?
  • La cámara no funciona en Android 2.2
  • Cómo comprobar si el dispositivo tiene luz de flash led android
  • Android: toma fotos sin interfaz de usuario
  • Ideas de origen de QualcommCameraHardware native_get_picture: MSM_CAM_IOCTL_GET_PICTURE Error de tiempo de espera de conexión?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.