Android Question Keep a B4X page fixed when activating Resume (Second Thread)

I was advised by the administrator to open another thread, providing more information about the issue. I’m using B4XPages (I'm migrating from activities to B4XPages) and I'm new to this approach. I'm trying to make it so that when the user hasn't logged in, the login screen is shown, and if they are already logged in, it goes directly to the app with the login data, without having to enter the credentials every time the app starts. My issue is that after 5 to 7 minutes in the background, the app asks for the login again. I was recommended to use KVS, and here is what I have and what it generates: I have this code in the B4XMainPage:

Code in B4XMainPage:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private BtnSigIn As Button
    Private ImageView1 As ImageView
    Private Label1 As Label
    Private Label2 As Label
    Private Label3 As Label
    Private LabelAgregarCuenta As Label
    Private LabelForgetPass As Label
    Private LabelPass As Label
    Private LabelRecovery As Label
    Private LabelTitle1 As Label
    Private LabelTitle2 As Label
    Private LabelUser As Label
    Private LabelView As Label
    Private Panel1 As Panel
    Private Panel2 As Panel
    Private Panel3 As Panel
    Private PanelNaranja As Panel
    Private PanelToolBar As Panel
    Private TextPassword As EditText
    Private TextUser As EditText
    
    'other variables
    Dim ImageIndex As Int
    Dim ImageTimer As Timer
    Dim tableApi As String = "api_jaanal_gloriafood.php"
    Dim insertdata As HttpJob
    Dim deletedata As HttpJob
    Dim updatedata As HttpJob
    Dim selectdata As HttpJob
    
    'trae los logos de comercios en hexadecimal
    Dim getLogoComercios As HttpJob
    
    'obtener la info del user
    Dim getInfoUser As HttpJob
    'obtener informacion de los comercios
    Dim getInfoComercios As HttpJob
    ' Declarar una variable para la librería Base64
    Dim su As StringUtils ' Declarar el objeto StringUtils
    
    Dim busquedadata As HttpJob 'es cuando hago una búsqueda
    
    
    
    'banner
    Private MyListBlob As List
    Private CurrentImageIndex As Int
    
    
    Private ImageSlider1 As ImageSlider
    Private CurrentImageIndex As Int
    Private ImageViewBlop As ImageView
    
    'progress
    Dim myProgressDialog As CustomProgressDialog
    Dim TotalProgress As Int
    
    ' Declare una variable para el Panel del diálogo
    Dim dialogPanel As Panel
    'Private ImageViewDialog As ImageView
    Private ImageViewDialog As ImageView
    Private LabelTittle As Label
    Private LabelDialogTittle As Label
    
    
'    Private imgsplash As B4XImageView
'    Private lbsplash As Label
'    Private lbsplashL As Label
'    Private psplash As Panel
'    Private ProgressBar1 As SD_LoadingIndicator
'    Private Root As Panel ' Añadido para manejar el panel raíz
'    Private t As Timer
    Private LabelAgregarCuenta As Label
    Private LabelView As Label
    Private LabelRecovery As Label
    
    Private ver As Boolean = False
    
    Private password_recovery As String
    Private usuario_recovery As String
    
    Public KVS As KeyValueStore
    
    
    'paginas
    Dim adduser_B4XPages_obj As adduser_B4XPages
    Dim login_B4XPages_obj As B4XMainPage
    Dim formprincipal_B4XPages_obj As formprincipal_B4XPages
    Dim vermapaubicacion_B4XPages_obj As vermapaubicacioncomercio_B4XPages
    Dim consolarestaurante_B4XPages_obj As consolarestaurante_B4XPages
    
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
    KVS.Initialize(xui.DefaultFolder,"kvs")
'    Log ("KVS Inicializado")
    If KVS.ContainsKey("user") Then  'If we've logged before, go directly to PageData (Si hemos iniciado sesión con anterioridad, vamos directamente a la página de datos)
        Log("KVS Ya hemos iniciado sesion: " & KVS.Get("user"))
        
        
'        B4XPages.MainPage.KVS.Remove("user")
'        B4XPages.MainPage.KVS.Remove("id_user")
'        B4XPages.MainPage.KVS.Remove("estado_id")
'        B4XPages.MainPage.KVS.Remove("municipio_id")
        
        
        formprincipal_B4XPages_obj.Initialize
        B4XPages.AddPage("formprincipal_B4XPages", formprincipal_B4XPages_obj)
        B4XPages.ShowPageAndRemovePreviousPages("formprincipal_B4XPages")
        
        
    Else
        Log("KVS no se ha iniciado sesion")
    End If
End Sub
'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("login")
    
'    'inicializamos para saber si el usuario se ha registrado
'    KVS.Initialize(xui.DefaultFolder,"kvs") 'We use KVS to save the logged user (Usaremos KVS para guardar el usuario que inicia sesión)
    
    adduser_B4XPages_obj.Initialize
    
    B4XPages.AddPage("adduser_B4XPages",adduser_B4XPages_obj)
    B4XPages.AddPage("B4XMainPage",login_B4XPages_obj)
    
    formprincipal_B4XPages_obj.Initialize
    B4XPages.AddPage("formprincipal_B4XPages",formprincipal_B4XPages_obj)
    
    vermapaubicacion_B4XPages_obj.Initialize
    B4XPages.AddPage("vermapaubicacioncomercio_B4XPages",vermapaubicacion_B4XPages_obj)
    
    consolarestaurante_B4XPages_obj.Initialize
    B4XPages.AddPage("consolarestaurante_B4XPages",consolarestaurante_B4XPages_obj)
    
    LabelView.Color=Colors.Gray
    'ProgressTimer.Initialize("ProgressTimer", 100)
    'ProgressTimer.Enabled=True
    
    MyListBlob.Initialize
    ImageView1.Initialize("ImageView1")
    ImageViewBlop.Initialize("ImageViewBlop")
    MostrarLogin
    CenterImageViewHorizontally(ImageView1)
    LabelTitle1.Visible=False
    CenterLabelHorizontally(LabelForgetPass)
    'getInfoUserLogin
    getAllLogoComercios
    'wait for (getAllLogoComercios) Complete (Answer As Boolean)
    'If Answer=True Then
    
    'If FirstTime Then
        ImageTimer.Initialize("ImageTimer", 2000) ' Cambia el intervalo según lo necesites (en milisegundos)
        ImageTimer.Enabled = True
        'ImageTimer_Tick
        'ImageSlider1.WindowBase.
            
        ImageIndex = 0
            
        ' Inicializa el temporizador para cambiar de imagen cada 3 segundos
'            timerSecuencia.Initialize("timerSecuencia", 3000) ' 3000 ms = 3 segundos
'            timerSecuencia.Enabled = True
'            btnSiguiente_Click
    'End If
    'End If
    
End Sub
And in formprincipal_B4XPages, I have this code:

Code in formprincipal_B4XPages:
Sub Class_Globals
    Private Root As B4XView 'ignore
    Private xui As XUI 'ignore
    
    Private const R As Double = 6371.0 ' Radio de la Tierra en kilómetros
    Public  WobbleMenu1 As WobbleMenu
    
    Private CLV1 As CustomListView
    'Private ImageView1 As B4XView
    Private ImageView1 As ImageView
    Private lblTitle As B4XView
    Private lblContent As B4XView
    Private lblAction1 As Label
    Private lblAction2 As Label
    
    Private Label1 As B4XView
    Private UM_AddToCart1 As UM_AddToCart
    
    
    Private precio As Double = 60
    Dim importeTotal As Double = 0
    
    Private Label2 As Label
    ' Declaración de una lista global para almacenar los paneles
    Private PanelList As List
    PanelList.Initialize
    
    Dim tableApi As String = "api_jaanal_gloriafood.php"
    Dim getInfoComercios As HttpJob
    Dim getInfoEstados As HttpJob
    Dim getInfoMunicipios As HttpJob
    
    ' Declarar una variable para la librería Base64
    Dim su As StringUtils ' Declarar el objeto StringUtils
    
    Dim listaComercios As List
    listaComercios.Initialize
    
    Dim listaEstados As List
    listaEstados.Initialize
    
    Dim listaMunicipios As List
    listaMunicipios.Initialize
    
        
    Private btnTienda As Button
    Private LabelUrl As Label
    Private LabelPhone As Label
    Private LabelWhatsapp As Label
    Private LabelEstatus As Label
    
    Private timerActualizarEstatus As Timer
    
    
    Dim n As Notification
    'Private btnEstado As Button
    
    Private xDialog As B4XDialog
    Private xListTemplate As B4XListTemplate
    
    Private xDialogMunicipio As B4XDialog
    Private xListTemplateMunicipio As B4XListTemplate
    
    
    
    Private btnIconEstado As IconButton
    Private btnIconMunicipio As IconButton
    Private LabelMaps As Label
    
    Dim Awake As PhoneWakeState
    
    ' Declaración de variables locales
    Private lat1 As Double = 20.1897702 ' Latitud del primer punto
    Private lon1 As Double = -89.267435 ' Longitud del primer punto
    Private lat2 As Double = 20.2193758 ' Latitud del segundo punto
    Private lon2 As Double = -89.309799 ' Longitud del segundo punto
    
    Private rp As RuntimePermissions
    
    Public KVS As KeyValueStore
End Sub

'You can add more parameters here.
Public Sub Initialize As Object
    Return Me
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    'load the layout to Root
    Root.LoadLayout("formPrincipal_layout")
    
    B4XPages.AddMenuItem(Me, "Item 1")
    B4XPages.AddMenuItem(Me, "Item 2")
    
    
    B4XPages.SetTitle(Me, "Bienvenid@: " & globales.nombreUserOnline)

'    Private mi As
'    ' Crear un menú con icono
'    mi = Activity.AddMenuItem("Otro item", "MenuItem3")
'    mi.AddToBar = True
'    mi.Bitmap = LoadBitmapResize(File.DirAssets, "profile.png", 64dip, 64dip, True)
    'Activity.AddMenuItem3("Notify", "Notify",LoadBitmap(File.DirAssets, "profile64.png"),True)
    'Menu
    'WobbleMenu1.Initialize("WobbleMenu1","WobbleMenu1")
    WobbleMenu1.SetTabTextIcon(1,"Home",Chr(0xF2DA),Typeface.FONTAWESOME)
    'WobbleMenu1.SetTabTextIcon(1,"Main Page",Chr(0xF009),Typeface.FONTAWESOME)
    WobbleMenu1.SetTabTextIcon(2,"Perfil",Chr(0xF2BD),Typeface.FONTAWESOME)
    'WobbleMenu1.SetTabTextIcon(3,"Dir.",Chr(0xF015),Typeface.FONTAWESOME)
    WobbleMenu1.SetTabTextIcon(3,"Pedidos",Chr(0xF179),Typeface.FONTAWESOME)
    'WobbleMenu1.SetTabTextIcon(5,"New Page2",Chr(0xF009),Typeface.FONTAWESOME)
    WobbleMenu1.SetCurrentTab2(1, False)
    
    If B4XPages.MainPage.KVS.ContainsKey("user") Then 'si ya se ha iniciado sesion entonces leemos el valor del estado id
        'leer un valor de kms KVS.Get("user")
        
        
        If Not(CLV1.IsInitialized) Then
            
            CLV1.Initialize("CLV1","CLV1")
            Else
                Log("ya esta inicializado")
        End If
        ProgressDialogShow("Preparando Comercios...")
        wait for (getInfoComerciosActivos(B4XPages.MainPage.KVS.Get("estado_id"),B4XPages.MainPage.KVS.Get("municipio_id"))) Complete (Answer As Boolean)
    
    Else
        'entonces lo hacemos con los valores de primera vez porque globales ya tiene un valor
        ProgressDialogShow("Preparando Comercios...")
        wait for (getInfoComerciosActivos(globales.idEstadoUserOnline,globales.idMunicipioUserOnline)) Complete (Answer As Boolean)
    
    End If
    
    
'    ProgressDialogShow("Preparando Comercios...")
'    wait for (getInfoComerciosActivos(globales.idEstadoUserOnline,globales.idMunicipioUserOnline)) Complete (Answer As Boolean)
'   
    
    Dim bitmaps As List = Array("ham.jpg", "ham2.jpg", _
        "ham3.jpg", "ham4.jpg")


    For i = 0 To listaComercios.Size - 1 'era 4
        
        Dim comercioInfo As Map = listaComercios.Get(i)
        
        Dim idComercio As String = comercioInfo.Get("IDCOMERCIO")
        Dim nombreComercio As String = comercioInfo.Get("NOMBRE_COMERCIO")
        Dim direccion As String = comercioInfo.Get("DIRECCION")
        Dim correo As String = comercioInfo.Get("CORREO")
        Dim telefono As String = comercioInfo.Get("TELEFONO")
        Dim sitioWeb As String = comercioInfo.Get("SITIOWEB")
        Dim hrApertura As String = comercioInfo.Get("HRAPERTURA")
        Dim hrCierre As String = comercioInfo.Get("HRCIERRE")
        Dim lunes As String = comercioInfo.Get("LUNES")
        Dim martes As String = comercioInfo.Get("MARTES")
        Dim miercoles As String = comercioInfo.Get("MIERCOLES")
        Dim jueves As String = comercioInfo.Get("JUEVES")
        Dim viernes As String = comercioInfo.Get("VIERNES")
        Dim sabado As String = comercioInfo.Get("SABADO")
        Dim domingo As String = comercioInfo.Get("DOMINGO")
        Dim estado As String = comercioInfo.Get("ESTADO")
        Dim municipio As String = comercioInfo.Get("MUNICIPIO")
        'comercioInfo.Put("URL_STORE", coljRoot.Get("url_store"))
        
        Dim logo As Bitmap = comercioInfo.Get("LOGO")
        Dim url_store As String =comercioInfo.Get("URL_STORE")
        Dim url_ubicacion As String = comercioInfo.Get("URL_UBICACION")
        
        Dim sb As StringBuilder
        sb.Initialize
        If lunes = "SI" Then sb.Append("Lunes, ")
        If martes = "SI" Then sb.Append("Martes, ")
        If miercoles = "SI" Then sb.Append("Miércoles, ")
        If jueves = "SI" Then sb.Append("Jueves, ")
        If viernes = "SI" Then sb.Append("Viernes, ")
        If sabado = "SI" Then sb.Append("Sábado, ")
        If domingo = "SI" Then sb.Append("Domingo, ")

        Dim result As String = sb.ToString
        ' Quita la última coma y el espacio si la cadena no está vacía
        If result.Length > 0 Then
            result = result.SubString2(0, result.Length - 2)
        End If
        
        'codigo para saber si abre hoy o no:
        '####
        ' Obtiene el día de la semana actual
        Dim today As Int = DateTime.GetDayOfWeek(DateTime.Now)

        Dim isOpenToday As Boolean = False
        Select today
            Case 1
                If domingo = "SI" Then isOpenToday = True
            Case 2
                If lunes = "SI" Then isOpenToday = True
            Case 3
                If martes = "SI" Then isOpenToday = True
            Case 4
                If miercoles = "SI" Then isOpenToday = True
            Case 5
                If jueves = "SI" Then isOpenToday = True
            Case 6
                If viernes = "SI" Then isOpenToday = True
            Case 7
                If sabado = "SI" Then isOpenToday = True
        End Select

        If isOpenToday Then
            Log("El comercio está abierto hoy.")
        Else
            Log("NO ABRE EL DÍA DE HOY")
        End If
        '####
        
        Dim estatusActual As String = CheckComercioStatus(comercioInfo)

        
        
        
        Dim content As String = direccion & "." & CRLF  & municipio & ", " & estado & CRLF & "Abre: " & hrApertura &  CRLF & "Cierra: " & hrCierre &  CRLF & result  &  CRLF & "Tel. "  & telefono &  CRLF & "Email: "   & correo '&  CRLF & url_store
‘AQUÍ ES DONDE GENERA UN ERROR AL ENTRAR CUANDO YA SE HA INICIADO SESION       
CLV1.Add(CreateItem(CLV1.AsView.Width, nombreComercio, bitmaps.Get(1), content,i,logo,url_store,telefono,estatusActual,isOpenToday,url_ubicacion), "")
    Next
    
    wait for (getAllEstados) Complete (AnswerEstados As Boolean)
    If AnswerEstados = True Then
    
    Else
        MsgboxAsync("No existen Estados o se generó un error al leerlos","Mensaje")
    End If
    
    timerActualizarEstatus.Initialize("timerActualizarEstatus",30000)
    timerActualizarEstatus.Enabled=True
    ProgressDialogHide
    '##Finaliza aqui

    
    ' Notificación
    n.Initialize
    n.Icon = "icon"
    n.AutoCancel= False
    n.SetInfo("Teclado", "Ejemplo de notificación", "")
    n.Notify(1)

    xDialog.Initialize(Root)
    xDialogMunicipio.Initialize(Root)
    
    Dim bm As BitmapDrawable
    bm.Initialize(LoadBitmap(File.DirAssets,"map.png"))
    btnIconEstado.Text = "SELECCIONE EL ESTADO     "
    btnIconEstado.IconPadding = 50
    btnIconEstado.setIcon(False,bm)
    
    
    Dim bm2 As BitmapDrawable
    bm2.Initialize(LoadBitmap(File.DirAssets,"map.png"))
    btnIconMunicipio.Text = "SELECCIONE EL MUNICIPIO"
    btnIconMunicipio.IconPadding = 50
    btnIconMunicipio.setIcon(False,bm2)
    
End Sub

When we start for the first time, it achieves the objective and everything is displayed correctly, but when the app goes into the background and is restarted, on the line:
CLV1.Add(CreateItem(CLV1.AsView.Width, nombreComercio, bitmaps.Get(1), content,i,logo,url_store,telefono,estatusActual,isOpenToday,url_ubicacion), "")
It generates this error:




Please help me!!!!!
 
Solution
Posting 500 lines of code is a bit too much...

I can only guess that something isn't initialized because B4XPage_Created of the main page didn't run. It didn't run because you added a page in the Initialize method. This will cause the formprincipal_B4XPages page to start first.
Thank you, Erel, I was able to resolve it. Since I'm new to using B4XPages, it's been a bit challenging to understand how it works, but I think it's just a matter of getting used to it. Thanks a lot!
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…