Spanish necesito desarrollar app que tome fotografias cada 10 min de manera automática

ricprehn

Member
Hola foreros,

Necesito desarrollar una app en B4A que tome fotografías cada 10 min de manera automática usando Camera2 en foreground.

Estoy intentando unir estos dos ejemplos, pero no me acabo de aclarar.

Pido presupuesto para experto que quiera ayudarme.

Gracias y saludos,
Ricard.
 

GeoT

Active Member
Licensed User
Longtime User
Last edited:

GeoT

Active Member
Licensed User
Longtime User
Hola ricprehn.
Rectifico.
Parece que no es necesario hacer una Activity transparente.
He conseguido unir los dos ejemplos que mencionas, y parece funcionar en mi dispositivo.
Pero aún he de pulir mi ejemplo, porque hay que parar el servicio de alguna manera, pues éste sigue funcionando y haciendo fotos aunque cierres del todo la aplicación.

Saludos.
 

ricprehn

Member
Hola GeoT,

Muy bien!! Mil gracias por dedicar tu tiempo y conocimiento!! yo he estado intentando unir los dos ejemplos y no lo he conseguido, llevo poco tiempo con B4A y me cuesta aun entender cómo funcionan los servicios, las activities... Si puedes publicar el código aquí te lo agradecería mucho, así lo pruebo con mi terminal a ver si corre bien, e intento buscar la manera de parar el servicio.

Saludos,
Ricard.
 
Last edited:

GeoT

Active Member
Licensed User
Longtime User
Hola ricprehn.
De nada. Entiendo.
Ya acabé todo el ejemplo y éste ya para el servicio.
Si, esta tarde con tiempo, si no pasa nada, lo publico y pongo algunas explicaciones.
Sí, a ver si funciona en otros dispositivos.

Saludos.
Manel.
 
Last edited:

GeoT

Active Member
Licensed User
Longtime User
Hola ricprehn.
Aquí adjunto el zip del proyecto con todo lo que cupo.
Al compilarlo te creará automáticamente lo que falta: la carpeta Objects y el archivo ScheduledPhotos.b4a.meta.

Espero que te sirva.
 

Attachments

  • ScheduledPhotos.zip
    14.7 KB · Views: 191
Last edited:

GeoT

Active Member
Licensed User
Longtime User
Y hago estas puntualizaciones:

- Lo primero es que escogiste bien los ejemplos-soluciones. Pues probé con un Timer y no funcionó.

- Este ejemplo funciona bien en mi Samsung Galaxy A50 con Android 11, pero falla en mi Galaxy Grand Prime+ con Android 6.0.1

- Hace fotos cada x segundos que se le especifique. Desde 0 a 600 con los dos controles añadidos a la cámara.

- Hace las fotos en Foreground (primer plano) y sigue haciéndolas aunque esté la B4XPage en Background. Son fotos sin zoom pero con efectos, si se quiere. Pues el ejemplo original parece que no hace fotos con zoom.

- En B4XMainPage:
La línea
B4X:
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
te obliga a crear una carpeta llamada Shared Files al lado de la del proyecto.

- cam.Stop del evento B4XPage_Background es controlado con el booleano ScheduledMode para hacer fotos programadas o bien manuales. No se apaga la cámara cuando son programadas.

- El servicio PhotoTacker comunica a B4XMainPage el valor True para el B4XSwitch (servicio funcionando) y el valor en segundos para el RoundSlider. Para cuando se cierra del todo la app por error y se vuelve a abrir, para poder detener el servicio.

- Deshabilitado el B4XSwitch y el RoundSlider pasa a cero en el evento btnMode_Click, cuando se utiliza el modo vídeo. Y los vuelve a habilitar en modo foto.

- Las notificaciones del ejemplo no las muestra debido a su baja prioridad en mi Android 11 (notification.IMPORTANCE_LOW), pero si un aviso sonoro en mi Android 6.0.1.

- Puesto opcionalmente el objeto PhoneWakeState en Main para que nunca se apague la pantalla con esta app

- Para ver las fotos tomadas hay que utilizar el ordenador, un cable USB al Móvil y permitir la depuración USB.
Ruta:
B4X:
Este equipo\Nombre del dispositivo\Phone\Android\data\b4a.scheduledphotos\files

- Hay que enchufar el cable USB cada vez que se quieran ver los cambios en esa carpeta, pues ahí no funciona el Actualizar (F5) de Windows. No sé por qué.

Saludos.
 
Last edited:

ricprehn

Member
Hola GeoT,

Muchas gracias por tu gran trabajo y la explicación detallada. He probado el código en dos móviles, en uno con buenos resultados y en otro no:

- Redmi 9 (andorid 11): Funciona perfectamente con la pantalla encendida y apagada. Los segundos seleccionados en el RoundSlider coinciden con la ejecución de las fotos.

- Motorola Edge 20 (android 12): Funciona perfectamente con la pantalla encendida, con la pantalla apagada falla. Lo curioso es que una vez apagada la pantalla, es capaz de realizar una foto, con la segunda es cuando falla dando este error en los logs:
"Error: (CameraAccessException) android.hardware.camera2.CameraAccessException: CAMERA_ERROR (3): The camera device has encountered a serious error"
En el Motorola los segundos seleccionados en el RoundSlider no coinciden con la ejecución de las fotos, las hace más tarde, sin coincidir los tiempos. Este problema lo he solucionado con StartServiceAtExact.

¿Alguna idea de porqué falla en el Motorola? Es curioso que no salte el error en la primera foto con pantalla apagada...

Saludos.
 

ricprehn

Member
¿Podría funcionar metiendo el código de la cámara en un módulo de actividad y lanzarlo desde un servicio tal como sugiere Erel en este post?

 

GeoT

Active Member
Licensed User
Longtime User
Hola ricprehn.
De nada.

Pues ahora mismo no lo sé.
Quizás sea la compatibilidad de Camera2 con cada versión de Android o con cada dispositivo. No sé.
Quizás tenga que ver con el acceso a la cámara o bien la vista previa de la imagen.

Seguiré investigando.

Saludos.
 
Last edited:

GeoT

Active Member
Licensed User
Longtime User
¿Se te cuelga la aplicación o solamente no hace las fotos y te loguea ese error?
 
Last edited:

GeoT

Active Member
Licensed User
Longtime User
Ok. Algo es algo. ¿No?

Sobre lo que me compartes de Erel, lo malo es que parce que cuando la actividad de la aplicación entra en pausa, ya sea una actividad normal o una B4XPage, la cámara se libera (Release) automáticamente, dejando de utilizarla, al menos con las librerías del foro.
Ya sea desde una actividad, o con la ayuda de una clase.

Y no sé aún si me estoy dejando algún otro detalle.

Saludos.
 

TILogistic

Expert
Licensed User
Longtime User
Ha probado este metodo.
B4A y B4I
Leer:
 

GeoT

Active Member
Licensed User
Longtime User
Gracias TILogistic.
Pero parece que con el Intent no se puede evitar que se muestre una pantalla de confirmación con "Ok" y "Reintentar".
No se puede usar el método basado en la intención para tomar una foto sin la confirmación del usuario.
Y no se tiene ningún control sobre la aplicación de la cámara para añadirle o quitarle elementos, como botones...

Fuente: Intent Based Camera - Taking photo with confirm screen

Saludos.
 

ricprehn

Member

Hola Geot y TILogistic,

Exacto. Parece que camera2 es la vía correcta. El código de GeoT funciona bien en algunos móviles, lo que he comprobado que el consumo de la batería aumenta considerablemente mientras la app está corriendo aunque el intervalo sea grande. Estoy probando de inicializar la cámara justo antes de realizar la foto, y apagarla hasta el siguiente intervalo (para reducir el consumo). He tenido poco tiempo para probar... de momento este código de aquí abajo no está funcionando.

B4X:
Sub Start_Camera
     
    cam.Initialize(pnlCamera)
    Log(cam.SupportedHardwareLevel)
    buttons = Array(btnScene, btnAutoExposure, btnEffects, btnFocus, btnMode)
    SetState(False, False, VideoMode)

End Sub

Sub Stop_Camera
    cam.Stop
End Sub
 

ricprehn

Member
Subo aquí código con el que se para la cámara una vez realizada la foto y se vuelve a reactivar en la siguiente foto (para ahorrar batería).
Lo malo es que sólo me está funcionando con la pantalla encendida. Cuando apago la pantalla no es capaz de inicializar la cámara. Si podéis echar un vistazo sería genial. Mil gracias.

( he desactivado botón de inicio y dial de tiempo, se inicializa solo con intervalos de 30 segundos entre foto y foto).
 

Attachments

  • ScheduledPhotos.zip
    20.9 KB · Views: 121

GeoT

Active Member
Licensed User
Longtime User
Hola.
No funciona bien el código que añadiste.
Sí, el problema es ese. Solamente funciona con la pantalla encendida y sin estar visible la pantalla de bloqueo de tu móvil. Cuando apagamos la pantalla no es capaz de inicializar la cámara con el código actual de Camera2.

Quizás sea que al entrar en onPause () se está matando el hilo que está utilizando CameraAPI. Y LegacyCameraDevice_nativeGetSurfaceId: no se pudo recuperar la superficie nativa de la superficie". Surface no tiene una superficie nativa válida.
Leí sobre ello que que "El ImageReader es una variable local en takePicture y no parece que esté almacenada en ninguna parte de la clase principal. Es probable que se recopile la basura inmediatamente o poco después de que se cierre takePicture, por lo que cuando la cámara intenta configurarse, Surface informa que está abandonada.
Una superficie es como una referencia débil y no mantendrá vivo el ImageReader por sí mismo. Guárdelo en la clase principal como lo hace con el dispositivo de cámara."

Añadiendo y modificando ciertas cosas cosas conseguí que con mi Galaxy Grand Prime+ con Android 6.0.1 hiciera la foto aún estando la app no visible, pero con la pantalla encendida.
También consigo forzar que se encienda la pantalla, pero al estar la pantalla de bloqueo, no se muestra la app y no toma la foto.

Seguiré investigando.
 
Last edited:

GeoT

Active Member
Licensed User
Longtime User
Hola ricprehn.

Como dices en el foro Android Questions, con la clase CameraEx2 y la librería Camera2 cuesta reabrir la cámara al cerrarla para evitar que permanezca abierta todo el tiempo, ya que consume mucha batería.

Pero he conseguido liberar la cámara tras entrar en onPause con la clase CameraEx y la librería Camera y volverla a "solicitar" luego para utilizarla. Que supongo que servirá.

Pero sigue necesitando la actividad para hacer las fotos.

Abre la actividad aunque esté la pantalla apagada y bloqueada con el código del post:
B4X:
Sub SetShowWhenLocked
    Dim r As Reflector
    r.Target = r.GetActivity
    r.Target = r.RunMethod("getWindow")
    r.RunMethod2("addFlags", 6815872, "java.lang.int")
End Sub
que en mis dos móviles funciona. No sé en los otros.

Y le hago cerrar después la actividad tras tomar la foto.

Como a partir de Android 10 solo las aplicaciones que tienen el permiso especial de "dibujar sobre aplicaciones" pueden iniciar actividades mientras la aplicación está en segundo plano, lo resuelvo con la clase RequestDrawOverPermission que utiliza el permiso SYSTEM_ALERT_WINDOW.

Adjunto mi ejemplo.

A ver si se puede aplicar a Camera2. Pero es más difícil.

Saludos.
 

Attachments

  • ScheduledCameraEx.zip
    29.1 KB · Views: 141
Last edited:

GeoT

Active Member
Licensed User
Longtime User
En este jemplo, el servicio no llama a hacer la foto diectamente pues se puede haber girado el dispositivo y la cámara aún no puede estar lista por ello.
Sino que llama a inicializar la cámara, que cuando está lista, a través del evento camEx_Ready (Success As Boolean) del objeto camEx en la activity Main, llama a realizar la foto.
Pero solamente llama a realizar la foto si la variable boleana global Take del servicio PhotoTaker es True y la variable scheduledMode de la activity Main es True, por si el usuario reabre la app a mano entre intervalos de toma de fotos y actua por ello de nuevo el evento camEx_Ready (Success As Boolean)
Tras realizar cada foto programada, la variable global Take del servicio PhotoTaker la ponemos en False.
Tras detener el usuario el servicio, la variable scheduledMode de la activity Main la ponemos en False.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…