Ejemplo de cámara en Android
camera android-camera (3)
Quiero escribir una actividad que:
- Muestra la vista previa de la cámara (visor) y tiene un botón de "captura".
- Cuando se presiona el botón "capturar", toma una foto y la regresa a la actividad de llamada (setResult () & finish ()).
¿Hay ejemplos completos por ahí que funcionen en todos los dispositivos ? Un enlace a una aplicación de código abierto simple que tome fotografías sería la respuesta ideal.
Mi investigación hasta ahora:
Este es un escenario común, y hay muchas preguntas y tutoriales sobre esto.
Hay dos enfoques principales:
- Utilice el evento android.provider.MediaStore.ACTION_IMAGE_CAPTURE. Ver esta pregunta
- Usa la API de la cámara directamente. Vea este ejemplo o esta pregunta (con muchas referencias) .
El enfoque 1 hubiera sido perfecto, pero el problema es que la intención se implementa de manera diferente en cada dispositivo. En algunos dispositivos funciona bien. Sin embargo, en algunos dispositivos puede tomar una foto, pero nunca se devuelve a su aplicación. En algunos dispositivos no pasa nada cuando lanzas la intención. Por lo general, también guarda la imagen en la tarjeta SD y requiere que la tarjeta SD esté presente. La interacción del usuario también es diferente en cada dispositivo.
Con el enfoque 2 los problemas son la estabilidad. Probé algunos ejemplos, pero logré detener el funcionamiento de la cámara (hasta que se reinicie) en algunos dispositivos y congelar completamente otro dispositivo. En otro dispositivo la captura funcionó, pero la vista previa se mantuvo en negro.
Habría usado ZXing como una aplicación de ejemplo (trabajo mucho con ella), pero solo usa la vista previa (visor) y no toma ninguna foto. También descubrí que en algunos dispositivos, ZXing no ajustaba automáticamente el balance de blancos cuando cambiaban las condiciones de iluminación, mientras que la aplicación nativa de la cámara lo hacía correctamente (no estoy seguro de si esto se puede arreglar).
Actualizar:
Por un tiempo usé la API de la cámara directamente. Esto da más control (IU personalizada, etc.), pero no lo recomendaría a nadie. Trabajaría en el 90% de los dispositivos, pero de vez en cuando se lanzaría un nuevo dispositivo, con un problema diferente.
Algunos de los problemas que he encontrado:
- Manejo de autofocus
- Manejo de flash
- Dispositivos compatibles con una cámara frontal, cámara trasera o ambos
- Cada dispositivo tiene una combinación diferente de resolución de pantalla, resoluciones de vista previa (no siempre coincide con la resolución de pantalla) y resoluciones de imagen.
Por lo tanto, en general, no recomendaría esta ruta, a menos que no haya otra manera. Después de dos años dejé el código personalizado y volví al enfoque basado en Intent. Desde entonces he tenido muchos menos problemas. Los problemas que he tenido con el enfoque basado en la Intención en el pasado probablemente fueron solo mi propia incompetencia.
Si realmente necesitas seguir esta ruta, he oído que es mucho más fácil si solo admites dispositivos con Android 4.0+.
Con el enfoque 2 los problemas son la estabilidad. Probé algunos ejemplos, pero logré detener el funcionamiento de la cámara (hasta que se reinicie) en algunos dispositivos y congelar completamente otro dispositivo. En otro dispositivo la captura funcionó, pero la vista previa se mantuvo en negro.
O bien hay un error en los ejemplos o hay un problema de compatibilidad con los dispositivos.
El ejemplo que CommonsWare dio funciona bien. El ejemplo funciona cuando se usa tal como está, pero aquí están los problemas que encontré al modificarlo para mi caso de uso:
- Nunca tome una segunda imagen antes de que se complete la primera imagen, en otras palabras, se ha llamado a
PictureCallback.onPictureTaken()
. El ejemplo de CommonsWare usa la banderainPreview
para este propósito. - Asegúrese de que su
SurfaceView
esté en pantalla completa. Si desea una vista previa más pequeña, es posible que deba cambiar la lógica de selección del tamaño de la vista previa, de lo contrario, la vista previa podría no encajar enSurfaceView
en algunos dispositivos. Algunos dispositivos solo admiten un tamaño de vista previa de pantalla completa, por lo que mantenerla a pantalla completa es la solución más sencilla.
Para agregar más componentes a la pantalla de vista previa, FrameLayout
funciona bien en mi experiencia. Comencé usando un LinearLayout
para agregar texto sobre la vista previa, pero eso rompió la regla # 2. Al usar un FrameLayout
para agregar componentes en la parte superior de la vista previa, no tiene ningún problema con la resolución de la vista previa.
También Camera.open()
un problema menor relacionado con Camera.open()
en GitHub .
"la forma recomendada para acceder a la cámara es abrir la cámara en una secuencia separada" . De lo contrario, Camera.open() puede tardar un tiempo y puede atascar el hilo de la interfaz de usuario.
"Las devoluciones de llamada se invocarán en el subproceso de evento abierto (int) desde el que se llamó" . Es por eso que para obtener el mejor rendimiento con devoluciones de llamada de vista previa de la cámara (por ejemplo, para codificarlas en un video de baja latencia para comunicación en vivo), recomiendo abrir la cámara en un nuevo HandlerThread, como se muestra here .