¿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.
- Descripción de la matriz de proyección libGDX
- Android Rotar imagen antes de guardar
- seleccione la cámara frontal
- Diferencia entre Camera.translate y Matrix.preTranslate o Matrix.postTranslate?
- Selector con intención de cámara e intención de selección de imágenes
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); } } } }
- Problema de orientación de la cámara en Android
- Obtener ruta y nombre de archivo del resultado de la intención de la cámara
- Mensaje de logcat de Android (E / SMD: DCD activado)
- Graves bloqueos de cámara y RuntimeException en Android
- Android 1.6 Rotación de la cámara?
- Cómo podemos medir la distancia entre el objeto y la cámara del teléfono android
- Funciones de la cámara Android no funcionan en algunos teléfonos
- Vista de la superficie de la cámara
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 elautoFocusCb
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 llamadamAutoFocusCallback
.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
puededoAutoFocus
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.
- RenderScript no procesa ScriptIntrinsicBlur correctamente, haciendo que ScriptIntrinsicBlur genere un arco iris de colores
- Cómo abrir una URL desde el terminal