Spanish [B4A] [Tutorial] Módulos de Servicio

vbmundo

Well-Known Member
Licensed User
@vbmundo
El servicio tendrías que sincronizar los datos a un bd sqlite en el teléfono de esa manera puedes utilizar en cualquier activity los datos, el servicio igual puede correr cada cierto tiempo aunque la aplicación este cerrada.
Perfecto, muchas gracias !!
 

bgsoft

Well-Known Member
Licensed User
Hola Pablo

Queria preguntarte si las variables que estan declaradas en un Servicio pueden consultarse desde un Activity
Si declaras una variable en Sub Process_Globals , podras consultarla desde cualquier sitio ya sea que el Sub Process_Globals esté en un servicio, modulo de clase o activity

Saludos
 

vbmundo

Well-Known Member
Licensed User
Amigos,

Estoy probando el nuevo B4A 6.0...

No se si es la nueva versión o siempre funcionó así..

Pero no logro que un servicio este listo cuando arranca la aplicación... por mas StartService que yo corra. siempre ejecuta el Activity_Resume antes..

No logro arrancar la aplicación ejecutando consultas a la Base de Datos, porque en el Servicio esta todo.. la conexión y todo... y cuando arranca .. el servicio aun no esta disponible.

Como puedo hacer para que un Service se cargue antes ?

Gracias
 

rscheel

Well-Known Member
Licensed User
Amigos,

Estoy probando el nuevo B4A 6.0...

No se si es la nueva versión o siempre funcionó así..

Pero no logro que un servicio este listo cuando arranca la aplicación... por mas StartService que yo corra. siempre ejecuta el Activity_Resume antes..

No logro arrancar la aplicación ejecutando consultas a la Base de Datos, porque en el Servicio esta todo.. la conexión y todo... y cuando arranca .. el servicio aun no esta disponible.

Como puedo hacer para que un Service se cargue antes ?

Gracias

En tu activity main coloca lo siguiente

B4X:
Sub Activity_Create(FirstTime As Boolean)
      If FirstTime Then
        
        StartServiceAt("ElNombreDelServicio", DateTime.Now + 5 * DateTime.TicksPerSecond, True) 'inicia 5 segundos después de que se ejecuta la aplicación.
        StopService("Starter") 'Detengo el servicio Starter ya que causa problemas al usarlo, por eso es mejor crear un nuevo servicio.
      
    End If
End Sub
 

vbmundo

Well-Known Member
Licensed User
En tu activity main coloca lo siguiente

B4X:
Sub Activity_Create(FirstTime As Boolean)
      If FirstTime Then
      
        StartServiceAt("ElNombreDelServicio", DateTime.Now + 5 * DateTime.TicksPerSecond, True) 'inicia 5 segundos después de que se ejecuta la aplicación.
        StopService("Starter") 'Detengo el servicio Starter ya que causa problemas al usarlo, por eso es mejor crear un nuevo servicio.
    
    End If
End Sub
Muchisimas Gracias amigo !!!

Lo he puesto para que se active a 1 segundo..

Existe una forma de preguntar si un servicio se encuentra ya iniciado o no ?

Gracias
 
Last edited:

vbmundo

Well-Known Member
Licensed User
Claro,

Pero te preguntaba, como se puede (por código) para saber si un Servicio pudo iniciarse o no aun...

Setear que un servicio arranque luego de 5 segundos, puede hacer que cuando tu cheques por código ciertas cosas, aun no hayan pasado esos 5 segundos...

En cuestiones de tiempo de ejecución... 5 segundos es un año...

Por eso puedo setear el StartServiceAt en 1 segundo, y meter un loop hasta que detecte que el servicio está iniciado.

Pero como puedo chequear si un servicio ya esta activo ?
 

bgsoft

Well-Known Member
Licensed User
Hola Pablo:

"oficialmente" puedes emplear esto:

B4X:
If IsPaused(NombreDelServicio) Then
Pero te recomiendo que pongas una variable global a True en Sub Service_Start (StartingIntent As Intent) , y la pongas a false en Sub Service_Destroy , haz la primera prueba y veras por que te digo lo de la variable global :D

Saludos
 

vbmundo

Well-Known Member
Licensed User
Hola Pablo:

"oficialmente" puedes emplear esto:

B4X:
If IsPaused(NombreDelServicio) Then
Pero te recomiendo que pongas una variable global a True en Sub Service_Start (StartingIntent As Intent) , y la pongas a false en Sub Service_Destroy , haz la primera prueba y veras por que te digo lo de la variable global :D

Saludos
Si, lo he hecho así. con una variable global, pero ya te digo que no hay forma de ejecutar el Servicio antes del Activity... por mas que le pongas 1 segundo.. siempre ejecuta el Activity_Resume antes...

Entonces tuve que poner los SUBs como Public en el Activity y hacer a la inversa...desde el Service correr las rutinas del Main.

Saludos
 

rscheel

Well-Known Member
Licensed User
Si, lo he hecho así. con una variable global, pero ya te digo que no hay forma de ejecutar el Servicio antes del Activity... por mas que le pongas 1 segundo.. siempre ejecuta el Activity_Resume antes...

Entonces tuve que poner los SUBs como Public en el Activity y hacer a la inversa...desde el Service correr las rutinas del Main.

Saludos
El código que te compartí mas arriba lo que hace es arrancar el servicio después que inicia el activity no antes si quieres que se ejecute el servicio junto con el activity debes utilizar

B4X:
Sub Activity_Create(FirstTime As Boolean)
    StartService("SQLService")
End Sub
Pero cada ves que se ejecute el activity iniciara el servicio, lo malo de esto es que la aplicación se vuelve pesada al inicio ya que estas ejecutando el activity y el servicio a la ves si quires ejecutar una consulta a base de datos lo mejor que puedes hacer es tener un Sub que se llame por ejemplo ConsultaBD y lo llames en el

B4X:
If FirstTime Then
    ConsultaBD
End If
Por ejemplo yo hago esto

B4X:
    If FirstTime Then
        AgregaCampoTabla 'Llamo al Sub
        EliminaFotos 'Llamo al Sub
        StartServiceAt("SincronizaDatos", DateTime.Now + 5 * DateTime.TicksPerSecond, True)
        StopService("Starter")
      If isConnected Then 'Compruebo la conexión a internet.
               User_PHP 'Usuario en una BD Remota, Si el usuario es valido La app continua, si no se cierra.
          Else
            ToastMessageShow("No tienen conexión a internet", False)
            UserLocal 'Si no hay conexión llamo al Sub y Si hay un usuario ya guardado en la bd sqlite sigo ejecutando la aplicación si no se cierra.
          End If
    End If
 
Last edited:

vbmundo

Well-Known Member
Licensed User
Amigo, yo he hecho eso... pero no funciona..

Depuro con F8 y por mas que he dado StartService("MySQL") y hasta que no termina la ultima instrucción de Activity_Create y Activity_Resume no carga el Servicio.

Entonces una vez que lo carga, ya no hay instrucciones que ejecutar.
 

bgsoft

Well-Known Member
Licensed User
Hola Pablo:

Cuando te dije que miraras el comportamiento de una APP con Starter no era para hacerte perder el tiempo, y ademas te dije que ahi verias por que te pasaba y cual seria la solución.
Como veo que os estais liando en crear codigos sin tener en cuenta el ciclo con Starter, he creado un programa vacio, con starter, un modulo de servicio (ModuloDeServicio) que dentro tiene un sub (Leer) que lo unico que hace es escribir un log para simplemente ver tiempos y secuencia.

Esta es la secuencia con vuestra propuesta:

Estoy en Process_Globals Main
Inicio el Tiempo en milisegundos
Estoy en Process_Globals Starter
Tiempo transcurrido 1
Estoy en Process_Globals ModuloDeServicio
** Service (starter) Create **
Tiempo transcurrido 2
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Main llama al servicio con StartServiceAt
Tiempo transcurrido 155
** Activity (main) Resume **
Tiempo transcurrido 165
** Service (modulodeservicio) Create **
Tiempo transcurrido 5168
** Service (modulodeservicio) Start **
Tiempo transcurrido 5170
Estoy en Sub Service_Start ModuloDeServicio y mando a Sub Leer
Estoy en Sub Leer de ModuloDeServicio

Tiempo transcurrido 5172

Creo que se ve claramente por que no hace lo que "esperas", a esto podriamos ganarle tiempo, si ese StartServiceAt en vez de llamarlo a 5 segundos lo llamas a 1 milisegundo, esta seria la secuencia:

** Activity (main) Pause, UserClosed = true **
Estoy en Process_Globals Main
Inicio el Tiempo en milisegundos
Estoy en Process_Globals Starter
Tiempo transcurrido 1
Estoy en Process_Globals ModuloDeServicio
** Service (starter) Create **
Tiempo transcurrido 2
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Main llama al servicio con StartServiceAt
Tiempo transcurrido 115
** Activity (main) Resume **
Tiempo transcurrido 117
** Service (modulodeservicio) Create **
Tiempo transcurrido 1143
** Service (modulodeservicio) Start **
Tiempo transcurrido 1144
Estoy en Sub Service_Start ModuloDeServicio y mando a Sub Leer
Estoy en Sub Leer de ModuloDeServicio

Tiempo transcurrido 1146

Hemos ganado mas de 5 segundos (los tiempos estan en milisegundos)
Pero digo yo, para que decirle que ejecute el servicio a un tiempo, si lo que quieres es que se ejecute "ya", entonces cambiamos el StartServiceAt por StartService y esta es la secuencia:

Estoy en Process_Globals Main
Inicio el Tiempo en milisegundos
Estoy en Process_Globals Starter
Tiempo transcurrido 1
Estoy en Process_Globals ModuloDeServicio
** Service (starter) Create **
Tiempo transcurrido 2
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Main llama al servicio con StartServiceAt
Tiempo transcurrido 190
** Activity (main) Resume **
Tiempo transcurrido 211
** Service (modulodeservicio) Create **
Tiempo transcurrido 212
** Service (modulodeservicio) Start **
Tiempo transcurrido 213
Estoy en Sub Service_Start ModuloDeServicio y mando a Sub Leer
Estoy en Sub Leer de ModuloDeServicio
Tiempo transcurrido 213

Le hemos ganado casi un segundo, pero tu me diras, mi problema sigue siendo el mismo, se ejecuta antes el Activity que el Sub del servicio, y ahi es donde entra lo que te dije de leete esto y ahi veras por que te pasa y la solución.
Por que te pasa ya lo hemos visto, que la secuencia es esta y por muchos inventos que hagamos no va de dejar de ser esa:

Main.Process_Globals
Starter.Process_Globals
Otros Activity.Process_Globals
Otros ModulodeCódigo.Process_Globals
Starter.Service_Create
Starter.Service:Start
Main.Globals
Main.Activity_Create
Main.Activity_Resume

Asi que está claro que tenemos que hacer, lo ideal es simplemente llamar a nuestro SUB Leer desde Starter, pero poniendo el Sub Leer en Starter, ya que este ademas de módulo de arranque es un servicio que podremos llamarlo como cualquier otro, crees que Erel iba a hacer un arranque que sirviera para "molestar"? está claro que no, pero tenemos primero que leer su funcionamiento para asi saber como emplearlo.

Si no quieres emplear Starter para hacer tus llamadas, pues llama al modulo de servicio con un StartService desde Sub Service_Create y en el Sub Service_Start (StartingIntent As Intent) del modulo de servicio llama a tu sub de leer ,esta es la secuencia:


Estoy en Process_Globals Main
Inicio el Tiempo en milisegundos
Estoy en Process_Globals Starter
Tiempo transcurrido 0
Estoy en Process_Globals ModuloDeServicio
** Service (starter) Create **
Tiempo transcurrido 2
Starter llama al servicio con StartServiceA
** Service (starter) Start **
** Service (modulodeservicio) Create **
Tiempo transcurrido 73
** Service (modulodeservicio) Start **
Tiempo transcurrido 73
Estoy en Sub Service_Start ModuloDeServicio y mando a Sub Leer
Estoy en Sub Leer de ModuloDeServicio

Tiempo transcurrido 74
** Activity (main) Create, isFirst = true **
Tiempo transcurrido 115
** Activity (main) Resume **
Tiempo transcurrido 115

Perdon por todo este rollo :D, pero era la forma de demostrar como se puede hacer y por que.
Aun asi, hay que tener en cuenta que hace el main, y que hace tu modulo, por que puede que cambie algo en el comportamiento global. Yo, como te he dicho simplemente he creado un proyecto vacio que llama a esos modulos y escribe Logs para ver la secuencia. Lo ideal es lo que dice Erel, si necesitas reiniciar cosas hazlo desde el Starter que para eso ha sido creado.

Saludos
 

vbmundo

Well-Known Member
Licensed User
Jesus,

Gracias por el tiempo que te has tomado en esto..

Pero entiende que previamente a tu explicación... tengo esta otra

StopService("Starter") 'Detengo el servicio Starter ya que causa problemas al usarlo, por eso es mejor crear un nuevo servicio.
Y no es el único que he leido que expresa que el Service STARTER da muchos problemas.. lo he leido en este foro en Español y en el de Ingles.

Es por eso que he optado por destruirlo al iniciar el APP.

Que hago entonces ? sigo tus consejos o de los que dicen que el Starter es basura.

Saludos y mil gracias.. sinceramente.
 

bgsoft

Well-Known Member
Licensed User
Hola Pablo:

Yo mis comentarios normalmente los hago basado en mi experiencia, yo estoy empleando Starter para inicializar cosas, e incluso para provocar eventos de la libreria Phone y por ahora no me dió ningún problema. Si tu tienes un problema concreto con starter plantealo en el foro y ya intentaremos dar con la solución o iremos directamente a Erel a consultarselo.

Creo que tu ultimo problema que has planteado de cargar un servicio antes que entre el Main Create o Resume ya te he dado un ejemplo de como resolverlo.

Por otro lado te vuelvo a insistir en lo mismo que te dije mas arriba, si verdaderamente Starter te da problemas, no lo destruyas, simplemente eliminalo del proyecto y asi dejará de darte problemas.

Saludos
 

rscheel

Well-Known Member
Licensed User
Bueno estimados, lo que dice Jesús es muy cierto, y les tengo que decir que los problemas los comencé a tener con el servicio starter con android 6.0, por eso estuve probando al crear un nuevo servicio y de esta forma la app funcionaba perfectamente, nunca fui mas aya al averiguar que pasaba con el servicio starte, al mismo tiempo recuerdo que me apareció el problema de las rutas de archivos con android 6.0 lo cual se soluciona colocando como máxima sdk la 22, todo esto es otro tema, y como dice Jesús es mejor que crees una pregunta en el foro y poder solucionarlo entre todos.

Saludos.
 

bgsoft

Well-Known Member
Licensed User
Hola

Como dice rscheel, los problemas los tuvo con Android 6, y creo que el servicio Starter los problemas que estan surgiendo vienen por ahi, ya hace unos meses puse un post informativo sobre Android 6 y doevents (https://www.b4x.com/android/forum/threads/informaciÓn-sobre-doevents-y-android-6.65847/) y era con Android 6, con ninguna otra versión me pasaba. Yo me reitero en lo que dije y lo que tambien ha echo rscheel, si te da problemas, lo quitas y punto, y tambien como se dice aqui, "si funciona... no lo toques" :D

Saludos
 

vbmundo

Well-Known Member
Licensed User
Hola Pablo:

Yo mis comentarios normalmente los hago basado en mi experiencia, yo estoy empleando Starter para inicializar cosas, e incluso para provocar eventos de la libreria Phone y por ahora no me dió ningún problema. Si tu tienes un problema concreto con starter plantealo en el foro y ya intentaremos dar con la solución o iremos directamente a Erel a consultarselo.

Creo que tu ultimo problema que has planteado de cargar un servicio antes que entre el Main Create o Resume ya te he dado un ejemplo de como resolverlo.

Por otro lado te vuelvo a insistir en lo mismo que te dije mas arriba, si verdaderamente Starter te da problemas, no lo destruyas, simplemente eliminalo del proyecto y asi dejará de darte problemas.

Saludos
Yo te comprendo y así lo haré.

También comprende mi situación.. estoy terminando mi primera App y me apoyo mucho en el foro para evacuar las dudas, por la cual, si leo mas de 1 opinión acerca de que el Servicio STARTER da problemas... es lógico que me de miedo usarlo.

Pero haré lo que tu comentas, y si llego a tener problemas lo volcaré en el foro.

Mil Gracias
 

bgsoft

Well-Known Member
Licensed User
Hola Pablo

Es logico que te surjan dudas y tambien que cuando veas comentarios de cosas que fallan te pongas en guardia, pero veras, yo como tu (pero yo con mas edad :rolleyes:) llevo programando cuando mi primer microprocesador el bus de datos era de 2 bits y se programaba en binario (codigo máquina) a pelo con pulsadores e interruptores (siii, ha llovido mucho de eso), y no te hablo de las tarjetas perforadas por que eso no era programar :D, luego ya vino hexadecimal, ensamblador, y luego los lenjuages de alto nivel secuenciales y los de objetos dirigidos por eventos, he escrito código en muchos y en diferentes SO incluidos los de PLC o Autómatas Programables en el mundo industrial, pero sinceramente Android se lleva la palma, me he quejado muchos años de Microsoft, pero Android y dado que va dirigido a un mercado que cada dia está evolucionando es muy dificil a veces encontrar por que no va, por que falla algo que nunca falló, etc. Pero lo que al principio fue como tu un desespero de no entender las cosas que en otros lenguajes funcionaban, hoy es un reto que me vuelve a dar vida cada vez que empiezo un nuevo proyecto, y eso para mi es mucho.
Pienso que la mayoria que nos dedicamos a esto es por que nos gusta y apasiona, y por eso nos desesperamos cuando no encontramos respuestas, pero como te he dicho, quizas sea eso lo bueno de esto, y por otro lado poder compartir tus experiencias con gente que está a miles de kilometros y que nos une este foro. A veces hay que dejar la tecla un rato y ver esas pequeñas cosas que compartimos todos y que no le damos importancia.

Saludos
 
Top