Italian Servizio in background (data/ora esatta) + notifica

Valentino.b

Member
Ciao a tutti, vorrei implementare una funzione ("servizio"?) che in background
sia quando l'APP è visibile sia quando l'utente la porta in secondo piano, faccia delle azioni
(ad esempio chiamare un servizio che verifichi data/ora esatta) e visualizzi una notifica in
caso di disallineamento.

OK per la notifica
B4X:
Sub Notifica
Dim myNotification As Notification
myNotification.Initialize
myNotification.SetInfo("Titolo notifica", "Testo notifica", myActivity)
myNotification.Notify(int)
End sub
anche se
B4X:
myNotification.Sound=False
non pare avere effetti.


Ma come dovrei gestire/lanciare il servizio di verifica data/ora?
Uso B4A v.9.80
E' preferibile creare un modulo esterno che gestisca questo servizio di verifica? Di quale tipo?

Nella mia Main dovrei invocare
B4X:
StartService(nomeModulo)
ma come gli posso indicare "avviati ogni 30 minuti", ad esempio?
StartServiceAt dovrebbe avviare il servizio ad un orario determinato.

Quale valore sarebbe preferibile settare per la proprietà AutomaticForegroundMode?

Come posso monitorare dalla mia APP lo stato del Servizio B4A creato? (se è in errore, se sta funzionando correttamente, ...)

Infine, per arrestare il servizio (durante l'utilizzo dell'App o durante l'aggiornamento) va usato StopService oppure CancelScheduledService?

Vi ringrazio.
 

Sagenut

Expert
Licensed User
Longtime User
Puoi trovare qualche spunto in questo esempio
Background Location
Questo esempio dovrebbe anche mostrarti come evitare che il tuo servizio venga ucciso dal S.O. che è sempre più aggressivo verso i servizi e le app in background.
 

Valentino.b

Member
Grazie @Sagenut
appurato che i servizi sono "moduli" particolari (contraddistinti dall'icona della saetta), avevo visto questo source code.

Fermo restando che il servizio viene avviato dall'APP (e non in automatico, all'avvio)
B4X:
#StartAtBoot: False

non mi è chiaro
  • come avviare il servizio ad evento e non ad un'orario preciso (StartService o StartServiceAt)?
  • come settare la proprietà AutomaticForegroundMode?
  • come ridare il focus all'applicazione (riportandola in primo piano, se dormiente) cliccando sulla notifica?
  • come monitorare lo stato del servizio (attivo, killed, ...)?
  • come fermare in sicurezza il servizio? E' sufficiente StopService? Ma dall'interno del servizio va in errore.
 

Sagenut

Expert
Licensed User
Longtime User
@Valentino.b ti chiedo scusa ma ultimamente non sono molto attivo.
Non ho usato direttamente quell'esempio quindi al momento non sò risponderti.
Spero che nel frattempo esaminando il codice tu possa aver trovato almeno alcune risposte alle tue domande.
 

udg

Expert
Licensed User
Longtime User
Ciao Valentino,
dalle tue domande direi che tu abbia seguito il consiglio di @Sagenut e studiato il codice proposto.
Per avviare il servizio in base ad un evento interno all'app (es. tasto premuto, condizione verificata..) utilizzi StartService(<nome servizio>); questa istruzione avvia il servizio "a richiesta" in quel momento (più o meno, ricorda che c'è sempre una coda di "messaggi" ovvero di azioni che si forma e man mano viene smaltita, quindi nulla è davvero immediato).
Nell'esempio citato, si usa anche StartServiceAt quale misura di sicurezza, in modo che se Android dovesse decidere di terminare il servizio, questi verrebbe lanciato nuovamente all'orario indicato (sempre più o meno). Potresti calcolare qualcosa tipo orar_attuale + 30 minuti, esattamente come nell'eesmpio..

Per fermare un servizio, utilizzi StopService, ma se hai fatto uso anche di StartServiceAt devi abbinare l'istruzione CancelScheduleService in modo che sia cancellata anche la "prenotazione" di futuro avvioo.

La notifica prevede già l'indicazione dell'activity da attivare quando viene cliccata. Un meccanismo simile lo trovi anche nei widget. Sarà Android a portare in primo piano l'app e portarsi sull'activity indicata. Un punto importante è verificare che non abbia dipendenze da informazioni sparse altrove e che potrebbero non essere disponibili nel momento del riavvio (es. un file chiuso, un percorso non salvato, un DB non inizializzato..)

Per monitorare il servizio, dall'interno dell'app, direi che ti sia sufficiente una variabile globale nel modulo Starter che venga aggiornata dals ervizio in base ad un qualche criterio. Quando l'app è attiva, consulti tale variabile e sai se il servizio sta funzionando regolarmente o meno.
Se invece desideri monitorare il funzionamento in gerale, dovresti pensare ad un watchdog, ovvero un'app separata che testi la regolare esecuzione della prima e provveda a riavvio o alert in caso di problemi.

Parti con un'implementazione semplice e ridotta all'osso. Poi man mano aggiungi funzionalità e verifica se tutto continua a funzionare come atteso.
 

Valentino.b

Member
Grazie @udg

ho avviato il servizio con StartService ed arrestato con StopService. Non dovrebbe servire CancelScheduleService.

Il mio servizio non ha (ovviamente) interfaccia grafica e deve lavorare in background per verificare data/ora esatta.
Affinchè il servizio lavori a prescindere che l'APP sia in primo piano, all'avvio del servizio (Service_Create) come va usata la proprietà AutomaticForegroundMode?

B4X:
Sub Service_Create
    Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_NEVER
....
....    
    Service.StartForeground(1,n)
End Sub
Never? Always? Se ho ben capito:
- con AUTOMATIC_FOREGROUND_WHEN_NEEDED (valore di default) il servizio entrerà in modalità "primo piano" quando necessario (ma chi lo stabilisce?)​
- con AUTOMATIC_FOREGROUND_NEVER non entrerà mai in modalità primo piano e quindi StartForeground è necessario​
- con AUTOMATIC_FOREGROUND_ALWAYS il servizio verrà sempre avviato in modalità primo piano​
ma io non voglio portare il servizio in primo piano bensì l'APP che lancia il servizio, ma solo quando viene cliccata la notifica.

Il servizio, ad evento, visualizza la notifica "data/ora aggiornata". Attualmente se clicco sulla notifica non accade nulla. Forse non devo usare SetInfo?
 
Top