Italian Effetto brutto alla chiusura di un'app

Sabotto

Active Member
Licensed User
Quando chiudo la mia app con il click su "Uscita" si crea questo effetto come se il layout "esce e rientra" prima di sparire completamente
Il codice che uso per terminare è questo e l'istruzione che genera tale effetto è quella evidenziata.
Io vorrei che rimanesse il layout fino alla fine del codice e poi chiudersi.

Suggerimenti?
piccolo spezzone app .gif


B4X:
Private Sub btnExit_Click

    Log1 ("Uscita")
    btnStart.Enabled=False
    btnExit.Enabled=False
    
    GL.bVPNstarted=False
    
    Wait For (GL.oConn.StopSophosClient) complete ' questa genera l'effetto sgradevole
    ' Gl.oConn è un'istanza di una classe dichiarata in un modulo GL dove ho le variabili globali
    ToastMessageShow("VPN disconnessa",False)
     B4XPages.ClosePage(Me)
            
End Sub

Sub StopSophosClient As ResumableSub
    Dim i As Intent
    i.Initialize(i.ACTION_MAIN, "")
    i.SetComponent("de.blinkt.openvpn/.api.DisconnectVPN")
    i.PutExtra("de.blinkt.openvpn.shortcutProfileName", "VPN_Telecontrollo")
    StartActivity(i)
    ToastMessageShow("Disconnessione VPN in corso...",False)
    Sleep(2000)
End Sub
 

LucaMs

Expert
Licensed User
Longtime User
A parte che se metti Sleep o Wait For all'interno di una routine, questa diventa una Resumable e quindi deve restituire un valore...
al suo interno avvii di nuovo l'Activity Main, usando quell'Intent, quindi è normale che faccia così.
Hai qualcosa nella B4XPage_Appear?
 

Sabotto

Active Member
Licensed User
A parte che se metti Sleep o Wait For all'interno di una routine, questa diventa una Resumable e quindi deve restituire un valore...
A me serve per far passare quei due secoindi prima di ritornare al chiamante. Prima la chiamavo cosi
B4X:
Wait For (GL.oConn.StopSophosClient) complete (result as Boolean)
'poi ho visto che se non serve il valore di ritorno posso chiamarla anche senza
Wait For (GL.oConn.StopSophosClient) complete
Hai qualcosa nella B4XPage_Appear?
La routine con l'Intent è un metodo di una classe. Nella Appear ho solo questo
B4X:
Sub B4xPage_Appear '
    
    GL.bPrimaVolta=True ' in modo che quando vado a pReport avvia anche il test
    btnStart.Enabled=True
    
End Sub
al suo interno avvii di nuovo l'Activity Main, usando quell'Intent, quindi è normale che faccia così.
E che dovrei fare per evitare?
 

LucaMs

Expert
Licensed User
Longtime User
Guardando meglio, col Wait For non stai attendendo il completamento della routine StopSophosClient scritta là sotto, ma evidentemente una copia che si trova nell'oggetto
GL.oConn.

Dato che quella routine è una Resumable, l'oggetto che la contiene non è da inserire in un modulo di codice, visto che questi non possono gestire eventi.
Quindi oConn va dichiarato, inizializzato e usato altrove, in un'altra B4XPage o nella B4XMainPage.

Perché poi serva un Intent non ne ho idea, visto che non conosco quella classe.


P.S. Mi era venuto un dubbio. E' vero che i moduli di codice non possono gestire eventi (in B4J sì) ma se hanno un oggetto pubblico il quale "esponga eventi"? E in effetti ho verificato, questo è possibile.

Confermo, però quanto scritto sopra; scrivendo, come hai fatto:
B4X:
Private Sub btnExit_Click

    Log1 ("Uscita")
    btnStart.Enabled=False
    btnExit.Enabled=False
   
    GL.bVPNstarted=False
   
    Wait For (GL.oConn.StopSophosClient) complete ' questa genera l'effetto sgradevole
    ' Gl.oConn è un'istanza di una classe dichiarata in un modulo GL dove ho le variabili globali
    ToastMessageShow("VPN disconnessa",False)
     B4XPages.ClosePage(Me)
           
End Sub

Sub StopSophosClient As ResumableSub
    Dim i As Intent
    i.Initialize(i.ACTION_MAIN, "")
    i.SetComponent("de.blinkt.openvpn/.api.DisconnectVPN")
    i.PutExtra("de.blinkt.openvpn.shortcutProfileName", "VPN_Telecontrollo")
    StartActivity(i)
    ToastMessageShow("Disconnessione VPN in corso...",False)
    Sleep(2000)
End Sub
la routine StopSophosClient scritta qui non viene eseguita, viene eseguita quella nell'oggetto oConn dichiarato nel modulo di codice Gl, quindi è in quella che dovresti mettere lo Sleep, è quella che lancia l'Intent e per attendere quei 2 secondi dovresti chiamarla con il Complete(NomeVariabile As TipoVariabile restituito dalla StopSophosClient). E' chiaro che l'Intent partirebbe subito, visto che lo Sleep lo esegui dopo.
 
Last edited:

Sabotto

Active Member
Licensed User
La routine "StoSophosClient" si trova nella classe con la quale dichiaro l'oggetto oConn, che siccome mi serve anche in altre pagine, ho dichiarato Public nel modulo GL.
Nel mostrare il codice l'ho scritta di seguito traendoti in inganno prche sembra che faccia parte della stessa pagina, mentre in realtà è nel modulo di classe clsConnessione.
In GL, quindi, ci sono solo alcune Dim e nessuna routine.
Piuttosto ho omesso di dire che durante l'uso del programma viene aperta un altra B4xPage dove mostro i risultati del test, ed è quella che provoca il "problema" Ho ifatto una prova a non farla visualizzare e quando esco dall'app l'effetto non si manifesta piu.
Ho provato ad inserito l'istruzione per chiudere tale pagina ma l'effetto rimane
Faccio un breve riepilogo delle parti interessate

B4X:
'******** In modulo GL **************
Sub Process_Globals
    Public oConn As clsConnessione
    Public bPrimaVolta As Boolean = True ' serve per evitare che ad ogni Appear viene rilanciato il test
    ''... e altre Dim
End Sub

'******** In B4XMainPage **************
Private Sub btnExit_Click

   B4XPages.Closepage(pReport) ' inserita ora ma l'effetto rimane
    btnStart.Enabled=False
    btnExit.Enabled=False
    GL.bVPNstarted=False
   Wait For (GL.oConn.StopSophosClient) complete ' questa genera l'effetto sgradevole
    ToastMessageShow("VPN disconnessa",False)
    B4XPages.ClosePage(Me)
          
End Sub

Private Sub btnStart_Click
  
    btnStart.Enabled=False
    If Not (GL.bVPNstarted) Then
        lblAttendere.Visible=True
        B4XLoadingIndicator1.Show
        Wait For (GL.oConn.StartSophosClient) complete
        ToastMessageShow("VPN connessa",False)
        GL.bVPNstarted=True
        lblAttendere.Visible=False
        B4XLoadingIndicator1.Hide
    End If
    B4XPages.ShowPage("idPageReport") ' questa è la pagina che alla chiusura dà "fastidio"....
      
End Sub


'******** In clsConnessione **************
Sub StopSophosClient As ResumableSub

    Dim i As Intent
    i.Initialize(i.ACTION_MAIN, "")
    i.SetComponent("de.blinkt.openvpn/.api.DisconnectVPN")
    i.PutExtra("de.blinkt.openvpn.shortcutProfileName", "VPN_Telecontrollo")
    StartActivity(i)
    ToastMessageShow("Disconnessione VPN in corso...",False)
    Sleep(2000)

End Sub
 

LucaMs

Expert
Licensed User
Longtime User
Piuttosto ho omesso di dire che durante l'uso del programma viene aperta un altra B4xPage dove mostro i risultati del test, ed è quella che provoca il "problema"
Secondo me, invece, il principale problema (non è detto che sia il solo) è che quella routine utilizzi un Intent per avviare nuovamente l'Activity Main (StartActivity(i))

Se non lo hai già fatto, scrivi:
B4X:
B4XPages.GetManager.LogEvents = True
Nella routine Initialze della B4XMainPage.

Poi usa l'app, chisura compresa, e segui con attenzione nella finestra dei log tutti gli eventi che riguardano sia l'Activity che le B4XPages.
[Sicuramente lo saprai già ma puoi anche copiare quei log, facendo tasto destro nella finestra e scegliendo la voce di menu]
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
c'è un errore di programmazione grossolano nella resumable sub che fa avanzare e chiudere la finestra, ma a ritorno della sub fa riaprire la finestra..
 

Star-Dust

Expert
Licensed User
Longtime User
Partiamo dalal cosa che già ti ha segnalato @LucaMs
B4X:
Wait For (GL.oConn.StopSophosClient) complete (Result As Boolean)

B4X:
Public Sub StopSophosClient As ResumableSub

    Dim i As Intent
    i.Initialize(i.ACTION_MAIN, "")
    i.SetComponent("de.blinkt.openvpn/.api.DisconnectVPN")
    i.PutExtra("de.blinkt.openvpn.shortcutProfileName", "VPN_Telecontrollo")
    StartActivity(i)
    ToastMessageShow("Disconnessione VPN in corso...",False)
    Sleep(2000)
     Return True
End Sub
Il risultato di una resumable ci dev'essere sempre per due ragioni: 1) per una scrittura pulita del codice e 2) per consentire al framework di capire bene dove mettere il punti di ripristino.

Un'alternativa è che potresti mettere Sleep dopo aver Chiamato GL.oConn.StopSophosClient
B4X:
Private Sub btnExit_Click
    Log1 ("Uscita")
    btnStart.Enabled=False
    btnExit.Enabled=False
    GL.bVPNstarted=False
    'Elimina le pagine vecchie altrimenti alla chiusura di questa pagina torna alla precedente
    '  per farlo non usare Show per chimare ogni pagina successiva ma ShowPageAndRemovePreviousPages

    GL.oConn.StopSophosClient
    Sleep(2000)
    ToastMessageShow("VPN disconnessa",False)
    B4XPages.ClosePage(Me)
End Sub

INFINE
Poi se vuoi chiudere B4XPAGES l'App (in Android) ma farlo rimanere in background usa questo:
B4X:
    Dim i As Intent
    i.Initialize(i.ACTION_MAIN, "")
    i.AddCategory("android.intent.category.HOME")
    i.Flags = 0x10000000
    StartActivity(i)
come indicato da @Erel in questo post

Se invece vuoi terminarla e togliere anche dal Task Manager usa questo:
B4X:
Sub RemoveActivityFromForeground

    '*** Below code moves the task containing this activity to the back of the activity stack.***
    '*** It's a quick way to remove your activity, more or less like "bring to back"
    Dim jo As JavaObject
    jo.InitializeContext
    jo.RunMethod("moveTaskToBack", Array(True))
    '********************************************************************************************
End Sub
Come spiegato dall'amico @moster67

In genere se usi B4XPages.ShowPageAndRemovePreviousPages le pagine precedenti non rimangono aperte
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Il risultato di una resumable ci dev'essere sempre per due ragioni: 1) per una scrittura pulita del codice e 2) per consentire al framework di capire bene dove mettere il punti di ripristino.
Mah, io grazie a @Sabotto ho scoperto che una riga come questa:
B4X:
Wait For (QualcheRoutine) Complete
non solo viene accettata dal parser ma anche in compilazione e funziona, nel senso che la pausa (l'attesa che si scateni l'evento) avviene :oops:
 

Star-Dust

Expert
Licensed User
Longtime User
Mah, io grazie a @Sabotto ho scoperto che una riga come questa:
B4X:
Wait For (QualcheRoutine) Complete
non solo viene accettata dal parser ma anche in compilazione e funziona, nel senso che la pausa (l'attesa che si scateni l'evento) avviene :oops:
Ma non è pulita è non sappiamo se Erel lo toglierà. Fra l'altro che l'ambiente IDE mi segnala errore se una ResumableSub non restituisca un valore
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
funziona su tutte e tre le piattaforme?

Comunque poi le considerazioni importanti sono le altre relative alla chiusura
 

LucaMs

Expert
Licensed User
Longtime User
funziona su tutte e tre le piattaforme?
Boh, immagino di sì.
Correggo, comunque, un senso ce l'ha, perché potresti non voler usare il valore restituito ma attendere ugualmente.

Comunque poi le considerazioni importanti sono le altre relative alla chiusura
Certo; volevo solo sottolineare che una riga come quella mi è subito sembrato un errore e pensavo pure che non sarebbe stata accettata, come minimo in fase di compilazione, invece è accettata anche dal parser e funziona perfettamente.
 

LucaMs

Expert
Licensed User
Longtime User
un senso ce l'ha, perché potresti non voler usare il valore restituito ma attendere ugualmente.
Spesso scrivo:
B4X:
Wait For(Qualcosa) Complete(Unused As Boolean)
ovvero non utilizzo il valore restituito, non mi serve (non a caso chiamo la variabile Unused). Beh, ora so che posso pure evitare di scrivere la parte dopo il Complete.
 

Star-Dust

Expert
Licensed User
Longtime User
Boh, immagino di sì.
Su B4J si blocca.

Certo; volevo solo sottolineare che una riga come quella mi è subito sembrato un errore e pensavo pure che non sarebbe stata accettata, come minimo in fase di compilazione, invece è accettata anche dal parser e funziona perfettamente.
Sto sperimentando e l'IDe lo segnala come errore il framework compe previsto non riesce sempre a trovare il punto di entrata e ritorno , almeno in B4J. Perchè ricordavo che Erel lo ha spiegato.

Adesso provo in B4i
 

Star-Dust

Expert
Licensed User
Longtime User
Ok scoperto. Se se non metti la sub tra le parentesi non effettua nessun Ritorno. Comunque funziona anche su B4J
Ora provo B4I
 

Star-Dust

Expert
Licensed User
Longtime User
In B4i non funziona
 
Top