Italian Avviare un servizio da un'altra app

AlpVir

Well-Known Member
Licensed User
Longtime User
Ho creato un semplice servizio (produce 5 beep)
B4X:
Sub Process_Globals
     Dim T   As Timer
     Dim suono    As Beeper
     Dim MaxBeep        As Int
End Sub
Sub Service_Create
    T.Initialize("T",1000)
    suono.Initialize(300, 500)
    T.Enabled=True
End Sub
Sub Service_Start (StartingIntent As Intent)
    T.Enabled=True
End Sub
Sub Service_Destroy
    T.Enabled=False
End Sub
Sub T_tick
    suono.Beep
    MaxBeep=MaxBeep+1
    If MaxBeep=5 Then
        Service_Destroy
    End If
End Sub
che lancio in Activity_Create
B4X:
Sub Activity_Create(FirstTime As Boolean)
    StartService(ServiceR)
End Sub
Tutto OK: sento i 5 beep.
Vorrei però che l'activity NON fosse visualizzata.
Inserisco nel Manifest
B4X:
AddReplacement(android.intent.action.MAIN, unused_action)
ed è ciò che accade ma i 5 beep non si odono più !
Avrò creato o meno un service ? Non ne sono certo.
Indipendentemente da tutto questo lo scopo mio finale è quello di lanciare da un'app ("A") il citato servizio (o un altro) tramite un pulsante che contestualmente chiude l'app "A" e, mentre sento i 5 (o più) beep vorrei esser libero di utilizzare il device come meglio credo, navigare, collegarmi a WhatsApp, ecc. ecc. L'app "A" è definitivamente chiusa !

Nell'elenco delle app, ricavato con :
B4X:
'    Dim pm As PackageManager
'    Dim packages As List
'    packages = pm.GetInstalledPackages
'    For i = 0 To packages.Size - 1
'        Log(packages.Get(i))
'    Next
ho effettivamente riscontrato l'esistenza del mio servizio ("nome.ServiceR"), ma con le istruzioni seguenti (e altre di questo tipo) non sono assolutamente riuscito ad avviarlo.
B4X:
Sub BotAvvia_click
    Dim Intent1 As Intent
    Dim pm As PackageManager
    Intent1 = pm.GetApplicationIntent ("nome.ServiceR")
    StartActivity (Intent1)
    Activity.Finish
End Sub
Come risolvere ?
Grazie per l'attenzione.
 

LucaMs

Expert
Licensed User
Longtime User
Ho una certa fretta per cui ho letto in fretta.

Non si capisce bene se vuoi attivare il servizio tramite un button o meno, dato che il primo esempio lo avviava nella Create della Main.

Se non ti serve che l'utente veda l'interfaccia grafica e quindi il button, puoi semplicemente avviare il servizio dal Service_Start del servizio Starter (oppure addirittura usare questo per i beep).
Puoi anche aggiungere la riga sotto, anche se non l'ho provata né so se potrebbe interferire con il tema dell'intera app; è un suggerimento di Erel per non far comparire il titolo per un attimo, prima dell'avvio del servizio:
B4X:
SetApplicationAttribute(android:theme,"@android:style/Theme.Holo.Light.NoActionBar.Fullscreen")


Se invece vuoi usare il button, dovrebbe essere sufficiente inserire nella routine evento Click:
B4X:
Button1_Click
    StartService(TuoServizio)
    Activity.Finish
End Sub
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Grazie.
Rispiego il tutto.
Vorrei creare un qualcosa (un'app isolata o un'app+un service, più probabilmente la seconda cosa, quindi 2 apk) che inizialmente visualizzi con un messaggio di istruzioni ed un pulsante (BotAvvia).
Premendo il pulsante l'app finisce o comunque non è più visibile e parte (probabilmente) un service che comincia ad emettere (uno ogni secondo) dei beep, indefinitivamente.
In realtà la cosa è un po' più complessa ma serve per rendere l'idea e controllare se il servizio (i beep) è attivo o meno. In realtà il service che ho in mente non deve emettere dei beep ma fare un'altra cosa ben più utile su cui non mi dilungo perchè complicherebbe la comprensione della questione. Ovviamente il limite di 5 beep è del tutto provvisorio.
Avviato il service l'app "A" non c'è più ed io sono libero di agire (con il sottofondo dei beep, sai che piacere !) con il device come meglio credo; ad esempio posso avviare WhatsApp o qualunque altra app e lavorarci insieme. Sempre con i beep (ossia il mio service) in funzione.
Questo è importante:
1) l'essere il service sempre attivo, a partire dalla pressione del mio pulsante BotAvvia;
2) il messaggio di istruzioni scomparso e l'app di partenza "A" assolutamente terminata;
3) la possibilità di integire con il device (dopo la pressione del mio pulsante ed il susseguente avvio del service).
Se esistesse un'istruzione Activity.visible=false avrei probabilmente risolto ogni problema, ma non esiste.

Circa l'incomprensione di quanto da me precedentemente scritto aggiungo che ho creato 2 diversi progetti; credo che ciò sia indispensabile.
"A" con il solo messaggio iniziale e il pulsante BotAvvia; nient'altro.
"R" con in main un Activity_create (e l'istruzione StartService(ServiceR) ) ed il modulo ServiceR il cui intero codice ho riportato nel precedente post.

E' evidente che se potessi realizzare il tutto con un solo progetto (ed un solo apk) sarebbe molto meglio ma credo che ciò non sia possibile, proprio per il punto 3) sopra elencato.
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Quasi risolto. Il mio service era scorretto; avevo registrato il mio codice in un file che avevo chiamato ServiceR.bas mentre invece dovevo registrarlo del file di default Starter.bas.
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Il quasi del mio precedente post era riferito al fatto che ero sì riuscito a creare il service (vedi file allegato) non non a richiamarlo da un'altra app (la "A" già citata).
Ho trovato delle indicazioni ( https://www.b4x.com/android/forum/t...sample-from-another-b4a-app.15340/#post101838 ) ma non riesco ad applicarle al mio caso. In pratica so come scrivere il codice in BotAvvia_click dell'app "A" tale per cui si avvi il service "ripidoservice" che - nota bene - non DEVE avere UI.
Grazie per l'attenzione.
 

Attachments

  • ripidoservice.zip
    9.3 KB · Views: 203

AlpVir

Well-Known Member
Licensed User
Longtime User
No.
In estrema sintesi io da una mia app (che chiamerò "A") voglio lanciare (con un pulsante) un service no UI (che si chiama "ripidoservice"), esterno all'app e da me creato. Non un'altra app, come suggerito nel link da te indicato.
In ogni caso non saprei proprio cosa scrivere, per adattarlo al mio caso, nei parametri scritti in rosso dell'esempio da te indicato.
 

LucaMs

Expert
Licensed User
Longtime User
In estrema sintesi io da una mia app (che chiamerò "A") voglio lanciare (con un pulsante) un service no UI (che si chiama "ripidoservice"), esterno all'app e da me creato.
Non esiste che tu possa lanciare un servizio senza che esso faccia parte di un'app (di un package).
Ma dell'app che lanci userai soltanto il servizio, quindi è come se lanciassi solo un servizio.
Purtroppo non so esattamente quale sia lo scopo finale; magari potresti fare tutto in una singola app, con più servizi, non so.
In ogni caso non saprei proprio cosa scrivere, per adattarlo al mio caso, nei parametri scritti in rosso dell'esempio da te indicato.
La prima riga rossa dev'essere il nome del package dell'app da lanciare.
La seconda è uguale con l'aggiunta della slash "/" e del nome dell'activity (Main, normalmente)
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Non esiste che tu possa lanciare un servizio senza che esso faccia parte di un'app (di un package).
Ti credo sulla parola.
Ma dell'app che lanci userai soltanto il servizio, quindi è come se lanciassi solo un servizio.
Può essere vero, ma bisogna tener conto che l'app che lancio ("R") non deve avere la UI. E' essenziale altrimenti cessa lo scopo di tutto.
Ho letto che bisogna inserire nel manifest
B4X:
AddReplacement(android.intent.action.MAIN, unused_action)
e sembra proprio che ciò sia vero (provare per credere).
Riporto qui sotto il codice dell'app "A" che dovrebbe avviare l'app ("R") o il suo servizio ("ripidoservice"), decidi tu.
Come vedi i tentativi sono molteplici e tutti senza risultato.

B4X:
Sub BotAvvia_click
   '--- non cancellare queste linee che elencano le app installate
'    Dim pm As PackageManager
'    Dim packages As List
'    packages = pm.GetInstalledPackages
'    For i = 0 To packages.Size - 1
'        Log(packages.Get(i))
'    Next

    Dim Intent1 As Intent
    Dim pm As PackageManager
    Intent1 = pm.GetApplicationIntent ("alpvir.ripidoservice")
    StartActivity (Intent1)
    Activity.Finish

'    Dim p As Phone
'    Dim i As Intent
'    i.Initialize("", "")
'    i.SetComponent("r1/.ripidoservice$ripidoservice_BR")
'    p.SendBroadcastIntent(i)

'    Dim in As Intent
'    Dim pm As PackageManager
'    in = pm.GetApplicationIntent("alpvir.ripidoservice")
'    If in.IsInitialized Then
'       in.SetComponent("alpvir.ripidoservice/.Main")
'           StartActivity(in)  
'    End If
End Sub

Se hai un momento prova a creare una semplicissima app "A" con un pulsante che chiamerai BotAvvia e tenta di avviare il servizio "ripidoservice". Io non ci sono riuscito :(.
Grazie anticipatamente.
 

LucaMs

Expert
Licensed User
Longtime User
A me questo funziona:
B4X:
Sub btnRipidoService_Click
    Dim in As Intent
    Dim pm As PackageManager

    in = pm.GetApplicationIntent("alpvir.ripidoservice")
Log("in is initialized: " & in.IsInitialized)
    If in.IsInitialized Then
        in.SetComponent("alpvir.ripidoservice/.main")
        StartActivity(in)  
    End If
  
    ' Se vuoi che termini completamente
    StopService(Starter)
    ExitApplication
  
    ' Se vuoi che "scompaia" ma resti attiva
'    Activity.Finish
End Sub

Il punto è che funziona solo la prima volta, in quanto la seconda volta che avvii l'App A, premi il tasto e "riavvii" il servizio, questo è ancora attivo, quindi o non viene riavviato o MaxBeep è già a 5.

Allego anche i due "progetti"; nota che ho dovuto togliere i due moduli HTTP e la riga nel manifest perché mi davano errore in compilazione e non avevo voglia di indagarne il motivo :)
 

Attachments

  • A.zip
    7.6 KB · Views: 191
  • RipidService.zip
    6.1 KB · Views: 192
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Ah, già, ti ho scritto quale sia il problema ma non la soluzione :D

Beh, in realtà ce ne sono due possibili, dipende da quale sia esattamente il problema (vedi post precedente):

1) fermare il servizio una volta raggiunti "i 5 beep"
B4X:
StopService(Me)
2 azzerare MaxBeep nel Service_Start (questo è da testare)
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Ah (2)... non sono riuscito a fare in modo che l'Activity "del servizio" non dia segnali d'esistenza, né usando il tuo codice nel manifest:
AddReplacement(android.intent.action.MAIN, unused_action)

né usando quello suggerito da Erel:
SetApplicationAttribute(android:theme,"@android:style/Theme.Holo.Light.NoActionBar.Fullscreen")

Nel primo caso compare per un attimo una schermata nera, nel secondo... bianca (per via del Light, suppongo)
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Il tuo
A me questo funziona:
mi ha fatto sperare, ma mi sa tanto che hai dimenticato la condizione "no UI".

Quelli da te suggeriti sono stati anche dei miei tentativi, tutti influttuosi al momento attuale.
E tale risultato non positivo permane, finora.
Premesso che il file tuo Starter.bas di ripidService.zip è vuoto (ma non importa !) non ho capito cosa significa la frase, un po' contorta,
non sono riuscito a fare in modo che l'Activity "del servizio" non dia segnali d'esistenza
La linea nel manifest AddReplacement(android.intent.action.MAIN, unused_action) credo che sia indispensabile.
Senza questa linea il meccanismo funziona ma non viene soddisfatta la condizione "no UI" e quindi .... siamo da capo. Non funziona !
Mi viene quasi da pensare che quanto da me desiderato sia impossibile da realizzare.

P.S.: non so cosa sia il Light da te citato nell'ultima riga.
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
ma mi sa tanto che hai dimenticato la condizione "no UI".
Allora, l'app che non deve avere UI è quella che hai chiamato RipidService, giusto? Ovvero quella che l'App A deve lanciare, premendo il tasto (e poi A deve "sparire").

Questo è quanto fanno i due progetti allegati al mio post precedente.
L'unica modifica che devi fare è a ripidservice: anziché richiamare Service_Destroy, come hai fatto, devi mettere StoptService(Me).

Dopodiché compili ripidservice, compili A, lanci quest'ultimo, premi il tasto e vedrai i log.


P.S.: non so cosa sia il Light da te citato nell'ultima riga.
Volevo dire che l'app "lanciante" mostra comunque per un attimo l'Activity, sia mettendo nel Manifest il codice che hai riportato tu, sia quello di Erel riportato da me; quest'ultimo contiene Light come tema e quindi, anziché nero, il lampeggìo è bianco.
 
Last edited:

AlpVir

Well-Known Member
Licensed User
Longtime User
Allora, l'app che non deve avere UI è quella che hai chiamato RipidService, giusto?
Esatto.
Relativamente ai 2 progetti faccio presente che il file Starter.bas di ripidoservice era completamente vuoto per cui ho utilizzato pari pari quello che avevo allegato nel post #5.
Ho seguito strettamente le tue indicazioni (non sono proprio digiuno di B4A) ma ... niente.
In particolare a seguito della compilazione di ripidoservice il tasto "Apri" è disabilitato (com'è giusto che sia visto che si tratta di un progetto "non UI")
Nel file manifest ho inserito solo AddReplacement(android.intent.action.MAIN, unused_action) ed ho eliminato gli altri 2 files Http .... (come mi hai detto)
Poi ho lavorato sul progetto "A" e qui ho riscontrato che forse l'intent dovrebbe essere inizializzato. L'ho fatto.
La faccio breve ma il progetto non funziona su nessuno dei 2 device su cui l'ho sperimentato. Anzi, la seconda volta che lo avvio nemmeno compare il pulsante btnRipidoService. Per ripristinare la situazione sono costretto a terminare manualmente il servizio. L'effetto "seconda volta" l'avevo già notato nelle mie numerose prove.
Insomma .... nebbia sulla valle.
Riallego i 2 progetti con le mie modifiche (su tuo suggerimento)
 

Attachments

  • A.zip
    7.8 KB · Views: 195
  • RipidoService.zip
    6.7 KB · Views: 188

LucaMs

Expert
Licensed User
Longtime User
Il RipidoService va bene (a parte che, come detto, non so come si possa evitare lo "sfarfallìo", ovvero la visualizzazione dell'Activity per un attimo).

Nel progetto A che hai allegato:
B4X:
Sub btnRipidoService_Click
    Dim in As Intent
    Dim pm As PackageManager

    in = pm.GetApplicationIntent("alpvir.ripidoservice")
Log("in is initialized: " & in.IsInitialized)
    If in.IsInitialized =False Then
        Log ("in.SetComponent('alpvir.ripidoservice/.main'")
        in.Initialize("","")                        ' LINEA AGGIUNTA, SEMBRA INDISPENSABILE
        in.SetComponent("alpvir.ripidoservice/.main")
        Log ("StartActivity(in)")
        StartActivity(in)  
    End If
  
    ' Se vuoi che termini completamente
    'StopService(Starter)         ' Starter.bas del progetto A è vuoto !!!!!!!
    'ExitApplication
  
    ' Se vuoi che "scompaia" ma resti attiva
    Activity.Finish
End Sub

l'inizializzazione dell'Intent non va eseguita come hai fatto, deve risultare dal comando pm.GetApp...
Infatti, poi si controlla se sia stato effettivamente inizializzato; se non lo è, significa che non è stata trovata l'applicazione "alpvir.ripidoservice" e infatti questo accade perché non hai scritto il nome dell'app (il package name) nella Build Configuration, nella quale di default c'è b4a.example.
Quindi devi sostituire quel b4a.example con alpvir.ripidoservice e la Sub btnRipidoService_Click dev'essere come nel mio post #10 e come è nel progetto allegato a quel post.
 
Last edited:

AlpVir

Well-Known Member
Licensed User
Longtime User
Ti ringrazio per tutto quanto hai fatto finora ma non ci siamo proprio. Sicuramente la cosa è di assai difficile realizzazione, se pure è tecnicamente possibile.
Non credi che non abbia provato ad inserire (e a non inserire) l'istruzione in.Initialize("","") ?
Non credi che abbia verificato (puoi farlo tu stesso) che in Build Configurations sia indicato il corretto package alpvir.ripidoservice (vedi immagine allegata) ?
Ho provato ora ora su un tablet con identico negativo risultato.
Dapprima ho compilato, in modalità release, il progetto ripidoservice del post #15
Poi ho compilato, in modalità debug, il progetto "A" del post #15 (dopo aver modificato lievemente il codice secondo quando riportato nel post #10).
Colmo delle prove ho anche provato a mettere in BuildConfigurazione del progetto "A" alpvir.ripidoservice (anche se sapevo che era inutile)
Per la terza volta di informo che il file Starter.bas del tuo ripidoservice.zip è completamente vuoto ! Non so proprio cosa tu abbia potuto collaudare con successo.
Se qualcun'altro volesse dire la sua sarebbe cosa assai gradita.
 

Attachments

  • Build.png
    Build.png
    15.1 KB · Views: 188

LucaMs

Expert
Licensed User
Longtime User
Non credi che non abbia provato ad inserire (e a non inserire) l'istruzione in.Initialize("","") ?
Come HO CERCATO DI SPIEGARE quella istruzione non devi metterla, per il semplice motivo che l'oggetto Intent viene restituito dall'istruzione:
B4X:
 in = pm.GetApplicationIntent("alpvir.ripidoservice")
Dopo questa istruzione viene verificato che l'Intent sia stato effettivamente restituito, ovvero che l'app esista, altrimenti non si fà niente.


Non credi che abbia verificato (puoi farlo tu stesso) che in Build Configurations sia indicato il corretto package alpvir.ripidoservice (vedi immagine allegata) ?
Ti sarai confuso, perché nel progetto A che hai allegato è impostato b4a.example, controlla tu stesso.


Per la terza volta di informo che il file Starter.bas del tuo ripidoservice.zip è completamente vuoto !
Spesso mi basta una volta, grazie. Ho preferito non correggere quello (non ho verificato ma mi fido e può accadere perfino che io faccia un errore) e rispondere ai tuoi post successivi.


Infine, "testo" di nuovo due progetti, li allego e poi lascio che da oggi in poi siano altri a risponderti (se loro avranno voglia di ricevere risposte di quel tono), spendendo meglio il mio tempo.


"Testato"; probabilmente la cosa continuava a funzionare solo al primo avvio in quanto non era sufficiente fermare il servizio, bisognava aggiungere un ExitApplication.
Apparentemente funzionava, comunque. I due progetti che allego a me funzionano sicuramente.


THE END
 

Attachments

  • A.zip
    7.6 KB · Views: 176
  • RipidService.zip
    6.7 KB · Views: 183

valentino s

Active Member
Licensed User
Longtime User
Ascolta, non ne so quasi nulla di quello di cui parlate, quindi ho una percentuale del 99% di sbagliarmi :)

Non testare il servizio con i 5 beep. Se l'app che contiene il servizio non ha impostazioni particolari, quando va in backgroud l'audio di default "si spegne".

Per fare test salva un file e vedi se il file viene creato.

Per sentire i beep devi lavorare un po' sui manifest. Io l'ho fatto per poter sentire l'audio anche in background per la mia radiotape.com sia ios che android c'e' lo stesso problema, se non ricordo male.
 

LucaMs

Expert
Licensed User
Longtime User
Ah, ecco l'incomprensione.

Il beep è solo un test, non è lo scopo finale del progetto, e, dato che io ho sempre il mio dispositivo col volume a zero, controllavo solamente che le 5 chiamate funzionassero; vedevo i 5 log e quindi per me l'app funziona.

P.S. come non detto; nell'evento Tick non viene "suonato" il beep ma, appunto, solo visualizzato il log ed a me funzionava, ma solo la prima volta, in quanto, come detto, non era sufficiente fermare il servizio, era necessario chiudere l'app (servizio) con ExitApplication.
 
Last edited:
Top