diff --git a/Lanterna2.b4a.meta b/Lanterna2.b4a.meta
index 538816a..c2dbca7 100644
--- a/Lanterna2.b4a.meta
+++ b/Lanterna2.b4a.meta
@@ -28,6 +28,6 @@ ModuleClosedNodes6=
ModuleClosedNodes7=
ModuleClosedNodes8=
ModuleClosedNodes9=
-NavigationStack=Principal,Activity_Create,211,6,Principal,b_mesaCerrar_Click,1340,0,Main,Process_Globals,30,0,appUpdater,Process_Globals,78,6,Principal,b_pagoCerrar_Click,1464,5,Principal,p_resItem_LongClick,3881,6,Principal,b_resumen_Click,3734,3,Principal,b_cambioPagos_Click,3900,3,Visual Designer,principal.bal,-100,6,Principal,llenaHistorial,1014,0
+NavigationStack=Principal,p_resItem_LongClick,3881,6,Principal,b_resumen_Click,3734,3,Principal,b_cambioPagos_Click,3900,3,Visual Designer,principal.bal,-100,6,Principal,llenaHistorial,1014,0,numeroATexto,Class_Globals,18,0,numeroATexto,Initialize,21,0,updateAvailable,Process_Globals,0,0,updateAvailable,Activity_Resume,43,0,appUpdater,Process_Globals,80,1
SelectedBuild=0
-VisibleModules=7,6,8
+VisibleModules=7,6,8,5,9,1
diff --git a/appUpdater.bas b/appUpdater.bas
new file mode 100644
index 0000000..f7a6133
--- /dev/null
+++ b/appUpdater.bas
@@ -0,0 +1,292 @@
+B4A=true
+Group=Default Group
+ModulesStructureVersion=1
+Type=Service
+Version=10.2
+@EndOfDesignText@
+#Region Service Attributes
+ #StartAtBoot: False
+#End Region
+
+'////////////////////////////////////////////////////////////////////////////////////////////
+'//// Servicio para revisar si hay actualizacion de aplicación, usa la
+'//// actividad "updateAvailable" para mostrar mensajes.
+'////
+'//// https://www.b4x.com/android/forum/threads/update-your-app-without-using-the-gplaystore.109720/#content
+'////
+'//// En la actividad del la cual se va a llamar la revision de actualizacion
+'//// hay que agregar los siguientes Subs:
+'////
+' Sub boton_que_llama_revision_Click
+' StartService(appUpdater)
+' End Sub
+'
+' appUpdater - Mostramos el anuncio de que se esta descargando el nuevo apk
+' Sub muestraProgreso
+' ProgressDialogShow("Descargando actualización")
+' End Sub
+'
+' appUpdater - Ocultamos el anuncio de que se esta descargando el nuevo apk
+' Sub ocultaProgreso
+' ProgressDialogHide
+' End Sub
+'////
+'//// Requiere las siguientes librerias:
+'////
+'//// * JavaObject
+'//// * OkHttpUtils2
+'//// * Phone
+'//// * RuntimePermissions
+'//// * appUpdating
+'////
+'//// Requiere las siguientes lineas en el manifiesto:
+'////
+' AddManifestText(
+' )
+' AddApplicationText(
+'
+'
+'
+' )
+' CreateResource(xml, provider_paths,
+'
+'
+'
+'
+'
+' )
+' AddPermission(android.permission.REQUEST_INSTALL_PACKAGES)
+' AddPermission(android.permission.INTERNET)
+' AddPermission(android.permission.INSTALL_PACKAGES)
+' AddPermission(android.permission.READ_EXTERNAL_STORAGE)
+' AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)
+' AddPermission(android.permission.READ_PHONE_STATE)
+' AddPermission(android.permission.WAKE_LOCK)
+'////
+'////////////////////////////////////////////////////////////////////////////////////////////
+
+Sub Process_Globals
+ 'These global variables will be declared once when the application starts.
+ 'These variables can be accessed from all modules.
+
+ 'Aqui va la liga al archivo .ver en el servidor que contiene la información de la aplicacion
+ Public lnk As String = "https://keymon.lat/movil/Lanterna/Lanterna.ver"
+ '#####################################################
+ '################# RUTA EN EL SERVIDOR ##################
+ '########## \\10.0.0.205\e$\Cargas\MOVIL\Lanterna ############
+ '#####################################################
+ '/// En el servidor se necesita un archivo de texto (.ver) que tenga los siguientes
+ '/// datos separados por un tabulador.
+ '/// contents of ver file, each field is seperated by a tab
+ ' Field 0 = 2.226.19.09.19.01a <-- Esta es la version de la aplicación disponible
+ ' Field 1 = A new version of the MyAPP is available, Download and update now ? <-- Mensaje para cuando hay actualización
+ ' Field 2 = MyApp is up to date <--- Mensaje para cuando no hay actualización
+ ' Field 3 = http://www.mydomain.com/Public/myapp.apk <--- Liga al apk de la actualización
+
+ Public nNewApp As Notification
+ Public nNewAppnID As Int = 16
+ 'Para Download
+ Dim nativeMe As JavaObject
+ Dim n2 As Notification
+ Dim n2ID As Int = 16
+ 'Para fileProvider
+ Public SharedFolder As String
+ Public UseFileProvider As Boolean
+ Private rp As RuntimePermissions
+
+ Type mNewVersion(update As Boolean, nonewAPP As Boolean, notifyUser As Boolean, _
+ version As String, newMsg As String, okMsg As String, appLink As String)
+ Public newApp As mNewVersion
+End Sub
+
+Sub Service_Create
+ Log("appUpdater(), Service_Create")
+ newApp.Initialize
+ Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_NEVER
+ n2.Initialize
+ nativeMe.InitializeContext
+End Sub
+
+Sub Service_Start (StartingIntent As Intent)
+ Log("appUpdater(), Service_Start")
+' CallSubDelayed2(Main, "muestraProgreso", "Buscando actualización")
+ CallSubDelayed2(Main, "muestraProgreso", "Buscando actualización")
+' B4XPages.MainPage.muestraProgreso("Buscando actualización")
+ Log("Buscando actualización")
+ fileProvider_init
+ Log(lnk)
+ Wait For (Download(Me, lnk)) JobDone (j As HttpJob)
+ If j.Success Then
+ Log("success")
+ Try
+ Dim app() As String = Regex.Split(Chr(9),j.GetString)
+ ' // Set the data
+ newApp.appLink = app(3) 'Liga a nueva app
+ newApp.newMsg = app(1) 'Texto de que hay actualizacion
+ newApp.okMsg = app(2) 'Texto de app al corriente
+ newApp.version = app(0) 'Version actual
+
+ Log($"Application.VersionName=${Application.VersionName}, newApp=${newApp}"$)
+
+ ' // App version check
+ If newApp.version = Application.VersionName Then
+ newApp.update = False
+ Log("No new app")
+' B4XPages.ShowPage("updateAvailable")
+ StartActivity(updateAvailable)
+ 'Se puede mandar tambien una notificacion avisando que NO hay actualizaciones
+ CreateNotification2("Aplicacion al corriente","No hay actualizaciones disponibles","ic_file_download_white_24dp",Main,True,True,nNewApp,nNewAppnID)
+ End If
+ If newApp.version <> Application.VersionName Then
+ newApp.update = True
+ Log("New app true")
+' B4XPages.ShowPage("updateAvailable")
+ StartActivity(updateAvailable)
+ 'Se puede mandar tambien una notificacion avisando que hay actualizacion disponible
+' CreateNotification2("Nueva aplicación disponible","Haga clic para descargar.","ic_file_download_white_24dp",C_UpdateAvailable,True,True,nNewApp,nNewAppnID)
+ End If
+ Catch
+ Log("appUpdater(), Job Failed, error " & LastException.Message)
+ End Try
+ Else
+ Log("appUpdater(), Job Failed " & lnk)
+ End If
+ j.Release
+' StopService(Me)
+End Sub
+
+Sub download_Start (StartingIntent As Intent)
+ download_newApk
+End Sub
+
+Sub download_newApk
+' CreateNotification("Descargando actualización", "Descargando apk", "ic_file_download_white_24dp", Main, False, True)
+' CallSubDelayed2(Main, "muestraProgreso", "Descargando actualización")
+ Log("Descargando actualización")
+' B4XPages.ShowPage("login")
+ StartActivity(Main)
+ Starter.muestraProgreso = 1
+ Dim job_newAPP As HttpJob
+ job_newAPP.Initialize("job_newAPP",Me)
+ job_newAPP.Download(newApp.appLink)
+ Wait for (job_newAPP) JobDone (job_newAPP As HttpJob)
+ If job_newAPP.Success = True Then
+ ' // Delete existing file
+ If File.Exists(SharedFolder,"newapp.apk") Then
+ File.Delete(SharedFolder,"newapp.apk")
+ End If
+ ' // Save new file
+ Dim outNewAPK As OutputStream = File.OpenOutput(SharedFolder,"newapp.apk", False)
+ File.Copy2(job_newAPP.GetInputStream, outNewAPK)
+ outNewAPK.Close
+ If Starter.Logger Then Log("APK dir: "&SharedFolder)
+ End If
+ job_newAPP.Release
+ ' // Install the app
+ Dim in As Intent
+ in.Initialize(in.ACTION_VIEW,"" )
+ SetFileUriAsIntentData(in, "newapp.apk")
+ ' // Type must be set after calling SetFileUriAsIntentData
+ in.SetType("application/vnd.android.package-archive")
+ StartActivity(in)
+ n2.Cancel(nNewAppnID)
+' B4XPages.MainPage.ocultaProgreso
+ CallSubDelayed(Main, "ocultaProgreso")
+' Service.StopForeground(nNewAppnID)
+ StopService(Me)
+' CallSubDelayed(Main,"ocultaProgreso")
+End Sub
+
+Sub download_Destroy
+ n2.Cancel(n2ID)
+ Service.StopForeground(n2ID)
+End Sub
+
+Sub Download (Callback As Object, link As String) As HttpJob
+ Dim j As HttpJob
+ j.Initialize("", Callback)
+ j.Download(link)
+ Return j
+End Sub
+
+Private Sub CreateNotification2(Title As String, Content As String, _ 'ignore
+ Icon As String, TargetActivity As Object, Sound As Boolean, _
+ Vibrate As Boolean, pN As Notification,pNID As Int) As Notification
+ pN.Initialize2(pN.IMPORTANCE_HIGH)
+' pN.Number = pNID
+' pN.Light = False
+ pN.Vibrate = Vibrate
+ pN.Sound = Sound
+' pN.OnGoingEvent = False
+ pN.Icon = Icon
+ pN.AutoCancel = True
+ pN.SetInfo(Title, Content, TargetActivity)
+ pN.Notify(pNID)
+ Return pN
+End Sub
+
+Private Sub CreateNotification(Title As String, Content As String, Icon As String, TargetActivity As Object, Sound As Boolean, Vibrate As Boolean) As Notification 'ignore
+ n2.Initialize
+ n2.Light = False
+ n2.Vibrate = Vibrate
+ n2.Sound = Sound
+ n2.OnGoingEvent = True
+ n2.Icon = Icon
+ n2.SetInfo(Title, Content, TargetActivity)
+ n2.Notify(nNewAppnID)
+End Sub
+
+Sub Service_Destroy
+ Log("appUpdater(), Service_Destroy")
+End Sub
+
+Sub fileProvider_init
+ Dim p As Phone
+ If p.SdkVersion >= 24 Or File.ExternalWritable = False Then
+ UseFileProvider = True
+ SharedFolder = File.Combine(File.DirInternal, "shared")
+ If Not(File.IsDirectory(File.DirInternal,"shared")) Then
+ File.MakeDir("", SharedFolder)
+ End If
+ Else
+ UseFileProvider = False
+ SharedFolder = rp.GetSafeDirDefaultExternal("shared")
+ End If
+ Log($"Using FileProvider? ${UseFileProvider}"$)
+End Sub
+
+'Returns the file uri.
+Sub GetFileUri (FileName As String) As Object
+ Try
+ If Not(UseFileProvider) Then
+ Dim uri As JavaObject
+ Return uri.InitializeStatic("android.net.Uri").RunMethod("parse", Array("file://" & File.Combine(SharedFolder, FileName)))
+ End If
+ Dim f As JavaObject
+ f.InitializeNewInstance("java.io.File", Array(SharedFolder, FileName))
+ Dim fp As JavaObject
+ Dim context As JavaObject
+ context.InitializeContext
+ fp.InitializeStatic("android.support.v4.content.FileProvider")
+ Return fp.RunMethod("getUriForFile", Array(context, Application.PackageName & ".provider", f))
+ Catch
+ Log("FileProvider::GetFileUri - error - " & LastException.Message)
+ Return ""
+ End Try
+End Sub
+
+'Replaces the intent Data field with the file uri.
+'Resets the type field. Make sure to call Intent.SetType after calling this method
+Sub SetFileUriAsIntentData (Intent As Intent, FileName As String)
+ Dim jo As JavaObject = Intent
+ jo.RunMethod("setData", Array(GetFileUri(FileName)))
+ Intent.Flags = Bit.Or(Intent.Flags, 1) 'FLAG_GRANT_READ_URI_PERMISSION
+End Sub
diff --git a/updateAvailable.bas b/updateAvailable.bas
new file mode 100644
index 0000000..82503cf
--- /dev/null
+++ b/updateAvailable.bas
@@ -0,0 +1,77 @@
+B4A=true
+Group=Default Group
+ModulesStructureVersion=1
+Type=Activity
+Version=12.8
+@EndOfDesignText@
+Sub Process_Globals
+' Private Root As B4XView 'ignore
+' Private xui As XUI 'ignore
+End Sub
+
+Sub Globals
+ 'These global variables will be redeclared each time the activity is created.
+ 'These variables can only be accessed from this module.
+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.
+Sub Activity_Create(FirstTime As Boolean)
+' Root = Root1
+ 'load the layout to Root
+ Activity.Color = Colors.Transparent
+End Sub
+
+Sub Activity_Resume
+ Try
+ Do While Not(CanRequestPackageInstalls)
+ MsgboxAsync($"Por favor permita que ${Application.PackageName} instale actualizaciones"$, "Instalar actualización")
+ Wait For Msgbox_Result(Result As Int)
+ Dim in As Intent
+ in.Initialize("android.settings.MANAGE_UNKNOWN_APP_SOURCES", "package:" & Application.PackageName)
+ StartActivity(in)
+ Loop
+ Catch
+ Log("updateAvailable() Error - " & LastException.Message)
+ End Try
+ If appUpdater.newApp.update Then
+ ofreceActualizacion
+ Else
+ sinActualizacion
+ End If
+End Sub
+
+'////////////////////////////////////////////////////////////////////////////////////////////
+'//// Esta es una actividad usada por el servicio appUpdater para mostrar notificaciones
+'//// cuando hay alguna actualizacion de apk.
+'////////////////////////////////////////////////////////////////////////////////////////////
+
+public Sub CanRequestPackageInstalls As Boolean
+ ' // https://www.b4x.com/android/forum/threads/version-safe-apk-installation.87667/#content
+ Dim ctxt As JavaObject
+ ctxt.InitializeContext
+ Dim PackageManager As JavaObject = ctxt.RunMethod("getPackageManager", Null)
+ Return PackageManager.RunMethod("canRequestPackageInstalls", Null)
+End Sub
+
+Sub ofreceActualizacion
+ If Msgbox2(appUpdater.newApp.newMsg,"Actualización disponible","Si","","No",Null) = DialogResponse.Positive Then 'ignore
+' StartService(DownloadService)
+ CallSubDelayed(appUpdater, "download_newApk")
+ End If
+ CallSubDelayed(Main, "ocultaProgreso")
+ StartActivity(Main)
+' Activity.Finish
+' B4XPages.ShowPage("Login")
+End Sub
+
+Sub sinActualizacion
+ Msgbox(appUpdater.newApp.okMsg, "Aplicación al corriente") 'ignore
+ CallSubDelayed(Main, "ocultaProgreso")
+ StartActivity(Main)
+' B4XPages.ShowPage("Login")
+End Sub
\ No newline at end of file