diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af94e9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/Objects +**/AutoBackups \ No newline at end of file diff --git a/B4A/B4XMainPage.bas b/B4A/B4XMainPage.bas new file mode 100644 index 0000000..8c2d8d0 --- /dev/null +++ b/B4A/B4XMainPage.bas @@ -0,0 +1,315 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=9.85 +@EndOfDesignText@ +#Region Shared Files +#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files" +'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True +'########################################################################################################### +'###################### PULL ############################################################# +'Ctrl + click ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=git&Args=pull +'########################################################################################################### +'###################### PUSH ############################################################# +'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=github&Args=..\..\ +'########################################################################################################### +#End Region + +'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip + +Sub Class_Globals + Dim rp As RuntimePermissions + Private Root As B4XView + Private xui As XUI + Private Root As B4XView + Public rp As RuntimePermissions + Public login As B4XMainPage + Public principal As C_Principal + Public clientes As C_Clientes + Public updateAvailable As C_UpdateAvailable + Dim reqManager As DBRequestManager +' Dim ruta As String + Dim usuario As String + Dim logger As Boolean = True + Dim lat_gps, lon_gps As String +' Dim skmt As SQL + Dim usuario As String + Dim server As String + Dim montoActual, clientesTotal, clientesVenta, clientesRechazo, clientesVisitados, almacen, rutaPreventa, CANTIDADPROD As String + Dim ultimaActualizacionGPS As String = 235959 + Dim fechaRuta As String +' Public wsServerLink As String = "ws://187.189.244.154:51042/push/b4a_ws2" +' Public wsServerLink As String = "ws://10.0.0.214:51042/push/b4a_ws2" + Dim srvIp As String + Dim phn As Phone + Dim user As EditText + Dim pass As EditText + Dim c As Cursor + Dim existe As String + Dim paso1 As String + Private IMEN As Label + Dim IMEI As String + Private Label1 As Label + Dim server As String + Private p_principal As Panel + Private Entrar As Button + Dim batt As Int + Dim porVisitar, entregas, rechazos, montoEntregado, montoRechazado As String + Private p_appUpdate As Panel + Private i_engrane As ImageView + Private b_server As Button + Private b_apk As Button + Private b_envioBD As Button + Private b_regesar As Button + Private et_server As EditText + Private p_serverList As Panel + Private lv_server As ListView + Public rutaBDBackup As String = "" +End Sub + +Public Sub Initialize +' B4XPages.GetManager.LogEvents = True +End Sub + +'This event will be called once, before the page becomes visible. +Private Sub B4XPage_Created (Root1 As B4XView) + Root = Root1 + B4XPages.GetManager.LogEvents = True + Root.LoadLayout("login") + B4XPages.SetTitle(Me, "Guna - Control de Kilometraje") + login.Initialize + B4XPages.AddPage("Login", login) + principal.Initialize + B4XPages.AddPage("Principal", principal) + clientes.Initialize + B4XPages.AddPage("Clientes", clientes) + updateAvailable.Initialize + B4XPages.AddPage("updateAvailable", updateAvailable) + reqManager.Initialize(Me, Starter.server) + LogColor($"ReqServer = ${Starter.server}"$, Colors.red) + Label1.Text = Application.VersionName + Starter.skmt.ExecNonQuery("CREATE TABLE IF NOT EXISTS CONTROL_KMS(PLACAS TEXT, OPERADOR TEXT, RUTA TEXT, KMS_INICIAL TEXT, KMS_FINAL TEXT)") +End Sub + +Sub B4XPage_Appear + If Starter.muestraProgreso = 1 Then + muestraProgreso("Descargando actualización") + Starter.muestraProgreso = 0 + End If + Subs.centraPanel(p_principal, Root.Width) +' Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION) +'' LogColor("Start Tracker1", Colors.red) +' Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) +' If Result Then +'' StartService(Tracker) +'' LogColor("Start Tracker", Colors.red) +' Else +' ToastMessageShow("No permission", True) +' Log("Sin permisos") +' End If +' LogColor("Start Tracker3", Colors.red) + c=Starter.skmt.ExecQuery("select USUARIO from usuarioa") + If c.RowCount > 0 Then +' c.Position=0 +' c=skmt.ExecQuery("select USUARIO from usuarioa") + c.Position=0 + usuario = c.GetString("USUARIO") + End If + c.Close +' Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE) +' Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) +' If Result Then +' Log("Con permisos de escritura externa") +' End If +End Sub + +'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage. + +Sub Entrar_Click + If user.Text = "KMTS1" Then + Starter.skmt.ExecNonQuery("delete from usuarioa") +' Starter.skmt.ExecNonQuery("delete from VERSION") + Starter.skmt.ExecNonQuery2("INSERT INTO USUARIOA VALUES (?,?)", Array As Object("ROOT", "ROOT")) +' Starter.skmt.ExecNonQuery("delete from cat_almacen") +' Starter.skmt.ExecNonQuery2("INSERT INTO CAT_ALMACEN(ID_ALMACEN) VALUES (?)", Array As Object (user.Text)) +' Starter.skmt.ExecNonQuery2("INSERT INTO VERSION(NOVERSION) VALUES (?)", Array As Object ("2.1")) +' principal.B_REGRESA_Click +' B4XPages.MainPage.principal.Subir.Visible = True + B4XPages.ShowPage("Principal") + Else + c=Starter.skmt.ExecQuery2("select count(*) as EXISTE1 from usuarioa where usuario = ?", Array As String(user.Text)) + c.Position=0 + existe = c.GetString("EXISTE1") + c.Close + 'existe = 1 + If existe = 0 Then + 'skmt.ExecNonQuery("delete from usuarioa") + Dim cmd As DBCommand + cmd.Initialize + cmd.Name = "select_usuario_mards_REPG" + cmd.Parameters = Array As Object(user.Text, pass.Text) + reqManager.ExecuteQuery(cmd , 0, "usuario") + + Dim cmd As DBCommand + cmd.Initialize + cmd.Name = "select_version_MARDS" + reqManager.ExecuteQuery(cmd , 0, "version") + Else +' principal.B_REGRESA_Click + B4XPages.ShowPage("Principal") + End If + End If +End Sub + +Sub JobDone(Job As HttpJob) + If Job.Success = False Then + ToastMessageShow("Error: " & Job.ErrorMessage, True) + Else + If Job.JobName = "DBRequest" Then + Dim result As DBResult = reqManager.HandleJob(Job) + If result.Tag = "version" Then 'query tag + For Each records() As Object In result.Rows + Starter.skmt.ExecNonQuery("delete from VERSION") + Dim CAT_VE_VERSION As String = records(result.Columns.Get("CAT_VE_VERSION")) +' Starter.skmt.ExecNonQuery2("INSERT INTO VERSION(NOVERSION) VALUES (?)", Array As Object (CAT_VE_VERSION)) + Next + End If + End If + + If Job.JobName = "DBRequest" Then + Dim result As DBResult = reqManager.HandleJob(Job) + If result.Tag = "agencia" Then 'query tag + For Each records() As Object In result.Rows + + Dim ID_ALMACEN As String = records(result.Columns.Get("ID_ALMACEN")) + Next + End If + End If + + If Job.JobName = "DBRequest" Then + Dim result As DBResult = reqManager.HandleJob(Job) + If result.Tag = "usuario" Then 'query tag + For Each records() As Object In result.Rows + Dim name As String = records(result.Columns.Get("USUARIO")) + Dim ID_ALMACEN As String = records(result.Columns.Get("CAT_LO_AGENCIA")) + Dim IMEI_BASE As String = records(result.Columns.Get("CAT_LO_IDTELEFONO")) + Next + paso1 = 1 + End If + End If + Job.Release + End If + + If paso1 = 1 Then + If name = "OKActivo" Then + Starter.skmt.ExecNonQuery("delete from usuarioa") + Starter.skmt.ExecNonQuery2("INSERT INTO USUARIOA VALUES (?,?)", Array As Object(user.Text, pass.Text)) + Starter.skmt.ExecNonQuery("delete from cat_almacen") +' Starter.skmt.ExecNonQuery2("INSERT INTO CAT_ALMACEN(ID_ALMACEN) VALUES (?)", Array As Object (ID_ALMACEN)) + B4XPages.ShowPage("Principal") + Else If name = "OKExpirado"& IMEI Then + Msgbox("Usuario Expirado llamar al administrador","") 'ignore + Else If name = "OKCancelado"& IMEI Then + Msgbox("Usuario Cancelado llamar al administrador","") 'ignore + Else + Msgbox("Usuario o password No validos","") 'ignore + End If + paso1 = 0 + End If +End Sub + +Private Sub i_engrane_Click + p_appUpdate.Width = Root.Width + p_appUpdate.Height = Root.Height + Subs.centraPanel(p_serverList, Root.Width) + Subs.centraBoton(b_server, Root.Width) + Subs.centraBoton(b_apk, Root.Width) + Subs.centraBoton(b_envioBD, Root.Width) + Subs.centraBoton(b_regesar, Root.Width) + Subs.centraBoton(b_server, p_serverList.Width) + lv_server.Clear + lv_server.AddSingleLine("http://keymon.lat:1787") + If user.Text = "KMTS1" Then lv_server.AddSingleLine("http://10.0.0.205:1787") +' l_server.Text = Starter.server + et_server.Text = Starter.server + Subs.panelVisible(p_appUpdate, 0, 0) +End Sub + +Private Sub B4XPage_CloseRequest As ResumableSub +' Log("closreq") + If p_appUpdate.Visible Then + p_appUpdate.Visible = False + Else + Sleep(0) + ExitApplication + End If + Return False +End Sub + +Private Sub b_regesar_Click + p_principal.Visible = True + p_appUpdate.Visible = False +End Sub + +'Enviamos la base de datos por correo o Whatsapp +Private Sub b_envioBD_Click + Public Provider As FileProvider + Log("provider") + Provider.Initialize + Dim FileName As String = "kmt.db" + Log("********* : "&Provider.SharedFolder) + Sleep(1000) + 'Copy the shared file to the shared folder + File.Copy(File.DirInternal, FileName, Provider.SharedFolder, FileName) + Dim email As Email + email.To.Add("soporte@keymonsoft.com") + email.Subject = "Base de datos para revisión" + email.Attachments.Add(Provider.GetFileUri(FileName)) +' email.Attachments.Add(Provider.GetFileUri(FileName)) 'second attachment + Dim in As Intent = email.GetIntent + in.Flags = 1 'FLAG_GRANT_READ_URI_PERMISSION + StartActivity(in) +End Sub + +Private Sub b_apk_Click + StartService(appUpdater) +End Sub + +Private Sub b_server_Click + Log("Guardar servidor") + Starter.skmt.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("SERVER")) + Starter.skmt.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER",et_server.text)) + Starter.server = et_server.text + If logger Then Log("Inicializamos reqManager con " & Starter.server) + reqManager.Initialize(Me, Starter.server) + LogColor($"ReqServer = ${Starter.server}"$, Colors.red) + reinicializaReqManager + p_appUpdate.Visible = False +' Entrar.Visible = True +End Sub + +Private Sub lv_server_ItemClick (Position As Int, Value As Object) +' l_server.Text = Value + et_server.Text = Value + Starter.server = Value + reqManager.Initialize(Me, Value) + LogColor($"ReqServer = ${Value}"$, Colors.red) + ToastMessageShow("Servidor modificado", False) +End Sub + +Sub reinicializaReqManager + reqManager.Initialize(Me, Starter.server) + If logger Then Log(Starter.server) + LogColor($"ReqServer = ${Starter.server}"$, Colors.red) +End Sub + +'appUpdater - Mostramos el anuncio de que se esta descargando el nuevo apk +Sub muestraProgreso(mensaje As String) + ProgressDialogShow(mensaje) +End Sub + +'appUpdater - Ocultamos el anuncio de que se esta descargando el nuevo apk +Sub ocultaProgreso + ProgressDialogHide +End Sub \ No newline at end of file diff --git a/B4A/C_Clientes.bas b/B4A/C_Clientes.bas new file mode 100644 index 0000000..596807b --- /dev/null +++ b/B4A/C_Clientes.bas @@ -0,0 +1,563 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=12.2 +@EndOfDesignText@ +Sub Mods + 'Los clientes con rechazo se estan mostrando en la lista ... se DEBEN de mostrar??? +End Sub + +Sub Class_Globals + Private Root As B4XView 'ignore + Private xui As XUI 'ignore + Dim q_buscar As String +' Dim skmt As SQL + Dim entro As String + Dim c As Cursor + Dim c2 As Cursor + Dim ListView1 As ListView +' Dim gest As Button + Dim lfila As Label + Dim busca As EditText + Private p_colonia As Panel +' Dim distList As List +' Dim distMap As Map + Dim laRuta As String + Private b_GetDirs As Button + Private distOrderedMap, clientesMapaO As B4XOrderedMap + Private img_getDirs As ImageView + Private l_rutaInfo As Label + Private b_getRutaInfo As Button + Private conMapa As Boolean = False + Dim listaWayPoints As List + Dim lv1Top As String + Private b_limpiarRuta As Button +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("clientes") + entro ="2" + lv1Top = ListView1.Top + clientesMapaO.Initialize + Starter.skmt.ExecNonQuery("delete from waypoints") +' Log("Coordenadas del almacen: " & Starter.cedisLocation.Longitude & "," & Starter.cedisLocation.Latitude) +End Sub + +'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage. + +Sub B4XPage_Appear + busca.Text = "" + b_GetDirs.Visible = False +' skmt.Initialize(Starter.ruta,"kmt.db", True) + entro ="2" + ' esto es para rutas se quito por colonia + 'SE COMENTA EL SIGUIENTE CODIGO PARA QUE TODAS LAS TIENDAS APAREZCAN. + 'c=skmt.ExecQuery("select CAT_CL_COLONIA, count(*) as cuantos from kmt_info where gestion = 0 group by CAT_CL_COLONIA order by CAT_CL_COLONIA asc") + p_colonia.Width = Root.Width + p_colonia.Height = Root.Height + p_colonia.Top = 0 + p_colonia.Left = 0 + Subs.centraListView(ListView1, p_colonia.Width) + ListView1.Height = p_colonia.Height * 0.75 + Subs.SetDivider(ListView1, Colors.LightGray, 2) + If Not(l_rutaInfo.Visible) Then + ListView1.Top = lv1Top + Else + ListView1.Top = lv1Top + 100 + End If + c=Starter.skmt.ExecQuery("select codigo, indice, CAT_CL_NOMBRE, CAT_CL_CALLE, CAT_CL_NOEXT from waypoints inner join kmt_info on waypoints.codigo = kmt_info.CAT_CL_CODIGO where gestion = 0 order by indice") + If c.RowCount > 0 Then 'Ya hay waypoints en la base de datos + c.Position = 0 +' Log("Ya hay waypoints.") + conMapa = True +' Private t1 As Map + ListView1.Clear + Dim cs, cs2 As CSBuilder + entro = 3 +' Log("Generamos ListView1 en Activity_Resume") + For i=0 To c.RowCount -1 'Generamos el listView con la lista ordenada. + c.Position=i + cs.Initialize + cs2.Initialize +' t1 = Starter.waypointsOrdered.Get(k) +' c.GetString("codigo") + ListView1.AddTwoLines(cs.Color(Colors.RGB(100,149,237)).Append(c.GetString("codigo")).PopAll, cs2.append(c.GetString("CAT_CL_NOMBRE")).Color(Colors.RGB(100,149,237)).Append(" Calle: ").Pop.Append(c.GetString("CAT_CL_CALLE").Trim & " " & c.GetString("CAT_CL_NOEXT")).PopAll ) + Next + Else + generaListViewRutas + End If + c.Close + p_colonia.Width = Root.Width + p_colonia.Height = Root.Height + Subs.centraEtiqueta(l_rutaInfo, Root.Width) + Subs.centraListView(ListView1, p_colonia.Width) + ListView1.Height = p_colonia.Height * 0.70 + Subs.centraEtiqueta(lfila, Root.Width) + b_getRutaInfo.Visible = True + b_getRutaInfo.BringToFront +End Sub + + +Sub ListView1_ItemClick (Position As Int, Value As Object) +' Log($"Entro= ${entro}"$) + ListView1.Clear + Sleep(50) + Subs.SetDivider(ListView1, Colors.LightGray, 2) + If Not(l_rutaInfo.Visible) Then + ListView1.Top = lv1Top + Else + ListView1.Top = lv1Top + 100 + End If + l_rutaInfo.Visible = False + b_GetDirs.Visible = False + If entro = "2" Then + b_GetDirs.Visible = True + img_getDirs.Visible = True + b_getRutaInfo.Visible = False + Private lrt As String + lrt = Value + laRuta = lrt.SubString(6) 'Quitamos el texto "Ruta: " para obtener el numero de la ruta. +' Log($"Original: ${Value} - Mod: |${lrt.SubString(6)}| - laRuta: ${laRuta}"$) + c2=Starter.skmt.ExecQuery2("select CAT_CL_NOMBRE, CAT_CL_CALLE, CAT_CL_CODIGO, CAT_CL_LAT, CAT_CL_LONG from kmt_info where CAT_CL_RUTA = ? and gestion = 0 order by CAT_CL_NOMBRE ", Array As String(laRuta)) +' Private thisLoc As Location + Private label1 As Label + Private label2 As Label + label1 = ListView1.TwoLinesLayout.Label + label1.TextSize = 15 + label1.TextColor = Colors.black + label2 = ListView1.TwoLinesLayout.SecondLabel + label2.TextSize = 15 + label2.TextColor = Colors.black + label2.Height = 38dip +' thisLoc.Initialize + If entro = 2 Then ListView1.TwoLinesLayout.ItemHeight = 75dip + lfila.text = "Nombre y Calle" + distOrderedMap.Initialize + If c2.RowCount>0 Then + For i=0 To c2.RowCount -1 'Generamos mapa de clientes + c2.Position=i +' thisLoc.Latitude = c2.GetString("CAT_CL_LAT") +' thisLoc.Longitude = c2.GetString("CAT_CL_LONG") +' Log(Tracker.UUGCoords) +' Private distancia As Int = Tracker.UUGCoords.DistanceTo(thisLoc) 'Calculamos la distancia de la posicion ACTUAL a la tienda. +' Private esteCliente As Map = CreateMap("distancia": distancia, "ubicacion": thisLoc.Longitude&","&thisLoc.Latitude, "codigo": c2.GetString("CAT_CL_CODIGO"), "nomDirDist": $"${c2.GetString("CAT_CL_NOMBRE")} CALLE: ${c2.GetString("CAT_CL_CALLE")} ${CRLF}Distancia: $1.1{(distancia/1000)} kms"$) +' distOrderedMap.Put(distancia, esteCliente) + Next + distOrderedMap.Keys.Sort(True) 'Ordenamos la mapa de clientes por distancia. + ListView1.Clear + Private m1 As Map + For Each k As Object In distOrderedMap.Keys 'Generamos el listView con el mapa ordenada. + m1 = distOrderedMap.Get(k) + m1.Get("codigo") + ListView1.AddTwoLines(m1.Get("codigo"), m1.Get("nomDirDist")) + Next + End If + c2.Close + entro = "3" + Else If entro = "3" Then + Starter.skmt.ExecNonQuery("delete from CUENTAA") + Starter.skmt.ExecNonQuery2("INSERT INTO CUENTAA VALUES (?)", Array As Object(Value)) + B4XPages.ShowPage("Cliente") + End If +End Sub + +'Genera el listview que muestra las rutas y clientes a visitar por ruta. +Sub generaListViewRutas + ListView1.Clear + Sleep(110) + lfila.Text = "RUTA PREVENTA" + Dim label1 As Label + label1 = ListView1.TwoLinesLayout.Label + label1.TextSize = 15 + label1.TextColor = Colors.Black + Dim label2 As Label + label2 = ListView1.TwoLinesLayout.SecondLabel + label2.TextSize = 15 + label2.TextColor = Colors.Black + ListView1.TwoLinesLayout.ItemHeight = 60dip + c=Starter.skmt.ExecQuery("select CAT_CL_RUTA, count(*) as cuantos from kmt_info where gestion = 0 group by CAT_CL_RUTA order by CAT_CL_RUTA asc") + If c.RowCount>0 Then + ListView1.Clear + For i=0 To c.RowCount -1 + c.Position=i + ListView1.AddTwoLines("Ruta: " & c.GetString("CAT_CL_RUTA"), "Por visitar: " & c.GetString("cuantos")) + Next + End If + c.Close +End Sub + +Sub Activity_KeyPress (key As Int) As Boolean 'ignore + ' BACK key pressed + If key=KeyCodes.KEYCODE_BACK Then + If entro = 3 And Not(conMapa) Then + b_GetDirs.Visible = False +' StartActivity(Activity_Create(False)) + B4XPage_Created(Root) + Return True + End If + B4XPages.ShowPage("Principal") + Return False + 'End If + End If + ' Returning False signals the system to handle the key +End Sub + +Sub BUSCA_TextChanged (Old As String, New As String) + q_buscar = "%" & busca.Text & "%" + c2=Starter.skmt.ExecQuery2("select CAT_CL_NOMBRE, CAT_CL_CALLE, CAT_CL_CODIGO from kmt_info where CAT_CL_NOMBRE like ? and gestion = 0 order by CAT_CL_CODIGO ", Array As String(q_buscar)) + ListView1.Clear + lfila.text = "Nombre y Calle" + Subs.SetDivider(ListView1, Colors.LightGray, 2) + If c2.RowCount>0 Then + For i=0 To c2.RowCount -1 + c2.Position=i + Dim label1 As Label + label1 = ListView1.TwoLinesLayout.Label + label1.TextSize = 15 + label1.TextColor = Colors.Black + Dim label2 As Label + label2 = ListView1.TwoLinesLayout.SecondLabel + label2.TextSize = 15 + label2.TextColor = Colors.Black + ListView1.AddTwoLines(c2.GetString("CAT_CL_CODIGO"), c2.GetString("CAT_CL_NOMBRE") &" CALLE: "& c2.GetString("CAT_CL_CALLE")) + Next + End If + entro = "3" + c2.Close +End Sub + +'Regresa la distancia y tiempo de la ruta entre dos puntos, usa el API del projecto OSRM. (Parte de la funcionalidad OSRM) +'Para mas información ir a esta liga: +'http://project-osrm.org/docs/v5.24.0/api/?language=cURL#route-service +Sub distanciaEntreCoords(id As String, coords1 As String, coords2 As String) As ResumableSub 'ignore +' Sleep(1050) +' Private distanciaTotal As String = "0" +' Private tiempo As String = "0" +' Dim j As HttpJob +' j.Initialize("", Me) +' j.Download("https://router.project-osrm.org/route/v1/driving/"&coords1&";"&coords2&"?overview=false") +' Wait For (j) JobDone(j As HttpJob) +' If j.Success Then +' Dim jp As JSONParser +' jp.Initialize(j.GetString) +' Dim m As Map = jp.NextObject +' Log($"Respuesta: ${m.Get("code")}"$) +' If m.Get("code") = "Ok" Then +'' Log(m) +' Dim rutas As List = m.Get("routes") +' Dim rutas2 As Map = rutas.Get(0) +'' Log(rutas2) +'' Dim legs As List = rutas2.Get("legs") +'' Log(legs) +' distanciaTotal = rutas2.Get("distance") +' tiempo = rutas2.Get("duration") +' Log($"Distancia total: ${distanciaTotal}, Tiempo: ${tiempo}"$ ) +' End If +' Else +' Log("Error!") +' End If +' j.Release +' Private r As List +' r.Initialize +' r.Add(id) +' r.Add(distanciaTotal) +' r.Add(tiempo) +' Return r +End Sub + +'Regresa la distancia y tiempo estimado de la ruta del repartidor, utiliza el API del projecto OSRM +'para calcular la distancia y tiempo de la ruta de un mapa de coordenadas a visitar dado. (Parte de la funcionalidad OSRM) +Sub traeRutaDia(aVisitar As B4XOrderedMap) +' Private coordsInicio As String = $"${Starter.cedisLocation.Longitude},${Starter.cedisLocation.Latitude}"$ +' Log($"Coordenadas de inicio: ${Starter.cedisLocation.Longitude},${Starter.cedisLocation.Latitude}"$) +' Private rutaCompleta As String = coordsInicio +' Private preRuta As String = coordsInicio +' Private distanciaTotal, distanciaTotal0, tiempo0, tiempo As Double +' Private masDe100 As Boolean +' Private m4 As Map +' Private visitaActual As Int = 0 +' Private cuantosAntes As Int = 0 +' listaWayPoints.Initialize +' If aVisitar.Keys.Size > 98 Then 'Si los clientes a visitar son mas de 100 entonces hacemos 2 rutas, una inicial con pocas visitas (las que pasen de 100) y la final con el resto ... +' cuantosAntes = aVisitar.Keys.Size - 98 'Definimos de cuantos clientes va a ser la ruta inicial. +' preRuta = coordsInicio 'Ponemos las coordenadas de inicio (Las del CEDIS). +' rutaCompleta = "" +' masDe100 = True +' End If +' Log($"a visitar: ${aVisitar.Keys.Size}"$) +' For Each k As Object In aVisitar.Keys +' visitaActual = visitaActual + 1 +' m4 = aVisitar.Get(k) +'' Log($"visitaActual: ${visitaActual} - cuantosAntes: ${cuantosAntes}"$) +' If visitaActual < cuantosAntes + 2 Then 'Si estas coordenadas son de la ruta inicial las agregamos ... +' preRuta = preRuta & ";" & m4.Get("coords") +'' LogColor($"PreRuta - visitaActual: ${visitaActual} - coords: ${m4.Get("coords")}"$, Colors.Magenta) +' End If +' If visitaActual >= cuantosAntes + 2 Then 'Si estas coordenadas son de la ruta final las agregamos ... +' rutaCompleta = rutaCompleta & ";" & m4.Get("coords") +'' LogColor($"RutaCompleta - visitaActual: ${visitaActual} - coords: ${m4.Get("coords")} - testRuta Size: ${testRutaCompleta.size}"$, Colors.Green) +' End If +' Next +' rutaCompleta = rutaCompleta & ";" & coordsInicio 'Agregamos las coordenadas del CEDIS al final para que sea viaje ida y vuelta. +'' rutaCompleta = rutaCompleta & ";" & coordsInicio +' If rutaCompleta.StartsWith(";") Then rutaCompleta = rutaCompleta.SubString(1) 'Si las cooredenadas tienen ";" al principio se lo quitamos. +'' LogColor(preRuta, Colors.magenta) +'' LogColor(rutaCompleta, Colors.Green) +' ProgressDialogShow2("Calculando distancia y tiempo, un momento por favor.", False) +' Private tiempoVisitas As Double 'TIMEPO DE 4 MINUTOS PROMEDIO POR TIENDA ESTO SE CAMBIA SEGUN EL CLIENTE +' tiempoVisitas = aVisitar.Keys.Size * 4 * 60 'Aqui se calcula el tiempo que duran las visitas x 4 mins cada una en segundos. +' tiempo0 = 0 +' distanciaTotal0 = 0 +' If masDe100 Then 'Si son mas de 100, entonces primero calculamos la ruta inicial. +' Dim j0 As HttpJob +' j0.Initialize("trip0", Me) +' j0.Download("https://router.project-osrm.org/trip/v1/driving/"&preRuta&"?source=first&destination=last&roundtrip=false&geometries=geojson") +'' LogColor("https://router.project-osrm.org/trip/v1/driving/"&preRuta&"?source=first&destination=last&roundtrip=false&geometries=geojson", Colors.Magenta) +' Wait For (j0) JobDone(j0 As HttpJob) +' If j0.Success Then +' Dim jp0 As JSONParser +' jp0.Initialize(j0.GetString) +' Dim m0 As Map = jp0.NextObject +' If m0.Get("code") = "Ok" Then +' Dim puntos0 As List = m0.Get("waypoints") +' Private esteWayPoint0 As Map +' For p = 0 To puntos0.Size -1 +' esteWayPoint0 = puntos0.Get(p) +'' LogColor("WP:" & esteWayPoint0, Colors.magenta) +'' LogColor("WP: " & esteWayPoint0.Get("waypoint_index") & ", loc: " & esteWayPoint0.Get("location") & ", name: " & esteWayPoint0.Get("name"), Colors.Magenta) +' esteWayPoint0.Remove("hint") +' esteWayPoint0.Remove("distance") +' esteWayPoint0.Remove("trips_index") +' listaWayPoints.Add(esteWayPoint0) +'' LogColor("estewaypoint: "&esteWayPoint0, Colors.Magenta) +' Next +' Dim rutas0 As List = m0.Get("trips") +' Dim rutas20 As Map = rutas0.Get(0) +'' Dim geometry0 As Map = rutas20.Get("geometry") +'' Private coords0 As List = geometry0.Get("coordinates") +' distanciaTotal0 = rutas20.Get("distance") +' tiempo0 = rutas20.Get("duration") +' tiempo0 = ((tiempo0 * 2) ) 'Tiempo X 2 (es muy corto porque no toma encuenta el trafico). +' Log($"Distancia total ruta inicial: $1.1{distanciaTotal0/1000} kms, tiempo aprox: $1.1{tiempo0/60} mins. ($1.1{tiempo0/60/60} hrs)"$) +'' l_rutaInfo.Text = $"Distancia total: $1.1{distanciaTotal0/1000} kms, tiempo aprox: $1.1{tiempo0/60/60} hrs"$ +' End If +' Else +' Log("Error!") +' End If +' j0.Release +' End If +' +' Dim j As HttpJob +' j.Initialize("trip", Me) 'Calculamos el resto de la ruta. +' j.Download("https://router.project-osrm.org/trip/v1/driving/"&rutaCompleta&"?source=first&destination=last&roundtrip=false&geometries=geojson") +'' LogColor("https://router.project-osrm.org/trip/v1/driving/"&rutaCompleta&"?source=first&destination=last&roundtrip=false&geometries=geojson", Colors.Green) +' Wait For (j) JobDone(j As HttpJob) +' If j.Success Then +' Dim jp As JSONParser +' jp.Initialize(j.GetString) +' Dim m As Map = jp.NextObject +' If m.Get("code") = "Ok" Then +' Dim puntos As List = m.Get("waypoints") +' Private esteWayPoint As Map +' Dim twpi As Int +' For p = 0 To puntos.Size -1 +' esteWayPoint = puntos.Get(p) +'' LogColor("WP:" & esteWayPoint, Colors.green) +'' LogColor("WP: " & esteWayPoint.Get("waypoint_index") & ", loc: " & esteWayPoint.Get("location") & ", name: " & esteWayPoint.Get("name"), Colors.Green) +' esteWayPoint.Remove("hint") +' esteWayPoint.Remove("distance") +' esteWayPoint.Remove("trips_index") +' twpi = esteWayPoint.Get("waypoint_index") +' esteWayPoint.Remove("waypoint_index") +' esteWayPoint.Put("waypoint_index", (twpi + cuantosAntes + 2)) +' listaWayPoints.Add(esteWayPoint) +'' LogColor("estewaypoint: "&esteWayPoint, Colors.Green) +' Next +' Dim rutas As List = m.Get("trips") +' Dim rutas2 As Map = rutas.Get(0) +' distanciaTotal = rutas2.Get("distance") +' Log("distancia ruta 2:" & (distanciaTotal) & "|" & rutas2.Get("distance")) +' distanciaTotal = distanciaTotal + distanciaTotal0 +' tiempo = rutas2.Get("duration") +' tiempo = (((tiempo + tiempo0) * 2) + tiempoVisitas) 'Tiempo X 2 (es muy corto porque no toma encuenta el trafico) + tiempoVisitas. +' Log($"Distancia total: $1.1{distanciaTotal/1000} kms, tiempo aprox: $1.1{tiempo/60} mins. ($1.1{tiempo/60/60} hrs)"$) +' l_rutaInfo.Text = $"Distancia: $1.1{distanciaTotal/1000} kms, tiempo aprox: $1.1{tiempo/60/60} hrs${CRLF}Visitas restantes: ${aVisitar.Keys.Size}"$ +' l_rutaInfo.Width = Root.Width * 0.9 +' Subs.centraEtiqueta(l_rutaInfo, Root.Width) +' l_rutaInfo.Visible = True +' l_rutaInfo.BringToFront +' ListView1.Top = lv1Top + 100 +' End If +' Else +' LogColor("**************** Error! ******************", Colors.red) +' End If +' j.Release +' ProgressDialogHide +'' LogColor("clientesMapaO size: " & clientesMapaO.Size & "|" & listaWayPoints.Size, Colors.Blue) +' Private r As Int = 1 +' Private r1, wps As Map +' Starter.skmt.ExecNonQuery("delete from waypoints") +' For Each k As Object In clientesMapaO.Keys 'Guardamos en la BD el orden de los waypoints para luego generar el listview. +' r1 = clientesMapaO.Get(k) +' r1.Get("codigo") +'' Log(listaWayPoints.Get(r) & "|" & r1.Get("coords") & "|" & r1.Get("calle")) +' wps = listaWayPoints.Get(r) +' Starter.skmt.ExecNonQuery2("insert into waypoints values (?,?)", Array As Object(r1.Get("codigo"), wps.get("waypoint_index"))) +' r = r + 1 +' Next +' ListView1.Clear +' Sleep(100) +' Dim label2 As Label +' label2 = ListView1.TwoLinesLayout.SecondLabel +' label2.TextSize = 15 +' label2.Height = 100dip +' ListView1.TwoLinesLayout.ItemHeight = 70dip +' Dim cs, cs2 As CSBuilder +' entro = 3 +' Log("Generamos ListView1 en traeRutaDia") +' 'Traemos las visitas restantes ordenadas por el indice de waypoints (este indice nos indica el orden en la ruta calculada). +' c=Starter.skmt.ExecQuery("select codigo, indice, CAT_CL_NOMBRE, CAT_CL_CALLE, CAT_CL_NOEXT from waypoints inner join kmt_info on waypoints.codigo = kmt_info.CAT_CL_CODIGO where gestion = 0 order by indice") +' If c.RowCount > 0 Then +' For i=0 To c.RowCount -1 'Generamos el listView con la lista ordenada. +' c.Position=i +' cs.Initialize +' cs2.Initialize +' ListView1.AddTwoLines(cs.Color(Colors.RGB(100,149,237)).Append(c.GetString("codigo")).PopAll, cs2.append(c.GetString("CAT_CL_NOMBRE")).Color(Colors.RGB(100,149,237)).Append(" Calle: ").Pop.Append(c.GetString("CAT_CL_CALLE").Trim & " " & c.GetString("CAT_CL_NOEXT")).PopAll ) +' Next +' End If +' c.Close +End Sub + +'Calcula distancia y tiempo de la ubicacion ACTUAL a las 8 primeras tiendas de la lista usando el API de OSRM. (Parte de la funcionalidad OSRM) +Private Sub b_GetDirs_Click + ProgressDialogShow("Calculando distancias y tiempos ...") + Private m2 As Map + Private f As Int = 0 + For Each k As Object In distOrderedMap.Keys 'Traemos la distancia y tiempo desde OSRM (2 puntos) + m2 = distOrderedMap.Get(k) + Private distancia2 As String = m2.Get("distancia") + Private thisLoc1 As String = m2.Get("ubicacion") +' Private locActual As String = Tracker.UUGCoords.Longitude&","&Tracker.UUGCoords.Latitude +' If locActual = "0,0" Then 'Si no tenemos ubicacion actual de GPS, buscamos la ultima guardada en la base de datos. +' c = Starter.skmt.ExecQuery("select * from hist_gps") +' If c.RowCount > 0 Then +' c.Position = 0 +'' locActual = c.GetString("hglon") & "," & c.GetString("hglat") +' End If +' c.Close +' End If + f = f+1 + If f < 8 Then +' If locActual = "0,0" Then 'Si todavia no tenemos ubicacion actual, entonces avisamos. +' ToastMessageShow("No se pudo obtener la ubicacion actual!!", True) +' f = 8 +' End If +' Log($"locActual: ${locActual}, thisLoc1: ${thisLoc1}"$) + Wait For(distanciaEntreCoords(distancia2, locActual, thisLoc1)) Complete (r As List) + LogColor($"R: ${r.Get(0)} - ${r.Get(1)} - ${r.Get(2)}"$, Colors.Green) + Private tId As Int = r.Get(0) + Private tMap As Map = distOrderedMap.Get(tId) + LogColor("|" & tId & "| - " &distOrderedMap.Get(tId), Colors.Blue) + Private tempNDD As String = tMap.Get("nomDirDist") + Private indexD As Int = tempNDD.IndexOf("Distancia:") + If indexD > -1 Then tempNDD = tempNDD.SubString2(0, indexD) + Log(tempNDD) + tempNDD = tempNDD & $"Dist: $1.1{(r.Get(1)/1000)} kms, Tiempo aprox: $1.0{((r.Get(2)*2)/60)} min."$ 'Multiplicamos el tiempo X 2 porque el tiempo estimado siempre es muy corto, X2 es mucho mas real con trafico. + Private esteCliente As Map = CreateMap("distancia": distancia2, "ubicacion": tMap.Get("ubicacion"), "codigo": tMap.Get("codigo"), "nomDirDist": tempNDD) + distOrderedMap.Put(tId, esteCliente) + ListView1.Clear + Private m3 As Map + For Each k As Object In distOrderedMap.Keys 'Generamos el listView con la lista ordenada. + m3 = distOrderedMap.Get(k) + m3.Get("codigo") + ListView1.AddTwoLines(m3.Get("codigo"), m3.Get("nomDirDist")) + Next + End If + Next + ProgressDialogHide +End Sub + +'Regresa un mapa (B4XOrderedMap) con todos los clientes que tiene que visitar el repartidor. (Parte de la funcionalidad OSRM) +Sub traeTodosAVisitar As B4XOrderedMap 'ignore +' Log("Iniciamos traeTodosAVisitar") +'' If Starter.waypointsOrdered.isInitialized Then Log(Starter.waypointsOrdered.Size) +'' Private rutaCompleta As String = "" +' Private thisLoc, ubicacionInicial As Location +' ubicacionInicial = Starter.cedisLocation +' LogColor(ubicacionInicial, Colors.Gray) +' c=Starter.skmt.ExecQuery("select sum(gestion) as hayVisitados from kmt_info") +' If c.RowCount > 0 Then +' c.Position = 0 +'' Log(c.GetString("hayVisitados")) +'' If c.GetString("hayVisitados") > 0 Then ubicacionInicial = Tracker.UUGCoords 'Si ya hay clientes visitados, entonces ya no estamos en el CEDIS y la ubicacion inicial debe de ser la ACTUAL. +' End If +' c.Close +' LogColor(ubicacionInicial, Colors.Red) +' thisLoc.Initialize +' clientesMapaO.Clear +' 'Traemos las rutas asignadas al repartidor. +' c=Starter.skmt.ExecQuery("select CAT_CL_RUTA, count(*) as cuantos from kmt_info where gestion = 0 group by CAT_CL_RUTA order by CAT_CL_RUTA asc") +' If c.RowCount>0 Then +' 'Traemos los clientes de cada ruta. +' For i=0 To c.RowCount -1 +' c.Position=i +'' Log($"Renglones ruta: ${c.RowCount} - i=${i} - Ruta: ${c.GetString("CAT_CL_RUTA")}"$) +' c2=Starter.skmt.ExecQuery2("select CAT_CL_NOMBRE, CAT_CL_CALLE, CAT_CL_CODIGO, CAT_CL_LAT, CAT_CL_LONG from kmt_info where CAT_CL_RUTA = ? and gestion = 0 order by CAT_CL_NOMBRE ", Array As String(c.GetString("CAT_CL_RUTA"))) +' If c2.RowCount>0 Then +' For j=0 To c2.RowCount -1 'Generamos lista de clientes +' c2.Position=j +'' Log($"Renglones clientes: ${c2.RowCount} - j=${j} - Ruta: ${c2.GetString("CAT_CL_CODIGO")}"$) +' thisLoc.Latitude = c2.GetString("CAT_CL_LAT") +' thisLoc.Longitude = c2.GetString("CAT_CL_LONG") +' If Not(thisLoc.Latitude = 0.0) And Not(thisLoc.Latitude = 0) Then 'Este IF es para que si las coordenadas no son válidas, entonces no las agregue al mapeo, porque el API de OSRM nos manda error. +' Private distancia As Int = ubicacionInicial.DistanceTo(thisLoc) 'Calculamos la distancia del cedis a la tienda. +' If clientesMapaO.ContainsKey(distancia) Then distancia = distancia + 1 'Si por alguna extraña razon hay dos tiendas a la misma distancia del CEDIS, le sumamos 1 para que sea diferente. +' Private esteCliente As Map = CreateMap("distancia": distancia, "ordenDist": j, "coords": c2.GetString("CAT_CL_LONG")&","&c2.GetString("CAT_CL_LAT"), "codigo": c2.GetString("CAT_CL_CODIGO"), "nombre": c2.GetString("CAT_CL_NOMBRE"), "calle": c2.GetString("CAT_CL_CALLE")) +' clientesMapaO.Put(distancia, esteCliente) +' Else +' ToastMessageShow("Hay tiendas SIN coordenadas, fueron excluidas!!", False) +' End If +'' Log($"${thisLoc}"$) +'' rutaCompleta = rutaCompleta & ";" & c2.GetString("CAT_CL_LONG")&","&c2.GetString("CAT_CL_LAT") +' Next +' End If +' Next +' End If +' clientesMapaO.Keys.Sort(True) 'Ordenamos la lista de clientes por distancia. +' c.Close +' c2.Close +' Log(c.RowCount & " rutas, " & clientesMapaO.Size & " clientes") +'' LogColor(rutaCompleta, Colors.Magenta) +'' Log(clientesMapaO) +' Return clientesMapaO +End Sub + +'Traemos la ruta de visitas via el API de OSRM usando el sub "traeRutaDia(traeTodosAVisitar)". +Private Sub b_getRutaInfo_Click + traeRutaDia(traeTodosAVisitar) +End Sub + +'Mostramos u ocultamos el boton para borrar los waypoints de la ruta. +Private Sub b_getRutaInfo_LongClick + If b_limpiarRuta.Visible Then + b_limpiarRuta.Visible = False + Else + b_limpiarRuta.Visible = True + End If +End Sub + +'Borramos los waypoints de la ruta. +Private Sub b_limpiarRuta_Click + Starter.skmt.ExecNonQuery("delete from waypoints") + b_limpiarRuta.Visible = False + B4XPage_Appear +End Sub \ No newline at end of file diff --git a/B4A/C_Principal.bas b/B4A/C_Principal.bas new file mode 100644 index 0000000..1445ac2 --- /dev/null +++ b/B4A/C_Principal.bas @@ -0,0 +1,278 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=12.2 +@EndOfDesignText@ +Sub Class_Globals + Private Root As B4XView 'ignore + Private xui As XUI 'ignore + Dim reqManager As DBRequestManager + Dim b_mapa As Button + Dim l_ruta As Label + Private inv As Button + Private p_principal As Panel + Dim ime As IME + Private et_placas As EditText + Private et_operador As EditText + Private et_rutaReparto As EditText + Private b_guardar As Button + Private ImageView1 As ImageView + Private ImageView1 As ImageView + Private p_datos As Panel + Private p_camara As Panel + Private b_cerrar As Button + Private pnlPreview As Panel + Private camEx As CameraExClass + + Private toast As BCToast + Private Capturing As Boolean + Private rp As RuntimePermissions + Private detector As JavaObject + Private camEx As CameraExClass + Private LastPreview As Long + Private IntervalBetweenPreviewsMs As Int = 100 + Dim codigoencontrado, codigoBuscado As String + Private b_escanRuta As Button + Private b_escanOperador As Button + Private b_escanPlacas As Button + Private et_kmsInicial As EditText + Private et_kmsFinal As EditText +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("principal") + reqManager.Initialize(Me, Starter.server) + B4XPages.MainPage.usuario=Subs.dameUsuarioDeDB + 'Inicia camara + p_camara.Width = Root.Width + p_camara.Height= Root.Height + p_camara.Visible = False + toast.Initialize(Root) + StopCamera + B4XPages.SetTitle(Me, "Barcode Example") + CreateDetector (Array("AZTEC", "CODE_128", "CODE_39", "CODE_93", "CODABAR", "DATA_MATRIX", "EAN_13", "EAN_8", "ITF", "PDF417", "QR_CODE", "UPC_A", "UPC_E")) + 'Termina camara +End Sub + +Sub B4XPage_Appear + Subs.centraPanel(p_principal, Root.Width) + +End Sub + +Sub JobDone(Job As HttpJob) +' Private r As DBResult = reqManager.HandleJob(Job) + If Job.Success = False Then + LogColor("** " & Job.Tag & " Error: " & Job.ErrorMessage, Colors.Red) ' Mod by CHV - 211023 + 'ToastMessageShow("Error: " & Job.ErrorMessage, True) + Else + LogColor("JobDone: '" & reqManager.HandleJob(Job).tag & "' - Registros: " & reqManager.HandleJob(Job).Rows.Size, Colors.Green) 'Mod por CHV - 211023 + If Job.JobName = "DBRequest" Then + Dim result As DBResult = reqManager.HandleJob(Job) + If result.Tag = "ins_rechazos" Then 'query tag + For Each records() As Object In result.Rows + For Each k As String In result.Columns.Keys + Log(k & ": " & records(result.Columns.Get(k))) + Next + Next + End If + End If + Job.Release + End If +End Sub + +Private Sub B4XPage_CloseRequest As ResumableSub + ' BACK key pressed + B4XPages.ShowPage("Login") + ' Returning False signals the system to handle the key + Return False +End Sub + +'Inicia camara + +Private Sub B4XPage_Disappear + If p_camara.Visible = True Then + p_camara.Visible = False + StopCamera + End If +End Sub + + +Sub btnStartStop_Click + If Capturing = False Then + p_camara.Visible = True + StartCamera + Else + p_camara.Visible = False + StopCamera + End If +End Sub + +Private Sub B_cerrar_Click +' If et_codigo.Text.Length = 0 Then +' p_camara.Visible = False +' Else +' p_camara.Visible = False +' et_codigo_EnterPressed +' End If + StopCamera + p_camara.Visible = False +End Sub + +Private Sub StopCamera +' et_codigo.Text = "" + Capturing = False + pnlPreview.Visible = False + If camEx.IsInitialized Then + camEx.Release + End If +End Sub + +Private Sub StartCameraShared + pnlPreview.Visible = True + Capturing = True +End Sub + +Private Sub FoundBarcode (msg As String) +' et_codigo.Text = msg + toast.Show($"Found [Color=Red][b][plain]${msg}[/plain][/b][/Color]"$) + Log(msg) + codigoencontrado = msg + Log($"${codigoencontrado}, ${codigoBuscado}"$) + If codigoBuscado = "placas" Then + et_placas.text = codigoencontrado + Else If codigoBuscado = "operador" Then + Log("ponemos operador en HOLA") + et_operador.text = codigoencontrado + Else If codigoBuscado = "ruta" Then + et_rutaReparto.text = codigoencontrado + End If +' If et_codigo.Text.Length > 1 Then + B_cerrar_Click +' End If +End Sub + +Private Sub StartCamera + rp.CheckAndRequest(rp.PERMISSION_CAMERA) + Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) + If Result = False Then + toast.Show("No permission!") + Return + End If + StartCameraShared + camEx.Initialize(pnlPreview, False, Me, "Camera1") + Wait For Camera1_Ready (Success As Boolean) + If Success Then + camEx.SetContinuousAutoFocus + camEx.CommitParameters + camEx.StartPreview + Else + toast.Show("Error opening camera") + StopCamera + End If +End Sub + +Private Sub CreateDetector (Codes As List) + Dim ctxt As JavaObject + ctxt.InitializeContext + Dim builder As JavaObject + builder.InitializeNewInstance("com/google/android/gms/vision/barcode/BarcodeDetector.Builder".Replace("/", "."), Array(ctxt)) + Dim barcodeClass As String = "com/google/android/gms/vision/barcode/Barcode".Replace("/", ".") + Dim barcodeStatic As JavaObject + barcodeStatic.InitializeStatic(barcodeClass) + Dim format As Int + For Each formatName As String In Codes + format = Bit.Or(format, barcodeStatic.GetField(formatName)) + Next + builder.RunMethod("setBarcodeFormats", Array(format)) + detector = builder.RunMethod("build", Null) + Dim operational As Boolean = detector.RunMethod("isOperational", Null) + If operational = False Then + toast.Show("Failed to create detector") + End If + b_escanOperador.Enabled = operational + b_escanPlacas.Enabled = operational + b_escanRuta.Enabled = operational +End Sub + +Private Sub Camera1_Preview (data() As Byte) + If DateTime.Now > LastPreview + IntervalBetweenPreviewsMs Then + 'Dim n As Long = DateTime.Now + Dim frameBuilder As JavaObject + Dim bb As JavaObject + bb = bb.InitializeStatic("java.nio.ByteBuffer").RunMethod("wrap", Array(data)) + frameBuilder.InitializeNewInstance("com/google/android/gms/vision/Frame.Builder".Replace("/", "."), Null) + Dim cs As CameraSize = camEx.GetPreviewSize + frameBuilder.RunMethod("setImageData", Array(bb, cs.Width, cs.Height, 842094169)) + Dim frame As JavaObject = frameBuilder.RunMethod("build", Null) + Dim SparseArray As JavaObject = detector.RunMethod("detect", Array(frame)) + LastPreview = DateTime.Now + Dim Matches As Int = SparseArray.RunMethod("size", Null) + If Matches > 0 Then + Dim barcode As JavaObject = SparseArray.RunMethod("valueAt", Array(0)) + Dim raw As String = barcode.GetField("rawValue") + FoundBarcode(raw) + End If + End If +End Sub + +'fin camara + +Private Sub b_guardar_Click + Starter.skmt.ExecNonQuery($"insert into CONTROL_KMS (PLACAS, OPERADOR, RUTA, KMS_INICIAL, KMS_FINAL) values ('${et_placas.text}', '${et_operador.text}', '${et_rutaReparto.text}', '${et_kmsInicial.text}', '${et_kmsFinal.text}')"$) +End Sub + +Private Sub pnlPreview_Click + +End Sub + +Private Sub p_camara_Click + +End Sub + +Private Sub b_escanPlacas_Click + ime.HideKeyboard + codigoBuscado = "placas" + Subs.panelVisible(p_camara, 0, 0) + If Capturing = False Then + p_camara.Visible = True + StartCamera + Else + p_camara.Visible = False + StopCamera + End If +End Sub + +Private Sub b_escanOperador_Click + ime.HideKeyboard + codigoBuscado = "operador" + Subs.panelVisible(p_camara, 0, 0) + If Capturing = False Then + p_camara.Visible = True + StartCamera + Else + p_camara.Visible = False + StopCamera + End If +End Sub + +Private Sub b_escanRuta_Click + ime.HideKeyboard + codigoBuscado = "ruta" + Subs.panelVisible(p_camara, 0, 0) + If Capturing = False Then + p_camara.Visible = True + StartCamera + Else + p_camara.Visible = False + StopCamera + End If +End Sub \ No newline at end of file diff --git a/B4A/C_UpdateAvailable.bas b/B4A/C_UpdateAvailable.bas new file mode 100644 index 0000000..62c83f8 --- /dev/null +++ b/B4A/C_UpdateAvailable.bas @@ -0,0 +1,74 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=11.5 +@EndOfDesignText@ +Sub Class_Globals + Private Root As B4XView 'ignore + Private xui As XUI 'ignore +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.Color = Colors.Transparent +End Sub + +Sub B4XPage_Appear + 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") +' ToastMessageShow("Descargando actualización", True) + End If + B4XPages.MainPage.ocultaProgreso + StartActivity(Main) +' Activity.Finish + B4XPages.ShowPage("Login") +End Sub + +Sub sinActualizacion + Msgbox(appUpdater.newApp.okMsg, "Aplicación al corriente") 'ignore +' StartActivity(Main) + B4XPages.MainPage.ocultaProgreso + B4XPages.ShowPage("Login") +End Sub \ No newline at end of file diff --git a/B4A/CameraExClass.bas b/B4A/CameraExClass.bas new file mode 100644 index 0000000..976371b --- /dev/null +++ b/B4A/CameraExClass.bas @@ -0,0 +1,414 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=7.01 +@EndOfDesignText@ +'Class module +'version 1.30 +'See this page for the list of constants: +'http://developer.android.com/intl/fr/reference/android/hardware/Camera.Parameters.html +'Note that you should use the constant values instead of the names. + +' Agregar a Main la siguientes lienas en Globals +' +' Type CameraInfoAndId (CameraInfo As Object, Id As Int) +' Type CameraSize (Width As Int, Height As Int) +' +' Agregar en main +' #AdditionalJar: com.google.android.gms:play-services-vision + +'Necesita las librerias XUI y XUI Views +' + +Sub Class_Globals + Private nativeCam As Object + Private cam As Camera + Private r As Reflector + Private target As Object + Private event As String + Public Front As Boolean + Private parameters As Object + + Public PreviewOrientation As Int +End Sub + +Public Sub Initialize (Panel1 As Panel, FrontCamera As Boolean, TargetModule As Object, EventName As String) + target = TargetModule + event = EventName + Front = FrontCamera + Dim id As Int + id = FindCamera(Front).id + If id = -1 Then + Front = Not(Front) 'try different camera + id = FindCamera(Front).id + If id = -1 Then + ToastMessageShow("No camera found.", True) + Return + End If + End If + cam.Initialize2(Panel1, "camera", id) +End Sub + +Private Sub FindCamera (frontCamera As Boolean) As CameraInfoAndId + Dim ci As CameraInfoAndId + Dim cameraInfo As Object + Dim cameraValue As Int + Log("findCamera") + If frontCamera Then cameraValue = 1 Else cameraValue = 0 + cameraInfo = r.CreateObject("android.hardware.Camera$CameraInfo") + Dim numberOfCameras As Int = r.RunStaticMethod("android.hardware.Camera", "getNumberOfCameras", Null, Null) + Log(r.target) + Log(numberOfCameras) + For i = 0 To numberOfCameras - 1 + r.RunStaticMethod("android.hardware.Camera", "getCameraInfo", Array As Object(i, cameraInfo), _ + Array As String("java.lang.int", "android.hardware.Camera$CameraInfo")) + r.target = cameraInfo + Log("facing: " & r.GetField("facing") & ", " & cameraValue) + If r.GetField("facing") = cameraValue Then 'ignore + ci.cameraInfo = r.target + ci.Id = i + Return ci + End If + Next + ci.id = -1 + Return ci +End Sub + +Private Sub SetDisplayOrientation + r.target = r.GetActivity + r.target = r.RunMethod("getWindowManager") + r.target = r.RunMethod("getDefaultDisplay") + r.target = r.RunMethod("getRotation") + Dim result, degrees As Int = r.target * 90 + Dim ci As CameraInfoAndId = FindCamera(Front) + r.target = ci.CameraInfo + Dim orientation As Int = r.GetField("orientation") + If Front Then + PreviewOrientation = (orientation + degrees) Mod 360 + result = PreviewOrientation + PreviewOrientation = (360 - PreviewOrientation) Mod 360 + Else + PreviewOrientation = (orientation - degrees + 360) Mod 360 + result = PreviewOrientation + Log("Preview Orientation: " & PreviewOrientation) + End If + r.target = nativeCam + r.RunMethod2("setDisplayOrientation", PreviewOrientation, "java.lang.int") + r.target = parameters + r.RunMethod2("setRotation", result, "java.lang.int") + CommitParameters +End Sub + +Private Sub Camera_Ready (Success As Boolean) + If Success Then + r.target = cam + nativeCam = r.GetField("camera") + r.target = nativeCam + parameters = r.RunMethod("getParameters") + SetDisplayOrientation + Else + Log("success = false, " & LastException) + End If + CallSub2(target, event & "_ready", Success) +End Sub +'Uncomment this sub if you need to handle the Preview event +Sub Camera_Preview (Data() As Byte) + If SubExists(target, event & "_preview") Then + CallSub2(target, event & "_preview", Data) + End If +End Sub + +Public Sub TakePicture + cam.TakePicture +End Sub + +Private Sub Camera_PictureTaken (Data() As Byte) + CallSub2(target, event & "_PictureTaken", Data) +End Sub + +Public Sub StartPreview + cam.StartPreview +End Sub + +Public Sub StopPreview + cam.StopPreview +End Sub + +Public Sub Release + cam.Release +End Sub + +'Saves the data received from PictureTaken event +Public Sub SavePictureToFile(Data() As Byte, Dir As String, FileName As String) + Dim out As OutputStream = File.OpenOutput(Dir, FileName, False) + out.WriteBytes(Data, 0, Data.Length) + out.Close +End Sub + +Public Sub SetParameter(Key As String, Value As String) + r.target = parameters + r.RunMethod3("set", Key, "java.lang.String", Value, "java.lang.String") +End Sub + +Public Sub GetParameter(Key As String) As String + r.target = parameters + Return r.RunMethod2("get", Key, "java.lang.String") +End Sub + +Public Sub CommitParameters + 'Try + r.target = nativeCam + r.RunMethod4("setParameters", Array As Object(parameters), Array As String("android.hardware.Camera$Parameters")) + 'Catch + ' ToastMessageShow("Error setting parameters.", True) + ' Log(LastException) + ' End Try +End Sub + +Public Sub GetColorEffect As String + Return GetParameter("effect") +End Sub + +Public Sub SetColorEffect(Effect As String) + SetParameter("effect", Effect) +End Sub + +Public Sub GetSupportedPreviewSizes As CameraSize() + r.target = parameters + Dim list1 As List = r.RunMethod("getSupportedPreviewSizes") + Dim cs(list1.Size) As CameraSize + For i = 0 To list1.Size - 1 + r.target = list1.get(i) + cs(i).Width = r.GetField("width") + cs(i).Height = r.GetField("height") + Next + Return cs +End Sub + +Public Sub SetPreviewSize(Width As Int, Height As Int) + r.target = parameters + r.RunMethod3("setPreviewSize", Width, "java.lang.int", Height, "java.lang.int") +End Sub +Public Sub GetSupportedPicturesSizes As CameraSize() + r.target = parameters + Dim list1 As List = r.RunMethod("getSupportedPictureSizes") + Dim cs(list1.Size) As CameraSize + For i = 0 To list1.Size - 1 + r.target = list1.get(i) + cs(i).Width = r.GetField("width") + cs(i).Height = r.GetField("height") + Next + Return cs +End Sub + +Public Sub SetPictureSize(Width As Int, Height As Int) + r.target = parameters + r.RunMethod3("setPictureSize", Width, "java.lang.int", Height, "java.lang.int") +End Sub + +Public Sub SetJpegQuality(Quality As Int) + r.target = parameters + r.RunMethod2("setJpegQuality", Quality, "java.lang.int") +End Sub + +Public Sub SetFlashMode(Mode As String) + r.target = parameters + r.RunMethod2("setFlashMode", Mode, "java.lang.String") +End Sub + +Public Sub GetFlashMode As String + r.target = parameters + Return r.RunMethod("getFlashMode") +End Sub + +Public Sub GetSupportedFlashModes As List + r.target = parameters + Return r.RunMethod("getSupportedFlashModes") +End Sub + +Public Sub GetSupportedColorEffects As List + r.target = parameters + Return r.RunMethod("getSupportedColorEffects") +End Sub + +'Returns a list with the supported preview fps. Each item in the list is an array of two ints (minimum value and maximum value). +Public Sub GetSupportedPreviewFpsRange As List + r.target = parameters + Return r.RunMethod("getSupportedPreviewFpsRange") +End Sub +'Returns the current preview fps range. +'Range is a two elements array. The minimum value and maximum value will be stored in this array. +Public Sub GetPreviewFpsRange(Range() As Int) + r.target = parameters + r.RunMethod4("getPreviewFpsRange", Array As Object(Range), Array As String("[I")) +End Sub + +Public Sub SetPreviewFpsRange(MinValue As Int, MaxValue As Int) + r.target = parameters + r.RunMethod4("setPreviewFpsRange", Array As Object(MinValue, MaxValue), _ + Array As String("java.lang.int", "java.lang.int")) +End Sub + +Public Sub GetPreviewSize As CameraSize + r.target = parameters + r.target = r.RunMethod("getPreviewSize") + Dim cs As CameraSize + cs.Width = r.GetField("width") + cs.Height = r.GetField("height") + Return cs +End Sub + +Public Sub GetPictureSize As CameraSize + r.target = parameters + r.target = r.RunMethod("getPictureSize") + Dim cs As CameraSize + cs.Width = r.GetField("width") + cs.Height = r.GetField("height") + Return cs +End Sub + +'Converts a preview image formatted in YUV format to JPEG. +'Note that you should not save every preview image as it will slow down the whole process. +Public Sub PreviewImageToJpeg(data() As Byte, quality As Int) As Byte() + Dim size, previewFormat As Object + r.target = parameters + size = r.RunMethod("getPreviewSize") + previewFormat = r.RunMethod("getPreviewFormat") + r.target = size + Dim width = r.GetField("width"), height = r.GetField("height") As Int + Dim yuvImage As Object = r.CreateObject2("android.graphics.YuvImage", _ + Array As Object(data, previewFormat, width, height, Null), _ + Array As String("[B", "java.lang.int", "java.lang.int", "java.lang.int", "[I")) + r.target = yuvImage + Dim rect1 As Rect + rect1.Initialize(0, 0, r.RunMethod("getWidth"), r.RunMethod("getHeight")) + Dim out As OutputStream + out.InitializeToBytesArray(100) + r.RunMethod4("compressToJpeg", Array As Object(rect1, quality, out), _ + Array As String("android.graphics.Rect", "java.lang.int", "java.io.OutputStream")) + + Return out.ToBytesArray +End Sub + +Public Sub GetSupportedFocusModes As List + r.target = parameters + Return r.RunMethod("getSupportedFocusModes") +End Sub + +Public Sub SetContinuousAutoFocus + Dim modes As List = GetSupportedFocusModes + If modes.IndexOf("continuous-picture") > -1 Then + SetFocusMode("continuous-picture") + Else If modes.IndexOf("continuous-video") > -1 Then + SetFocusMode("continuous-video") + Else + Log("Continuous focus mode is not available") + End If +End Sub + +Public Sub SetFocusMode(Mode As String) + r.target = parameters + r.RunMethod2("setFocusMode", Mode, "java.lang.String") +End Sub + +Public Sub GetFocusDistances As Float() + Dim F(3) As Float + r.target = parameters + r.RunMethod4("getFocusDistances", Array As Object(F), Array As String("[F")) + Return F +End Sub + +Public Sub GetSupportedPictureFormats As List + r.target = parameters + Return r.RunMethod("getSupportedPictureFormats") +End Sub +'This method should only be called if you need to immediately release the camera. +'For example if you need to start another application that depends on the camera. +Public Sub CloseNow + cam.Release + r.target = cam + r.RunMethod2("releaseCameras", True, "java.lang.boolean") +End Sub +'Calls AutoFocus and then takes the picture if focus was successfull. +Public Sub FocusAndTakePicture + cam.AutoFocus +End Sub + + +Private Sub Camera_FocusDone (Success As Boolean) + If Success Then + Sleep(100) + TakePicture + Else + Log("AutoFocus error.") + End If +End Sub + +Public Sub IsZoomSupported As Boolean + r.target = parameters + Return r.RunMethod("isZoomSupported") +End Sub + +Public Sub GetMaxZoom As Int + r.target = parameters + Return r.RunMethod("getMaxZoom") +End Sub + +Public Sub getZoom() As Int + r.target = parameters + Return r.RunMethod("getZoom") +End Sub + +Public Sub setZoom(ZoomValue As Int) + r.target = parameters + r.RunMethod2("setZoom", ZoomValue, "java.lang.int") +End Sub + +Public Sub getExposureCompensation As Int + r.target = parameters + Return r.RunMethod("getExposureCompensation") +End Sub + +Public Sub setExposureCompensation(v As Int) + r.target = parameters + r.RunMethod2("setExposureCompensation", v, "java.lang.int") +End Sub + +Public Sub getMinExposureCompensation As Int + r.target = parameters + Return r.RunMethod("getMinExposureCompensation") +End Sub + +Public Sub getMaxExposureCompensation As Int + r.target = parameters + Return r.RunMethod("getMaxExposureCompensation") +End Sub + +Public Sub SetFaceDetectionListener + Dim jo As JavaObject = nativeCam + Dim e As Object = jo.CreateEvent("android.hardware.Camera.FaceDetectionListener", "FaceDetection", Null) + jo.RunMethod("setFaceDetectionListener", Array(e)) +End Sub + +Private Sub FaceDetection_Event (MethodName As String, Args() As Object) As Object + Dim faces() As Object = Args(0) + For Each f As Object In faces + Dim jo As JavaObject = f + Dim faceRect As Rect = jo.GetField("rect") 'ignore + Next + Return Null +End Sub + + + +Public Sub StartFaceDetection + Dim jo As JavaObject = nativeCam + jo.RunMethod("startFaceDetection", Null) +End Sub + +Public Sub StopFaceDetection + Dim jo As JavaObject = nativeCam + jo.RunMethod("stopFaceDetection", Null) +End Sub + diff --git a/B4A/DBRequestManager.bas b/B4A/DBRequestManager.bas new file mode 100644 index 0000000..b3d83a1 --- /dev/null +++ b/B4A/DBRequestManager.bas @@ -0,0 +1,272 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=7.01 +@EndOfDesignText@ +'Class module +Sub Class_Globals + Private mTarget As Object + Type DBResult (Tag As Object, Columns As Map, Rows As List) + Type DBCommand (Name As String, Parameters() As Object) + Private link As String + Private bc As ByteConverter + Private T_NULL = 0, T_STRING = 1, T_SHORT = 2, T_INT = 3, T_LONG = 4, T_FLOAT = 5 _ + ,T_DOUBLE = 6, T_BOOLEAN = 7, T_BLOB = 8 As Byte + Private VERSION As Float = 0.9 + Private tempArray(1) As Object + Dim jobTagAnterior As String = "" 'Mod por CHV - 211023 +End Sub + +'Target - The module that handles JobDone (usually Me). +'ConnectorLink - URL of the Java server. +Public Sub Initialize (Target As Object, ConnectorLink As String) + mTarget = Target + link = ConnectorLink +End Sub + +'Sends a query request. +'Command - Query name and parameters. +'Limit - Maximum rows to return or 0 for no limit. +'Tag - An object that will be returned in the result. +Public Sub ExecuteQuery(Command As DBCommand, Limit As Int, Tag As Object) + Dim j As HttpJob + Dim ms As OutputStream + Dim out2 As OutputStream = StartJob(j,ms, Tag) + + WriteObject(Command.Name, out2) + WriteInt(Limit, out2) + WriteList(Command.Parameters, out2) + out2.Close + j.PostBytes(link & "?method=query", ms.ToBytesArray) +End Sub + +'Executes a batch of (non-select) commands. +'ListOfCommands - List of the commands that will be executes. +'Tag - An object that will be returned in the result. +Public Sub ExecuteBatch(ListOfCommands As List, Tag As Object) + Dim j As HttpJob + Dim ms As OutputStream + Dim out2 As OutputStream = StartJob(j,ms, Tag) + WriteInt(ListOfCommands.Size, out2) + For Each Command As DBCommand In ListOfCommands + WriteObject(Command.Name, out2) + WriteList(Command.Parameters, out2) + Next + out2.Close + j.PostBytes(link & "?method=batch", ms.ToBytesArray) +End Sub + +'Similar to ExecuteBatch. Sends a single command. +Public Sub ExecuteCommand(Command As DBCommand, Tag As Object) + ExecuteBatch(Array As DBCommand(Command), Tag) +End Sub + +Private Sub StartJob(j As HttpJob, MemoryStream As OutputStream, Tag As Object) As OutputStream + j.Initialize("DBRequest", mTarget) + j.Tag = Tag + MemoryStream.InitializeToBytesArray(0) + Dim compress As CompressedStreams + Dim out As OutputStream = compress.WrapOutputStream(MemoryStream, "gzip") + WriteObject(VERSION, out) + Return out +End Sub + +Private Sub WriteList(Parameters As List, out As OutputStream) + Dim data() As Byte + If Parameters = Null Or Parameters.IsInitialized = False Then + Dim Parameters As List + Parameters.Initialize + End If + data = bc.IntsToBytes(Array As Int(Parameters.Size)) + out.WriteBytes(data, 0, data.Length) + For Each o As Object In Parameters + WriteObject(o, out) + Next +End Sub + +Private Sub WriteObject(o As Object, out As OutputStream) + Dim data() As Byte + tempArray(0) = o + If tempArray(0) = Null Then + out.WriteBytes(Array As Byte(T_NULL), 0, 1) + Else If tempArray(0) Is Short Then + out.WriteBytes(Array As Byte(T_SHORT), 0, 1) + data = bc.ShortsToBytes(Array As Short(o)) + Else If tempArray(0) Is Int Then + out.WriteBytes(Array As Byte(T_INT), 0, 1) + data = bc.IntsToBytes(Array As Int(o)) + Else If tempArray(0) Is Float Then + out.WriteBytes(Array As Byte(T_FLOAT), 0, 1) + data = bc.FloatsToBytes(Array As Float(o)) + Else If tempArray(0) Is Double Then + out.WriteBytes(Array As Byte(T_DOUBLE), 0, 1) + data = bc.DoublesToBytes(Array As Double(o)) + Else If tempArray(0) Is Long Then + out.WriteBytes(Array As Byte(T_LONG), 0, 1) + data = bc.LongsToBytes(Array As Long(o)) + Else If tempArray(0) Is Boolean Then + out.WriteBytes(Array As Byte(T_BOOLEAN), 0, 1) + Dim b As Boolean = 0 + Dim data(1) As Byte + If b Then data(0) = 1 Else data(0) = 0 + Else If GetType(tempArray(0)) = "[B" Then + data = o + out.WriteBytes(Array As Byte(T_BLOB), 0, 1) + WriteInt(data.Length, out) + Else 'If o Is String Then (treat all other values as string) + out.WriteBytes(Array As Byte(T_STRING), 0, 1) + data = bc.StringToBytes(o, "UTF8") + WriteInt(data.Length, out) + End If + If data.Length > 0 Then out.WriteBytes(data, 0, data.Length) +End Sub + +Private Sub ReadObject(In As InputStream) As Object + Dim data(1) As Byte + In.ReadBytes(data, 0, 1) + Select data(0) + Case T_NULL + Return Null + Case T_SHORT + Dim data(2) As Byte + Return bc.ShortsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_INT + Dim data(4) As Byte + Return bc.IntsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_LONG + Dim data(8) As Byte + Return bc.LongsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_FLOAT + Dim data(4) As Byte + Return bc.FloatsFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_DOUBLE + Dim data(8) As Byte + Return bc.DoublesFromBytes(ReadBytesFully(In, data, data.Length))(0) + Case T_BOOLEAN + Dim b As Byte = ReadByte(In) + Return b = 1 + Case T_BLOB + Dim len As Int = ReadInt(In) + Dim data(len) As Byte + Return ReadBytesFully(In, data, data.Length) + Case Else + Dim len As Int = ReadInt(In) + Dim data(len) As Byte + ReadBytesFully(In, data, data.Length) + Return BytesToString(data, 0, data.Length, "UTF8") + End Select +End Sub + +Private Sub ReadBytesFully(In As InputStream, Data() As Byte, Len As Int) As Byte() + Dim count = 0, read As Int + Do While count < Len And read > -1 + read = In.ReadBytes(Data, count, Len - count) + count = count + read + Loop + Return Data +End Sub + +Private Sub WriteInt(i As Int, out As OutputStream) + Dim data() As Byte + data = bc.IntsToBytes(Array As Int(i)) + out.WriteBytes(data, 0, data.Length) +End Sub + +Private Sub ReadInt(In As InputStream) As Int + Dim data(4) As Byte + Return bc.IntsFromBytes(ReadBytesFully(In, data, data.Length))(0) +End Sub + +Private Sub ReadByte(In As InputStream) As Byte + Dim data(1) As Byte + In.ReadBytes(data, 0, 1) + Return data(0) +End Sub + +'Handles the Job result and returns a DBResult. +Public Sub HandleJob(Job As HttpJob) As DBResult +' Dim start As Long = DateTime.Now + Dim In As InputStream = Job.GetInputStream + Dim cs As CompressedStreams + In = cs.WrapInputStream(In, "gzip") + Dim serverVersion As Float = ReadObject(In) 'ignore + Dim method As String = ReadObject(In) + Dim table As DBResult + table.Initialize + table.Columns.Initialize + table.rows.Initialize + table.Tag = Job.Tag + If jobTagAnterior <> Job.Tag Then LogColor("HandleJob: '"&Job.Tag&"'", Colors.Blue) 'Mod por CHV - 211023 + jobTagAnterior = Job.Tag 'Mod por CHV - 211023 + If method = "query" Then + Dim numberOfColumns As Int = ReadInt(In) + For i = 0 To numberOfColumns - 1 + table.Columns.Put(ReadObject(In), i) + Next + Do While ReadByte(In) = 1 + Dim rowObjects(numberOfColumns) As Object + table.rows.Add(rowObjects) + For col = 0 To numberOfColumns - 1 + Dim o As Object = ReadObject(In) + rowObjects(col) = o + Next + Loop + Else If method = "batch" Then + table.Columns.Put("AffectedRows", 0) + Dim rows As Int = ReadInt(In) + For i = 0 To rows - 1 + table.rows.Add(Array As Object(ReadInt(In))) + Next + End If + In.Close + Return table +End Sub + +'Reads a file and returns the file as a bytes array. +Public Sub FileToBytes(Dir As String, FileName As String) As Byte() + Dim out As OutputStream + out.InitializeToBytesArray(0) + Dim In As InputStream = File.OpenInput(Dir, FileName) + File.Copy2(In, out) + out.Close + Return out.ToBytesArray +End Sub + +'Converts an image to a bytes array (for BLOB fields). +Public Sub ImageToBytes(Image As Bitmap) As Byte() + Dim out As OutputStream + out.InitializeToBytesArray(0) + Image.WriteToStream(out, 100, "JPEG") + out.Close + Return out.ToBytesArray +End Sub +'Converts a bytes array to an image (for BLOB fields). +Public Sub BytesToImage(bytes() As Byte) As Bitmap + Dim In As InputStream + In.InitializeFromBytesArray(bytes, 0, bytes.Length) + Dim bmp As Bitmap + bmp.Initialize2(In) + Return bmp +End Sub + +'Prints the table to the logs. +Public Sub PrintTable(Table As DBResult) + Log("Tag: " & Table.Tag & ", Columns: " & Table.Columns.Size & ", Rows: " & Table.Rows.Size) + Dim sb As StringBuilder + sb.Initialize + For Each col In Table.Columns.Keys + sb.Append(col).Append(TAB) + Next + Log(sb.ToString) + For Each row() As Object In Table.Rows + Dim sb As StringBuilder + sb.Initialize + For Each record As Object In row + sb.Append(record).Append(TAB) + Next + ToastMessageShow(sb.ToString, True) + Next +End Sub + + \ No newline at end of file diff --git a/B4A/Files/alert2.png b/B4A/Files/alert2.png new file mode 100644 index 0000000..44d3b7e Binary files /dev/null and b/B4A/Files/alert2.png differ diff --git a/B4A/Files/alerta.jpg b/B4A/Files/alerta.jpg new file mode 100644 index 0000000..5edc6ba Binary files /dev/null and b/B4A/Files/alerta.jpg differ diff --git a/B4A/Files/buscar.bal b/B4A/Files/buscar.bal new file mode 100644 index 0000000..afb40f4 Binary files /dev/null and b/B4A/Files/buscar.bal differ diff --git a/B4A/Files/cliente.bal b/B4A/Files/cliente.bal new file mode 100644 index 0000000..8806a17 Binary files /dev/null and b/B4A/Files/cliente.bal differ diff --git a/B4A/Files/clientes.bal b/B4A/Files/clientes.bal new file mode 100644 index 0000000..0434eaa Binary files /dev/null and b/B4A/Files/clientes.bal differ diff --git a/B4A/Files/dbc.png b/B4A/Files/dbc.png new file mode 100644 index 0000000..1519c8c Binary files /dev/null and b/B4A/Files/dbc.png differ diff --git a/B4A/Files/detalle_promo.bal b/B4A/Files/detalle_promo.bal new file mode 100644 index 0000000..14ef3fb Binary files /dev/null and b/B4A/Files/detalle_promo.bal differ diff --git a/B4A/Files/detalleventa.bal b/B4A/Files/detalleventa.bal new file mode 100644 index 0000000..929cd75 Binary files /dev/null and b/B4A/Files/detalleventa.bal differ diff --git a/B4A/Files/durakelo1.png b/B4A/Files/durakelo1.png new file mode 100644 index 0000000..00cb434 Binary files /dev/null and b/B4A/Files/durakelo1.png differ diff --git a/B4A/Files/engrane.jpg b/B4A/Files/engrane.jpg new file mode 100644 index 0000000..01159de Binary files /dev/null and b/B4A/Files/engrane.jpg differ diff --git a/B4A/Files/fondo_kmt.jpg b/B4A/Files/fondo_kmt.jpg new file mode 100644 index 0000000..4055faf Binary files /dev/null and b/B4A/Files/fondo_kmt.jpg differ diff --git a/B4A/Files/foto.bal b/B4A/Files/foto.bal new file mode 100644 index 0000000..9cf56b7 Binary files /dev/null and b/B4A/Files/foto.bal differ diff --git a/B4A/Files/guardagestion.bal b/B4A/Files/guardagestion.bal new file mode 100644 index 0000000..41d52cf Binary files /dev/null and b/B4A/Files/guardagestion.bal differ diff --git a/B4A/Files/guna_viejo.png b/B4A/Files/guna_viejo.png new file mode 100644 index 0000000..a0c3190 Binary files /dev/null and b/B4A/Files/guna_viejo.png differ diff --git a/B4A/Files/guna_viejo2.png b/B4A/Files/guna_viejo2.png new file mode 100644 index 0000000..d937027 Binary files /dev/null and b/B4A/Files/guna_viejo2.png differ diff --git a/B4A/Files/historico.bal b/B4A/Files/historico.bal new file mode 100644 index 0000000..929cd75 Binary files /dev/null and b/B4A/Files/historico.bal differ diff --git a/B4A/Files/infonavit1.jpg b/B4A/Files/infonavit1.jpg new file mode 100644 index 0000000..b8cce4c Binary files /dev/null and b/B4A/Files/infonavit1.jpg differ diff --git a/B4A/Files/itembuttonblue.png b/B4A/Files/itembuttonblue.png new file mode 100644 index 0000000..af4dc0b Binary files /dev/null and b/B4A/Files/itembuttonblue.png differ diff --git a/B4A/Files/kelloggs.png b/B4A/Files/kelloggs.png new file mode 100644 index 0000000..4debf15 Binary files /dev/null and b/B4A/Files/kelloggs.png differ diff --git a/B4A/Files/keymon_logo.png b/B4A/Files/keymon_logo.png new file mode 100644 index 0000000..945e546 Binary files /dev/null and b/B4A/Files/keymon_logo.png differ diff --git a/B4A/Files/kmt.db b/B4A/Files/kmt.db new file mode 100644 index 0000000..346ba1a Binary files /dev/null and b/B4A/Files/kmt.db differ diff --git a/B4A/Files/kmt.dbx b/B4A/Files/kmt.dbx new file mode 100644 index 0000000..de16c89 Binary files /dev/null and b/B4A/Files/kmt.dbx differ diff --git a/B4A/Files/login.bal b/B4A/Files/login.bal new file mode 100644 index 0000000..add0b8f Binary files /dev/null and b/B4A/Files/login.bal differ diff --git a/B4A/Files/logo guna_192x192.png b/B4A/Files/logo guna_192x192.png new file mode 100644 index 0000000..4dcd00c Binary files /dev/null and b/B4A/Files/logo guna_192x192.png differ diff --git a/B4A/Files/logo sanfer.jpg b/B4A/Files/logo sanfer.jpg new file mode 100644 index 0000000..791fe4f Binary files /dev/null and b/B4A/Files/logo sanfer.jpg differ diff --git a/B4A/Files/logo_exitus1.jpg b/B4A/Files/logo_exitus1.jpg new file mode 100644 index 0000000..b8cce4c Binary files /dev/null and b/B4A/Files/logo_exitus1.jpg differ diff --git a/B4A/Files/logo_mariana.jpg b/B4A/Files/logo_mariana.jpg new file mode 100644 index 0000000..8803ba9 Binary files /dev/null and b/B4A/Files/logo_mariana.jpg differ diff --git a/B4A/Files/mainpage.bal b/B4A/Files/mainpage.bal new file mode 100644 index 0000000..acba0d3 Binary files /dev/null and b/B4A/Files/mainpage.bal differ diff --git a/B4A/Files/malo.jpg b/B4A/Files/malo.jpg new file mode 100644 index 0000000..bbf3c87 Binary files /dev/null and b/B4A/Files/malo.jpg differ diff --git a/B4A/Files/mapa.bal b/B4A/Files/mapa.bal new file mode 100644 index 0000000..d9624ae Binary files /dev/null and b/B4A/Files/mapa.bal differ diff --git a/B4A/Files/mapa_cliente.bal b/B4A/Files/mapa_cliente.bal new file mode 100644 index 0000000..f8fc4a2 Binary files /dev/null and b/B4A/Files/mapa_cliente.bal differ diff --git a/B4A/Files/mapa_rutas.bal b/B4A/Files/mapa_rutas.bal new file mode 100644 index 0000000..dfcb856 Binary files /dev/null and b/B4A/Files/mapa_rutas.bal differ diff --git a/B4A/Files/mariana_logo_192x192.jpg b/B4A/Files/mariana_logo_192x192.jpg new file mode 100644 index 0000000..73ab234 Binary files /dev/null and b/B4A/Files/mariana_logo_192x192.jpg differ diff --git a/B4A/Files/no_venta.bal b/B4A/Files/no_venta.bal new file mode 100644 index 0000000..216c095 Binary files /dev/null and b/B4A/Files/no_venta.bal differ diff --git a/B4A/Files/nuevocliente.bal b/B4A/Files/nuevocliente.bal new file mode 100644 index 0000000..584381c Binary files /dev/null and b/B4A/Files/nuevocliente.bal differ diff --git a/B4A/Files/pedido.bal b/B4A/Files/pedido.bal new file mode 100644 index 0000000..defff34 Binary files /dev/null and b/B4A/Files/pedido.bal differ diff --git a/B4A/Files/planfia_logo.png b/B4A/Files/planfia_logo.png new file mode 100644 index 0000000..680ffd0 Binary files /dev/null and b/B4A/Files/planfia_logo.png differ diff --git a/B4A/Files/planfia_logo_old.png b/B4A/Files/planfia_logo_old.png new file mode 100644 index 0000000..4adb130 Binary files /dev/null and b/B4A/Files/planfia_logo_old.png differ diff --git a/B4A/Files/planfia_logo_old2.png b/B4A/Files/planfia_logo_old2.png new file mode 100644 index 0000000..316f337 Binary files /dev/null and b/B4A/Files/planfia_logo_old2.png differ diff --git a/B4A/Files/principal.bal b/B4A/Files/principal.bal new file mode 100644 index 0000000..770b979 Binary files /dev/null and b/B4A/Files/principal.bal differ diff --git a/B4A/Files/proditem.bal b/B4A/Files/proditem.bal new file mode 100644 index 0000000..210f3ed Binary files /dev/null and b/B4A/Files/proditem.bal differ diff --git a/B4A/Files/productos.bal b/B4A/Files/productos.bal new file mode 100644 index 0000000..9e4df4a Binary files /dev/null and b/B4A/Files/productos.bal differ diff --git a/B4A/Files/profina.jpg b/B4A/Files/profina.jpg new file mode 100644 index 0000000..f092f0f Binary files /dev/null and b/B4A/Files/profina.jpg differ diff --git a/B4A/Files/profina.png b/B4A/Files/profina.png new file mode 100644 index 0000000..d307055 Binary files /dev/null and b/B4A/Files/profina.png differ diff --git a/B4A/Files/sync.png b/B4A/Files/sync.png new file mode 100644 index 0000000..ff7d32e Binary files /dev/null and b/B4A/Files/sync.png differ diff --git a/B4A/Files/tabulador.bal b/B4A/Files/tabulador.bal new file mode 100644 index 0000000..d4f90be Binary files /dev/null and b/B4A/Files/tabulador.bal differ diff --git a/B4A/Files/telefonos.bal b/B4A/Files/telefonos.bal new file mode 100644 index 0000000..7c1d382 Binary files /dev/null and b/B4A/Files/telefonos.bal differ diff --git a/B4A/Files/thumbs.db b/B4A/Files/thumbs.db new file mode 100644 index 0000000..49c9b96 Binary files /dev/null and b/B4A/Files/thumbs.db differ diff --git a/B4A/Guna_CK.b4a b/B4A/Guna_CK.b4a new file mode 100644 index 0000000..36280e4 --- /dev/null +++ b/B4A/Guna_CK.b4a @@ -0,0 +1,200 @@ +Build1=Default,guna_ck.keymon.lat,HU2_PUBLIC +File1=alert2.png +File10=engrane.jpg +File11=fondo_kmt.jpg +File12=foto.bal +File13=guardagestion.bal +File14=guna_viejo.png +File15=guna_viejo2.png +File16=historico.bal +File17=infonavit1.jpg +File18=itembuttonblue.png +File19=kelloggs.png +File2=alerta.jpg +File20=keymon_logo.png +File21=kmt.db +File22=kmt.dbx +File23=login.bal +File24=Logo Guna_192x192.png +File25=logo sanfer.jpg +File26=logo_exitus1.jpg +File27=logo_mariana.jpg +File28=MainPage.bal +File29=malo.jpg +File3=buscar.bal +File30=mapa.bal +File31=mapa_cliente.bal +File32=mapa_rutas.bal +File33=mariana_logo_192x192.jpg +File34=no_venta.bal +File35=nuevocliente.bal +File36=pedido.bal +File37=planfia_logo.png +File38=planfia_logo_old.png +File39=planfia_logo_old2.png +File4=cliente.bal +File40=principal.bal +File41=proditem.bal +File42=productos.bal +File43=profina.jpg +File44=PROFINA.png +File45=sync.png +File46=tabulador.bal +File47=telefonos.bal +File48=Thumbs.db +File5=clientes.bal +File6=dbc.png +File7=detalle_promo.bal +File8=detalleVenta.bal +File9=durakelo1.png +FileGroup1=Default Group +FileGroup10=Default Group +FileGroup11=Default Group +FileGroup12=Default Group +FileGroup13=Default Group +FileGroup14=Default Group +FileGroup15=Default Group +FileGroup16=Default Group +FileGroup17=Default Group +FileGroup18=Default Group +FileGroup19=Default Group +FileGroup2=Default Group +FileGroup20=Default Group +FileGroup21=Default Group +FileGroup22=Default Group +FileGroup23=Default Group +FileGroup24=Default Group +FileGroup25=Default Group +FileGroup26=Default Group +FileGroup27=Default Group +FileGroup28=Default Group +FileGroup29=Default Group +FileGroup3=Default Group +FileGroup30=Default Group +FileGroup31=Default Group +FileGroup32=Default Group +FileGroup33=Default Group +FileGroup34=Default Group +FileGroup35=Default Group +FileGroup36=Default Group +FileGroup37=Default Group +FileGroup38=Default Group +FileGroup39=Default Group +FileGroup4=Default Group +FileGroup40=Default Group +FileGroup41=Default Group +FileGroup42=Default Group +FileGroup43=Default Group +FileGroup44=Default Group +FileGroup45=Default Group +FileGroup46=Default Group +FileGroup47=Default Group +FileGroup48=Default Group +FileGroup5=Default Group +FileGroup6=Default Group +FileGroup7=Default Group +FileGroup8=Default Group +FileGroup9=Default Group +Group=Default Group +Library1=appupdating +Library10=phone +Library11=randomaccessfile +Library12=reflection +Library13=runtimepermissions +Library14=sql +Library15=xcustomlistview +Library16=xui +Library17=xui views +Library2=b4xpages +Library3=bctoast +Library4=byteconverter +Library5=camera +Library6=core +Library7=fileprovider +Library8=ime +Library9=okhttputils2 +ManifestCode='This code will be applied to the manifest file during compilation.~\n~'You do not need to modify it in most cases.~\n~'See this link for for more information: https://www.b4x.com/forum/showthread.php?p=78136~\n~AddManifestText(~\n~~\n~)~\n~SetApplicationAttribute(android:icon, "@drawable/icon")~\n~SetApplicationAttribute(android:label, "$LABEL$")~\n~CreateResourceFromFile(Macro, Themes.LightTheme)~\n~'End of default text.~\n~~\n~''''' CAMBIA LA CLAVE API~\n~'AddApplicationText(~\n~'~\n~' ~\n~')~\n~~\n~'CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)~\n~SetApplicationAttribute(android:usesCleartextTraffic, "true")~\n~'AddManifestText()~\n~'AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)~\n~'AddManifestText()~\n~'AddManifestText()~\n~'AddManifestText() 'in order to access the device non-resettable identifiers such as IMEI and serial number.~\n~'AddManifestText()~\n~'/////////////// FLP y FBMessageing MOD Inicia /////////////////////~\n~'CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)~\n~'CreateResourceFromFile(Macro, FirebaseAnalytics.Firebase)~\n~'CreateResourceFromFile(Macro, FirebaseAnalytics.FirebaseAnalytics)~\n~'CreateResourceFromFile(Macro, FirebaseNotifications.FirebaseNotifications)~\n~'SetServiceAttribute(Tracker, android:foregroundServiceType, "location")~\n~'/////////////// FLP y FBMessageing MOD Termina /////////////////////~\n~~\n~'Si al cargar un mapa de google mande este error "java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion". agregar la siguiente linea:~\n~AddApplicationText()~\n~~\n~'/////////////////////// App Updating ////////////////~\n~ AddManifestText(~\n~ )~\n~ AddApplicationText(~\n~ ~\n~ ~\n~ ~\n~ )~\n~ CreateResource(xml, provider_paths,~\n~ ~\n~ ~\n~ ~\n~ ~\n~ ~\n~ )~\n~AddManifestText()~\n~AddManifestText()~\n~AddManifestText()~\n~AddManifestText()~\n~~\n~AddPermission(android.permission.REQUEST_INSTALL_PACKAGES)~\n~AddPermission(android.permission.INTERNET)~\n~AddPermission(android.permission.INSTALL_PACKAGES)~\n~AddPermission(android.permission.READ_EXTERNAL_STORAGE)~\n~AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)~\n~AddPermission(android.permission.READ_PHONE_STATE)~\n~AddPermission(android.permission.WAKE_LOCK)~\n~CreateResourceFromFile(Macro, JhsIceZxing1.CaturePortrait)~\n~ ~\n~SetApplicationAttribute(android:largeHeap, "true")~\n~~\n~ +Module1=appUpdater +Module2=B4XMainPage +Module3=C_Clientes +Module4=C_Principal +Module5=C_UpdateAvailable +Module6=CameraExClass +Module7=DBRequestManager +Module8=Starter +Module9=Subs +NumberOfFiles=48 +NumberOfLibraries=17 +NumberOfModules=9 +Version=11.5 +@EndOfDesignText@ +#Region Project Attributes + #ApplicationLabel: Guna CK + #VersionCode: 1 + #VersionName: 3.06.28 + 'SupportedOrientations possible values: unspecified, landscape or portrait. + #SupportedOrientations: portrait + #CanInstallToExternalStorage: False + #AdditionalJar: com.android.support:support-v4 + #AdditionalJar: com.google.android.gms:play-services-location + #BridgeLogger: True + #AdditionalJar: com.google.android.gms:play-services-vision +#End Region + +#Region Activity Attributes + #FullScreen: False + #IncludeTitle: True +#End Region + +Sub Process_Globals + Public ActionBarHomeClicked As Boolean +End Sub + +Sub Globals + Type CameraInfoAndId (CameraInfo As Object, Id As Int) + Type CameraSize (Width As Int, Height As Int) +End Sub + +Sub Activity_Create(FirstTime As Boolean) + Dim pm As B4XPagesManager + pm.Initialize(Activity) +End Sub + +'Template version: B4A-1.01 +#Region Delegates + +Sub Activity_ActionBarHomeClick + ActionBarHomeClicked = True + B4XPages.Delegate.Activity_ActionBarHomeClick + ActionBarHomeClicked = False +End Sub + +Sub Activity_KeyPress (KeyCode As Int) As Boolean + Return B4XPages.Delegate.Activity_KeyPress(KeyCode) +End Sub + +Sub Activity_Resume + B4XPages.Delegate.Activity_Resume +End Sub + +Sub Activity_Pause (UserClosed As Boolean) + B4XPages.Delegate.Activity_Pause +End Sub + +Sub Activity_PermissionResult (Permission As String, Result As Boolean) + B4XPages.Delegate.Activity_PermissionResult(Permission, Result) +End Sub + +Sub Create_Menu (Menu As Object) + B4XPages.Delegate.Create_Menu(Menu) +End Sub + +#if Java +public boolean _onCreateOptionsMenu(android.view.Menu menu) { + processBA.raiseEvent(null, "create_menu", menu); + return true; +} +#End If +#End Region + +'Program code should go into B4XMainPage and other pages. \ No newline at end of file diff --git a/B4A/Guna_CK.b4a.meta b/B4A/Guna_CK.b4a.meta new file mode 100644 index 0000000..5988fdf --- /dev/null +++ b/B4A/Guna_CK.b4a.meta @@ -0,0 +1,33 @@ +ModuleBookmarks0= +ModuleBookmarks1= +ModuleBookmarks2= +ModuleBookmarks3= +ModuleBookmarks4= +ModuleBookmarks5= +ModuleBookmarks6= +ModuleBookmarks7= +ModuleBookmarks8= +ModuleBookmarks9= +ModuleBreakpoints0= +ModuleBreakpoints1= +ModuleBreakpoints2= +ModuleBreakpoints3= +ModuleBreakpoints4= +ModuleBreakpoints5= +ModuleBreakpoints6= +ModuleBreakpoints7= +ModuleBreakpoints8= +ModuleBreakpoints9= +ModuleClosedNodes0= +ModuleClosedNodes1= +ModuleClosedNodes2=2 +ModuleClosedNodes3=2 +ModuleClosedNodes4=1,5,7,8 +ModuleClosedNodes5= +ModuleClosedNodes6= +ModuleClosedNodes7= +ModuleClosedNodes8= +ModuleClosedNodes9= +NavigationStack=Subs,fechaKMT,27,0,Subs,Process_Globals,16,0,Starter,Service_Create,37,3,C_Principal,b_escanPlacas_Click,245,0,C_Principal,b_guardar_Click,224,6,C_Principal,Camera1_Preview,222,0,C_Principal,Class_Globals,0,0,C_Principal,Initialize,40,0,C_Principal,B4XPage_Created,48,0,C_Principal,B4XPage_Appear,62,0,C_Principal,B4XPage_CloseRequest,91,0 +SelectedBuild=0 +VisibleModules=2,8,4,9,6 diff --git a/B4A/Starter.bas b/B4A/Starter.bas new file mode 100644 index 0000000..814ecb4 --- /dev/null +++ b/B4A/Starter.bas @@ -0,0 +1,155 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Service +Version=9.85 +@EndOfDesignText@ +#Region Service Attributes + #StartAtBoot: False + #ExcludeFromLibrary: True +#End Region + +Sub Process_Globals + 'These global variables will be declared once when the application starts. + 'These variables can be accessed from all modules. + Public rp As RuntimePermissions +' Public FLP As FusedLocationProvider + Private flpStarted As Boolean + Dim skmt As SQL + Dim ruta As String +' Private BTAdmin As BluetoothAdmin + Public BluetoothState As Boolean + Dim Timer1 As Timer + Dim Interval As Int = 300 + 'Para WebSockets +' Dim monitor As Timer 'Lo usamos para monitorear los servicios Tracker y PushService +' Dim monitorTicks As Int = 0 + Dim trackerActividad As String = "501231235959" + Dim pushServiceActividad As String = "501231235959" + 'Para los Logs + Private logs As StringBuilder + Private logcat As LogCat + Public SharedFolder As String 'Para actualizar apk +' Dim cedisLocation As Location + Dim reqManager As DBRequestManager + Dim server As String = "http://187.189.244.154:1787" + Dim muestraProgreso = 0 +End Sub + +Sub Service_Create + 'This is the program entry point. + 'This is a good place to load resources that are not specific to a single activity. + ruta = File.DirInternal 'Ruta de la base de datos por defecto. +' If File.ExternalWritable Then ruta = rp.GetSafeDirDefaultExternal("") 'Si podemos escribir a la tarjeta, cambiamos la ruta. + If Not(File.Exists(ruta, "kmt.db")) Then File.Copy(File.DirAssets, "kmt.db", ruta, "kmt.db") 'Si no existe el archivo de la base de datos, lo copiamos. + Log(ruta) + Log(File.DirAssets) + skmt.Initialize(ruta,"kmt.db", True) +' CallSubDelayed(PushService, "SubscribeToTopics") +' CallSubDelayed(FirebaseMessaging, "SubscribeToTopics") +' BTAdmin.Initialize("admin") +' If BTAdmin.IsEnabled = False Then +' If BTAdmin.Enable = False Then +' ToastMessageShow("Error enabling Bluetooth adapter.", True) +' Else +' ToastMessageShow("Enabling Bluetooth adapter...", False) +' End If +' Else +' BluetoothState = True +' End If +' reqManager.Initialize(Me, Main.server) + Timer1.Initialize("Timer1", Interval * 1000) + Timer1.Enabled = True + SharedFolder = rp.GetSafeDirDefaultExternal("") +' cedisLocation.Initialize +' cedisLocation.Latitude = "19.48118148992086" +' cedisLocation.Longitude = "-99.15295579261536" +End Sub + +Sub Service_Start (StartingIntent As Intent) + Service.StopAutomaticForeground 'Starter service can start in the foreground state in some edge cases. +' StartService(PushService) +' monitor.Initialize("monitor", 30000) +' monitor.Enabled = True +End Sub + +Sub Service_TaskRemoved + 'This event will be raised when the user removes the app from the recent apps list. +End Sub + +'Return true to allow the OS default exceptions handler to handle the uncaught exception. +Sub Application_Error (Error As Exception, StackTrace As String) As Boolean + Return True +End Sub + +Sub Service_Destroy + +End Sub + +Private Sub Timer1_Tick +' ToastMessageShow("Timer",False) +' LogColor("Siguiente actualizacion " & DateTime.Time(DateTime.Now + Interval * 1000),Colors.Blue) + ENVIA_ULTIMA_GPS +End Sub + +Sub ENVIA_ULTIMA_GPS +' If IsConnectedToInternet Then +' Log("Con internet, enviamos UTR!") +' Dim skmt As SQL +' Dim cmd As DBCommand +' Dim reqManager As DBRequestManager +' reqManager.Initialize(Me, server) +'' LogColor($"ReqServer = ${server}"$, Colors.red) +' skmt.Initialize(ruta,"kmt.db", True) +'' Log("server: "&Main.server) +' skmt.Initialize(ruta,"kmt.db", True) +' If B4XPages.MainPage.logger Then LogColor("Iniciamos ENVIA_ULTIMA_GPS", Colors.red) +' DateTime.TimeFormat = "HHmmss" +' B4XPages.MainPage.ultimaActualizacionGPS = DateTime.Time(DateTime.Now) +' cmd.Initialize +' cmd.Name = "select_fechat" +' reqManager.ExecuteQuery(cmd , 0, "fechat") +' +' Dim cmd As DBCommand +' cmd.Initialize +' cmd.Name = "UPDATE_MARDS_ACTUALR3_GPS" +' cmd.Parameters = Array As Object(B4XPages.MainPage.montoActual, B4XPages.MainPage.clientestotal, B4XPages.MainPage.clientesventa, B4XPages.MainPage.clientesvisitados, B4XPages.MainPage.lat_gps, B4XPages.MainPage.lon_gps, B4XPages.MainPage.batt, B4XPages.MainPage.montoRechazado, B4XPages.MainPage.montoEntregado, B4XPages.MainPage.clientestotal, B4XPages.MainPage.porVisitar, B4XPages.MainPage.entregas, B4XPages.MainPage.rechazos, Application.VersionName, B4XPages.MainPage.ALMACEN, B4XPages.MainPage.rutapreventa ) +' If B4XPages.MainPage.logger Then Log($"montoActual: ${B4XPages.MainPage.montoActual}, cTotal: ${B4XPages.MainPage.clientestotal}, cVenta: ${B4XPages.MainPage.clientesventa}, cVisitados: ${B4XPages.MainPage.clientesvisitados}, ${B4XPages.MainPage.lat_gps}, ${B4XPages.MainPage.lon_gps}, Batt: ${B4XPages.MainPage.batt}, montoRechazado: ${B4XPages.MainPage.montoRechazado}, montoEntregado: ${B4XPages.MainPage.montoEntregado}, porVisitar: ${B4XPages.MainPage.porVisitar}, entregas: ${B4XPages.MainPage.entregas}, rechazos: ${B4XPages.MainPage.rechazos}, Almacen: ${B4XPages.MainPage.ALMACEN}, Ruta: ${B4XPages.MainPage.rutapreventa}"$) +' +' reqManager.ExecuteCommand(cmd, "inst_visitas") +' skmt.ExecNonQuery2("Update cat_variables set CAT_VA_VALOR = ? WHERE CAT_VA_DESCRIPCION = ?" , Array As String(DateTime.Time(DateTime.Now),"HoraIngreso")) +' +' 'Reiniciamos el timer para cuando llamamos el Sub desde otra actividad +' Timer1.Enabled = False +' Timer1.Interval = Interval * 1000 +' Timer1.Enabled = True +' Else +' Log("Sin conexión a internet, no se envió UTR!") +' End If +End Sub + +Sub IsConnectedToInternet As Boolean 'ignore +' Dim r As Reflector +' r.Target = r.GetContext +' r.Target = r.RunMethod2("getSystemService", "connectivity", "java.lang.String") +' r.Target = r.RunMethod("getActiveNetworkInfo") +' If r.Target <> Null Then +' Return r.RunMethod("isConnectedOrConnecting") +' End If +' Return False +End Sub + +Sub JobDone(Job As HttpJob) +' LogColor("starter jobdone", Colors.Red) +' Log(Job.ErrorMessage) +' Private r As DBResult = reqManager.HandleJob(Job) + If Job.Success = False Then +' LogColor("** " & Job.Tag & " Error: " & Job.ErrorMessage, Colors.Red) ' Mod by CHV - 211023 + If Job.ErrorMessage.Contains("failed to connect") Or Job.ErrorMessage.Contains("Failed to connect") Then + ToastMessageShow("!Hubo un error contactando al servidor, por favor revise su conexión!", True) + End If + 'ToastMessageShow("Error: " & Job.ErrorMessage, True) + Else +' LogColor("JobDone: '" & reqManager.HandleJob(Job).tag & "' - Registros: " & reqManager.HandleJob(Job).Rows.Size, Colors.Green) 'Mod por CHV - 211023 + End If +End Sub \ No newline at end of file diff --git a/B4A/Subs.bas b/B4A/Subs.bas new file mode 100644 index 0000000..d4efd29 --- /dev/null +++ b/B4A/Subs.bas @@ -0,0 +1,228 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=StaticCode +Version=11 +@EndOfDesignText@ +'Code module +'Subs in this code module will be accessible from all modules. +Sub Process_Globals + 'These global variables will be declared once when the application starts. + 'These variables can be accessed from all modules. +' Public GZip As GZipStrings + Private su As StringUtils + Dim phn As Phone + Dim devModel As String + Dim kmt As SQL 'Requiere la libreria "SQL" +' Dim wifi As MLwifi + Dim ssid As String 'ignore + Dim rutaMaxPoints As Int = 3000 + Dim rutaHrsAtras As Int = 48 +' Dim rutaInicioHoy As String = "" +End Sub + +'Convierte una fecha al formato yyMMddHHmmss +Sub fechaKMT(fecha As String) As String 'ignore +' Log(fecha) + Dim OrigFormat As String = DateTime.DateFormat 'save orig date format + DateTime.DateFormat="yyMMddHHmmss" + Dim nuevaFecha As String=DateTime.Date(fecha) + DateTime.DateFormat=OrigFormat 'return to orig date format +' Log(nuevaFecha) + Return nuevaFecha +End Sub + +'Trae un string con hora, minutos y segundos - HHmmss +Sub hmsKMT As String 'ignore +' Log(fecha) + Dim OrigFormat As String = DateTime.DateFormat 'save orig date format + DateTime.DateFormat="HHmmss" + Private nuevaHora As String=DateTime.Date(DateTime.Now) + DateTime.DateFormat=OrigFormat 'return to orig date format +' Log(nuevaFecha) + Return nuevaHora +End Sub + +'Genera una notificacion con importancia alta +Sub notiHigh(title As String, body As String, activity As Object) 'ignore + Private notif As Notification + notif.Initialize2(notif.IMPORTANCE_HIGH) + notif.Icon = "icon" + notif.Vibrate = False + notif.Sound = False + notif.AutoCancel = True + Log("notiHigh: "&title) + notif.SetInfo(title, body, activity) +' Log("notiHigh SetInfo") + notif.Notify(777) +End Sub + +'Regresa el objeto de una notificacion con importancia baja +Sub notiLowReturn(title As String, Body As String, id As Int) As Notification 'ignore + Private notification As Notification + notification.Initialize2(notification.IMPORTANCE_LOW) + Log("notiLowReturn: "&title) + notification.Icon = "icon" + notification.Sound = False + notification.Vibrate = False + notification.SetInfo(title, Body, Main) + notification.Notify(id) +' Log("notiLowReturn SetInfo") + Return notification +End Sub + +'Revisa que exista la BD y si es necesario crea algunas tablas dentro de ella +Sub revisaBD 'ignore + If Not(File.Exists(Starter.ruta, "kmt.db")) Then File.Copy(File.DirAssets, "kmt.db", Starter.ruta, "kmt.db") + If Not(kmt.IsInitialized) Then kmt.Initialize(Starter.ruta, "kmt.db", True) +' kmt.ExecNonQuery("CREATE TABLE IF NOT EXISTS RUTA_GPS(FECHA INTEGER, LAT TEXT, LON TEXT)") +' kmt.ExecNonQuery("CREATE TABLE IF NOT EXISTS UUC(fecha INTEGER, lat TEXT, lon TEXT)") 'LastKnownLocation +' kmt.ExecNonQuery("CREATE TABLE IF NOT EXISTS bitacora(fecha INTEGER, texto TEXT)") 'Bitacora +End Sub + +'Regresa la fecha y hora de hoy a las 00:00 en el formato "yyMMddHHMMSS" +Sub fechaInicioHoy As String 'ignore + Dim OrigFormat As String = DateTime.DateFormat 'save orig date format + DateTime.DateFormat="yyMMdd" + Private h As String = DateTime.Date(DateTime.Now)&"000000" + DateTime.DateFormat=OrigFormat 'return to orig date format + Log("Hoy="&h) + Return h +End Sub + +'Regresa verdadero si ya pasaron XX minutos de la fecha dada +Sub masDeXXMins(hora As Int, mins As Int) As Boolean 'ignore + If (hora + mins * DateTime.TicksPerMinute) < DateTime.Now Then + Return True + Else + Return False + End If +End Sub + +'Regresa verdadero si ya pasaron XX minutos de la fechaKMT dada +Sub masDeXXMinsKMT(hora As String, mins As Int) As Boolean 'ignore + Try + ' LogColor($"Hora=${fechaKMT(fechaKMT2Ticks(hora) + mins * DateTime.TicksPerMinute)}, Mins=${mins}, Actual=${fechaKMT(DateTime.Now)}"$,Colors.red) + If fechaKMT2Ticks(hora) + mins * DateTime.TicksPerMinute < DateTime.Now Then +' Log("+++ +++ "&fechaKMT(fechaKMT2Ticks(hora) + mins * DateTime.TicksPerMinute) & " < " & fechaKMT(DateTime.Now)) + Return True + Else + ' Log("+++ +++ "&fechaKMT(fechaKMT2Ticks(hora) + mins * DateTime.TicksPerMinute) & " > " & fechaKMT(DateTime.Now)) + Return False + End If + Catch + Log(LastException) + End Try +End Sub + +'Convierte una fecha en formato YYMMDDHHMMSS a Ticks +Sub fechaKMT2Ticks(fKMT As String) As Long 'ignore + Try + If fKMT.Length = 12 Then + Private parteFecha As String = fKMT.SubString2(0,6) + Private parteHora As String = fKMT.SubString(6) + Private OrigFormat As String = DateTime.DateFormat 'save original date format + DateTime.DateFormat="yyMMdd" + DateTime.TimeFormat="HHmmss" + Private ticks As Long = DateTime.DateTimeParse(parteFecha,parteHora) +' Log(" +++ +++ pFecha:"&parteFecha&" | pHora:"&parteHora) + DateTime.DateFormat=OrigFormat 'return to original date format + Return ticks + Else + Log("Formato de fecha incorrecto, debe de ser 'YYMMDDHHMMSS', no '"&fKMT&"' largo="&fKMT.Length) + Return 0 + End If + Catch + Log(LastException) + LogColor($"Fecha dada: ${fKMT}, Parte Fecha: ${parteFecha}, Parte Hora: ${parteHora}"$, Colors.Red) + Return 0 + End Try +End Sub + +Sub InstallAPK(dir As String, apk As String) 'ignore + If File.Exists(dir, apk) Then + Dim i As Intent + i.Initialize(i.ACTION_VIEW, "file://" & File.Combine(dir, apk)) + i.SetType("application/vnd.android.package-archive") + StartActivity(i) + End If +End Sub + +'Hace visible el panel con los parametros "Top" y "Left" dados +Sub panelVisible(panel As Panel, top As Int, left As Int) 'ignore + panel.BringToFront + panel.Visible = True + panel.Top = top + panel.Left = left +End Sub + +'Saca el usuario de la tabla USUARIOA +Sub dameUsuarioDeDB As String 'ignore + Private c As Cursor + Private u As String = "SinUsuario" + If Not(kmt.IsInitialized) Then revisaBD + c=kmt.ExecQuery("select USUARIO from usuarioa") + c.Position=0 + If c.RowCount > 0 Then u = c.GetString("USUARIO") + c.Close + Return u +End Sub + +Sub SetDivider(lv As ListView, Color As Int, Height As Int) 'ignore + Dim r As Reflector + r.Target = lv + Dim CD As ColorDrawable + CD.Initialize(Color, 0) + r.RunMethod4("setDivider", Array As Object(CD), Array As String("android.graphics.drawable.Drawable")) + r.RunMethod2("setDividerHeight", Height, "java.lang.int") +End Sub + +'Centra un listview dentro de un elemento superior +Sub centraListView(elemento As ListView, anchoElementoSuperior As Int) 'ignore + elemento.Left = Round(anchoElementoSuperior/2)-(elemento.Width/2) +End Sub + +'Centra un panel dentro de un elemento superior +Sub centraPanel(elemento As Panel, anchoElementoSuperior As Int) 'ignore + elemento.Left = Round(anchoElementoSuperior/2)-(elemento.Width/2) +End Sub + +'Centra una etiqueta dentro de un elemento superior +Sub centraEtiqueta(elemento As Label, anchoElementoSuperior As Int) 'ignore + elemento.Left = Round(anchoElementoSuperior/2)-(elemento.Width/2) +End Sub + +'Centra un boton dentro de un elemento superior +Sub centraBoton(elemento As Button, anchoElementoSuperior As Int) 'ignore + elemento.Left = Round(anchoElementoSuperior/2)-(elemento.Width/2) +End Sub + +'Trae el cliente desde la BD. +Sub traeCliente As String 'ignore + Private cli As Cursor = Starter.skmt.ExecQuery("Select CUENTA from cuentaa") + cli.Position = 0 + Private cl As String = cli.GetString("CUENTA") + cli.Close + Return cl +End Sub + +'Agrega una columna a la tabla especificada. +'Hay que indicar el "tipo" de la columna (TEXT, INTEGER, ETC) +'Ej. agregaColumna("TABLA", "COLUMNA", "TIPO") +Sub agregaColumna(tabla As String, columna As String, tipo As String) + Try 'Intentamos usar "pragma_table_info" para revisar si existe la columna en la tabla + Private c As Cursor = Starter.skmt.ExecQuery($"SELECT COUNT(*) AS fCol FROM pragma_table_info('${tabla}') WHERE name='${columna}'"$) + c.Position = 0 + If c.GetString("fCol") = 0 Then 'Si no esta la columna la agregamos + Starter.skmt.ExecNonQuery($"ALTER TABLE ${tabla} ADD COLUMN ${columna} ${tipo}"$) + Log($"Columna "${columna} ${tipo}", agregada a "${tabla}"."$) + End If + Catch 'Si no funciona "pragma_table_info" lo hacemos con try/catch + Try + Starter.skmt.ExecNonQuery($"ALTER TABLE ${tabla} ADD COLUMN ${columna} ${tipo}"$) + Log($"Columna "${columna} ${tipo}", agregada a "${tabla}".."$) + Catch + Log(LastException) + End Try + End Try +End Sub \ No newline at end of file diff --git a/B4A/appUpdater.bas b/B4A/appUpdater.bas new file mode 100644 index 0000000..c0962f9 --- /dev/null +++ b/B4A/appUpdater.bas @@ -0,0 +1,284 @@ +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: +'//// +'//// * appUpdating +'//// * JavaObject +'//// * OkHttpUtils2 +'//// * Phone +'//// * RuntimePermissions +'//// +'//// 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/mariana/mariana_reparto.ver" + + '/// 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") + B4XPages.MainPage.muestraProgreso("Buscando actualización") + Log("Buscando actualización") + fileProvider_init + Wait For (Download(Me, lnk)) JobDone (j As HttpJob) + If j.Success Then + 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") + '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") + '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") + B4XPages.MainPage.muestraProgreso("Descargando actualización") + 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) + B4XPages.MainPage.ocultaProgreso + Log("ocultamos prigreso DOWNLOAD APK") + 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) +' 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