Spanish [SOLUCIONADO] TIMER

Anton Solans Argemí

Active Member
Licensed User
Longtime User
Buenos días,

Estoy utilizando por primera vez el Timer y no se como hacer lo siguiente:

Tengo una app donde pasa por distintas pantallas y en el Main estoy definiendo:

B4X:
Sub Globals
Timer1.Initialize("Timer1", 6000) 
Timer1.Enabled = True
End Sub

Sub Timer1_Tick
Msgbox("Prueba","Timer")
End Sub
[ENDCODE]

Cuando estoy en la primera pantalla me lo hace correctamente y me va saliendo el mensaje cada 6 segundos pero si no estoy en la primera pantalla no me salta el mensaje. Como lo debo hacer?
 

josejad

Expert
Licensed User
Longtime User
Hola:

Cuando estoy en la primera pantalla
No sé a qué te refieres con esto. Supongo que con "pantalla" te refieres a "Activity"?
Si es así, tu código sólo se ejecuta cuando está activa la Activity en la que estás en ese momento. Si quieres que se ejecute en otra, tienes que replicar tu código en esa otra Activity.
O mejor aún, deberías ejecutar ese código desde un servicio, que está siempre activo. Eso sí, tendrías que mostrar un ToastMessageShow, ya que los servicios no permiten mostrar MsgBox

saludos,
 

Anton Solans Argemí

Active Member
Licensed User
Longtime User
También lo había probado lo de replicar el código pero no me funcionó y pensé que no se hacía así.

Lo volveré a probar a ver si encuentro el porque no me funcionó.

Muchas gracias!
 

josejad

Expert
Licensed User
Longtime User
Si pones en el servicio Starter

B4X:
Sub Service_Create
    Timer1.Initialize("Timer1", 6000)
    Timer1.Enabled = True
End Sub

Sub Timer1_Tick
    ToastMessageShow("Prueba", False)
End Sub

Debe funcionarte en cualquier Activity.

Si no te funciona, pon tu código por aquí e intentaremos echarte una mano
 

Anton Solans Argemí

Active Member
Licensed User
Longtime User
He probado de ponerlo en el Servicio starter y me funciona pero tengo que sacar un MsgBox y tal como me has dicho antes con el MsgBox no funciona.

Si lo hago replicando el código en cada modulo deberia poner el siguiente código?

B4X:
Sub Timer1_Tick
Msgbox("Prueba","Timer")
End Sub
[END CODE]

Como la variables Timer1 la tengo de finida en el globals, ya no debería ponerla en ningún sitio más?

[CODE]
Sub Globals
Timer1.Initialize("Timer1", 6000) 
Timer1.Enabled = True
End Sub
[END CODE]

Si lo pongo tal como te digo en el primer módulo me sale el MsgBox pero en el segundo ya no.
 

Descartex

Well-Known Member
Licensed User
Longtime User
He probado de ponerlo en el Servicio starter y me funciona pero tengo que sacar un MsgBox y tal como me has dicho antes con el MsgBox no funciona.
Y si desde el propio servicio llamas a un modulo de codigo que contenga el MsgBox?
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
Y si desde el propio servicio llamas a un modulo de codigo que contenga el MsgBox?

Siguiendo la indicación de Descartex:
B4X:
' Primero pregunto por si la Activity está en pausa o no. 
' Si tienes una aplicación con varias activities, esto te sirve para saber cual es la que está activa y así obrar en consecuencia.
 If Not(IsPaused(ActivityDeseada)) Then
            CallSubDelayed2(ActivityDeseada, "ProcedimientoMsgBox", "Mensaje del MsgBox personalizado por si así lo necesitaras.")
 End If
 

jparraga

Member
Licensed User
Longtime User
Hola @Anton Solans Argemí,
no tienes por que usar un Timer en un servicio, puede hacer que arranque cada 6 segundos con:

B4X:
StartServiceAt("", DateTime.Now + 6 * DateTime.TicksPerMinute, True)

Esto arrancará el servicio cada 6 segundos aproximadamente y podrás pasar un mensaje a la Activity activa, o comprobando si está activa con:

B4X:
If Not(IsPaused(ActivityName)) Then CallSubDelayed(ActivityName,"nombre_funcion")

Si quieres que sea exactamente 6 segundos, deberás utilizar

B4X:
StartServiceAtExact(ServiceName, DateTime.Now + 6 * DateTime.TicksPerMinute, True)

Pero esto gasta bastante más batería.

En los dos casos el tercer parámetro es:
DuringSleep - Si se debe iniciar el Servicio cuando el dispositivo esté durmiendo. Si está configurado en False y el dispositivo está inactivo a la hora especificada, el Servicio se iniciará cuando el dispositivo se encienda.

Cuidado con el CallSubDelayed si la Activity no está activa, por que creo recordar que encola los mensaje y cuando se reactiva los ejecuta después del Resume todos seguidos y no creo que sea lo que quieres hacer, por eso te pongo que compruebes primero si está activa la Activity con IsPaused.

Aquí creo que puedes encontrar un ejemplo que espero que te sea util.
https://www.b4x.com/android/forum/threads/alarm-clock-using-b4a.15328/#post87415

Un saludo.

PD: Está todo explicado mejor en el libro que tienes en mi firma de abajo.
 

Anton Solans Argemí

Active Member
Licensed User
Longtime User
Buenos días !! Primero de todo daros las gracias a todos por las respuestas.

Lo pruebo y si tengo alguna duda os iré preguntando y ya os informo como termina la consulta.

Saludos.
 

figorra

Member
Licensed User
Longtime User
Otra posible solución.....


B4X:
Sub Process_Globals

    Dim Temporizador As Timer

End Sub

Luego en cada pantalla (activity)


B4X:
Sub Activity_Create(FirstTime As Boolean)
   
    Temporizador.Initialize("Tiempo",2000)

End Sub

Y en el evento del temporizador


B4X:
Sub Tiempo_tick

    (TU CODIGO)
    Temporizador.Enabled = False

End Sub

Si usas un módulo de funciones, donde llamas y realizas en cada activity el msgbox, sería sencillo pasarle en que activity estás y así no repetir código.

NOTA: Un módulo de funciones para mi es un modulo de código donde creas funciones que pueden ser llamadas desde cualquier activity
 

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola:

Varias cosas:

si no estoy en la primera pantalla no me salta el mensaje
Cuando sales de un Activity y entras en otro, el ciclo de vida se va a Sub Activity_Pause (UserClosed As Boolean) del Activity donde estas, y luego entra en el
Sub Activity_Create(FirstTime As Boolean) del que has llamado. Asi que al entrar ese Activity en Pause el temporizador se para, mirate el ciclo de vida:
https://www.b4x.com/android/forum/threads/b4a-tutorial-guia-rápida-del-ciclo-de-vida-de-android.38760/


Para que un temporizador no te cree varias instancias cada vez que entras en un Activity, lo debes declarar en Sub Process_Globals que al no ver el código igual lo has hecho bien.
Una forma estandar para que no te cree varias instancias del mismo temporizador seria asi:
B4X:
Sub Process_Globals
dim Timer1 as Timer
' .............
' .............
' .............

Sub Activity_Create(FirstTime As Boolean)
if FirstTime then
  Timer1.Initialize("Timer1", 6000)
  Timer1.Enabled = True ' esto puedes hacerlo desde donde te interese ponerlo en marcha
End if
NOTA: Si no lo pones cuando FirstTime se cumpla, simplemente al girar la pantalla volverá a crearte una nueva instancia del temporizador, y esto hará que entre a los seis segundos de entrar en el Create, mientras las instancias anteriores entraran cuando se cumplan los seis segundos, puede ser un buen quebradero de cabeza dependiendo que hagas en el evento del temporizador.


Como bien te han comentado, si lo tienes que llamar de diferentes módulos te iria bien crearlo en un servicio, pero como te ha comentado jparraga haciendo llamadas StartServiceAt( , el problema es que con esa llamada tan corta de seis segundos vas a consumir muchos recursos.
Mejor (personalmente) que crees uno por Activity y de esa forma cuando salgas de el se parará, y no tendrás que estar gestionado el servicio (marcha/paro y en que modulo está para sacar el MsgBox) desde los diferentes Activity.

Saludos
 
Last edited:
Top