diff --git a/B4A/C_Subs.bas b/B4A/C_Subs.bas new file mode 100644 index 0000000..2a7a1f3 --- /dev/null +++ b/B4A/C_Subs.bas @@ -0,0 +1,608 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=12.2 +@EndOfDesignText@ +Sub Class_Globals + 'These global variables will be declared once when the application starts. + 'These variables can be accessed from all modules. +' Public GZip As GZipStrings 'Usa la libreria CompressStrings +' Private su As StringUtils 'Usa la libreria StringUtils + Dim reqManager As DBRequestManager + Private EventName As String 'ignore + Private CallBack As Object 'ignore + Dim phn As Phone + Dim devModel As String + Dim db, kmt, errorLog As SQL 'Requiere la libreria "SQL" 'ignore + Dim ssid As String 'ignore + Dim reqsList As List + Dim reqError As Boolean = False + Private subsLogs As Boolean = False +End Sub + +'You can add more parameters here. +Public Sub Initialize (vCallback As Object, vEventName As String) As Object + reqsList.Initialize + EventName = vEventName + CallBack = vCallback + db = dbInit + reqManager = reqManagerInit + Return Me +End Sub + +'Inicializa la BD con "kmt.db" en File.DirInternal, si el archivo no existe, lo copia desde File.DirAssets. +'Dispara el evento "dbOk" cuando termina. +Sub dbInit As SQL + If File.Exists(File.DirInternal, "kmt.db") = False Then File.Copy(File.DirAssets, "kmt.db", File.DirInternal, "kmt.db") + db.Initialize(File.DirInternal,"kmt.db", True) + dbOk(True) +' Log(db.IsInitialized) + Return db +End Sub + +Sub dbOk(Success As Boolean) + If SubExists(CallBack, EventName & "_dbOk") Then + CallSub2(CallBack, EventName & "_dbOk", Success) + End If +End Sub + +'Inicializamos el DBReqServer. +Sub reqManagerInit As DBRequestManager + Private rm As DBRequestManager + rm.Initialize(Me, traeDBReqServerDeBD(db)) + Log($"Inicializamos reqManager con ${traeDBReqServerDeBD(db)}"$) + Return rm +End Sub + +'Reinicializamos el DBReqServer de C_Subs. +Sub reqManagerReInit + Log("reqManager ReInit") + reqManager = reqManagerInit +End Sub + +Sub envioTest + reqsList.Initialize ' Ponemos la lista de DBRequests en cero. + Private cmd As DBCommand + cmd.Initialize + cmd.Name = "select_fecha" + For i = 0 To 50 +' Sleep(200) + reqManager.ExecuteQuery(cmd, 0, $"select_fecha_${i}"$) + reqsList.Add($"select_fecha_${i}"$) + Next +End Sub + +'Dispara el evento "_envioOk" del caller. +Sub envioOk(Success As Boolean) +' Log($"_ENVIOOK_"$) + If SubExists(CallBack, EventName & "_envioOk") Then + CallSub2(CallBack, EventName & "_envioOk", Success) + End If +End Sub + +Sub JobDone(Job As HttpJob) + LogColor("C_SUBS JOBDONE - " & Job.Success, Colors.Red) + If Job.Success = False Then + Log($"Error en el request ${Job.Tag}"$) + LogColor("** " & Job.Tag & " Error: " & Job.ErrorMessage, Colors.Red) + If reqsList.IndexOf(Job.Tag) > -1 Then reqsList.RemoveAt(reqsList.IndexOf(Job.Tag)) + reqError = True + Else + If Job.JobName = "DBRequest" Then + Dim resultado As DBResult = reqManager.HandleJob(Job) + If reqsList.IndexOf(resultado.Tag) > -1 Then reqsList.RemoveAt(reqsList.IndexOf(resultado.Tag)) + If resultado.Tag = "select_fecha" Then + For Each records() As Object In resultado.Rows + For Each k As String In resultado.Columns.Keys + Log(resultado.Tag & ": " & k & ": " & records(resultado.Columns.Get(k))) + Next + Next + End If + End If + End If + Log(reqsList.Size) + If reqsList.Size = 0 Then 'Ya no hay DBReqs pendientes. + Log(reqError) + If Not(reqError) Then + envioOk(True) + Else + envioOk(False) + End If + reqError = False + Log("-= FIN =-") + End If + Job.Release +End Sub + +'Pone el valor de phn.Model en la variable global "devModel" +Sub getPhnId As String 'ignore + 'Requiere la libreria "Phone" + devModel = phn.Model + If devModel.Length <= 3 Then 'Si phn.Model esta en blanco ... + Dim t As String = phn.GetSettings("android_id") 'Intentamos con "android_id" + devModel = t + End If + If devModel.Length >= 3 Then 'Si tenemos valor para phn.Model + File.WriteString(File.DirInternal, "phnId.txt", devModel) 'Sobreescribimos archivo phnId.txt with deviceId +' Log("Tenemos phnId: "&devModel&" "&File.DirInternal&"/phn.txt sobreescrito") + Else If devModel.Length < 3 Then ' Si no tenemos valor, lo leemos de phnId.txt + Dim s As String = File.ReadString(File.DirInternal, "phnId.txt") + devModel = s +' Log("Leemos id de "&File.DirInternal&"/phnId.txt") +' Log(devModel) + End If + Return devModel +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 + +'Escribimos las coordenadas y fecha a un archivo de texto +Sub guardaInfoEnArchivo(coords As String) 'ignore + ' Cambiamos el formato de la hora + Dim OrigFormat As String=DateTime.DateFormat 'save orig date format + DateTime.DateFormat="MMM-dd HH:mm:ss" + Dim lastUpdate As String=DateTime.Date(DateTime.Now) + DateTime.DateFormat=OrigFormat 'return to orig date format + + Dim ubic As String = coords&","&lastUpdate + Dim out As OutputStream = File.OpenOutput(File.DirRootExternal, "gps.txt", True) + Dim s As String = ubic & CRLF + Dim t() As Byte = s.GetBytes("UTF-8") + out.WriteBytes(t, 0, t.Length) + out.Close +End Sub + +'Escribimos las coordenadas (latitud, longitud, fecha) y fecha a una BD +Sub guardaInfoEnBD(coords As String) 'ignore + Log("Guardamos ubicacion en BD - "&coords) + Try + Dim latlon() As String = Regex.Split("\|", coords) + If latlon.Length < 2 Then latlon = Regex.Split(",", coords) 'Si son menos de 2, entonces estan separadas por comas y no por "|" + If subsLogs Then Log("LatLon="&latlon) + kmt.ExecNonQuery2("INSERT INTO RUTA_GPS(FECHA, LAT, LON) VALUES (?,?,?)", Array As Object (latlon(2),latlon(0),latlon(1))) + Catch + LogColor(LastException, Colors.red) + End Try +End Sub + +'Limpiamos la tabla RUTA_GPS de la BD +Sub deleteGPS_DB 'ignore + kmt.ExecNonQuery("delete from RUTA_GPS") + kmt.ExecNonQuery("vacuum;") + ToastMessageShow("Borramos BD Coords GPS", False) +End Sub + +'Limpiamos la tabla errorLog de la BD +Sub deleteErrorLog_DB 'ignore + errorLog.ExecNonQuery("delete from errores") + errorLog.ExecNonQuery("vacuum;") + ToastMessageShow("BD Errores Borrada", False) +End Sub + +'Mandamos "coords" en un mensaje a "Sprvsr" +'Sub mandamosLoc(coords As String) 'ignore +'' Log("Iniciamos mandamosLoc "&coords) +'' Log("locRequest="&Tracker.locRequest) +' guardaInfoEnBD(coords)'Escribimos coordenadas y fecha a una bd +' Dim t As String +' If Tracker.locRequest="Activa" Then +' If PushService.au = 1 Then +' t = "au" ' es una actualizacion +' Else +' t = "u" ' es una peticion +' End If +' Dim params As Map = CreateMap("topic":"Sprvsr", "coords":coords, "t":t, "b":PushService.battery, "mt":Main.montoActual) +' CallSub2(PushService, "mandaMensaje",params) +' Tracker.locRequest="Enviada" +' CallSubDelayed(Tracker,"CreateLocationRequest") +' End If +'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 + +'Guardamos "texto" a la bitacora +Sub log2DB(texto As String) 'ignore + LogColor(fechaKMT(DateTime.Now)&" - log2BD: '"&texto&"'", Colors.LightGray) + kmt.ExecNonQuery2("INSERT INTO bitacora(fecha, texto) VALUES (?,?)", Array As Object (fechaKMT(DateTime.now), texto)) +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 + +'Limpiamos la tabla "bitacora" de la BD +Sub borraLogDB 'ignore + LogColor("Borramos BD de log", Colors.Magenta) + kmt.ExecNonQuery("delete from bitacora") + kmt.ExecNonQuery("vacuum;") +End Sub + +'Monitoreamos los servicios para ver si estan activos (No pausados), y si no, los reniciamos +'Sub Monitor 'ignore +' Private monitorStatus As Boolean = True +' LogColor("Corriendo Subs.Monitor", Colors.RGB(161,150,0)) +' If IsPaused(Tracker) Then +' log2DB("Reiniciando 'Tracker Pausado' desde Subs.Monitor") +' StartService(Tracker) +' monitorStatus = False +' Else +' CallSubDelayed(Tracker, "revisaFLP") +' End If +' If IsPaused(PushService) Then +' log2DB("Reiniciando 'PushService Pausado' desde Subs.Monitor") +' StartService(PushService) +' monitorStatus = False +' Else +' revisaPushService +' End If +' If monitorStatus Then LogColor(" +++ +++ Servicios Activos", Colors.Green) +'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) + 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 + +'Copia la base de datos del almacenamiento interno al externo en el directorio kmts. +Sub copiaDB(result As Boolean) 'ignore + ToastMessageShow("copiaDB", False) + If result Then + Dim p As String + If File.ExternalWritable Then + p = File.DirRootExternal +' Log("Externo") + Else + p = File.DirInternal +' Log("Interno") + End If + Dim theDir As String + Try + File.MakeDir(File.DirRootExternal,"kmts") + theDir = "/kmts" + Catch + theDir = "" + End Try + Try + File.Copy(File.DirInternal,"kmt.db",File.DirRootExternal&theDir,"cedex_kmt.db") + File.Copy(File.DirInternal,"errorLog.db",File.DirRootExternal&theDir,"cedex_errorLog.db") + ToastMessageShow("BD copiada!", False) + Catch + ToastMessageShow("No se pudo hacer la copia: "&LastException, True) + End Try + Log("rootExternal="&p) + Log("File.DirInternal="&File.DirInternal) + Log("File.DirRootExternal="&File.DirRootExternal) + Else + ToastMessageShow("Sin permisos", False) + End If +End Sub + +'Hace visible y trae al frente 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 + +'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 panel horizontalmente 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 un panel verticalmente dentro de un elemento superior. +Sub centraPanelV(elemento As Panel, altoElementoSuperior As Int) 'ignore + elemento.Top = Round(altoElementoSuperior/2)-(elemento.Height/2) +End Sub + +'Centra una barra de progreso dentro de un elemento superior. +Sub centraProgressBar(elemento As ProgressBar, anchoElementoSuperior As Int) 'ignore + elemento.Left = Round(anchoElementoSuperior/2)-(elemento.Width/2) +End Sub + +'Regresa el usuario de la tabla USUARIOA si es que existe, si no existe, regresa "SinUsuario". +Sub buscaDBUsuario As String 'ignore + Private c As Cursor + Private usuario As String = "SinUsuario" + c=kmt.ExecQuery("select USUARIO from usuarioa") + c.Position=0 + If c.RowCount > 0 Then usuario = c.GetString("USUARIO") + Return usuario +End Sub + +'Regresa la fecha en el formato "MM/dd/yyyy" +Sub traeFecha As String 'ignore + DateTime.DateFormat = "MM/dd/yyyy" + Private sDate As String = DateTime.Date(DateTime.Now) + Private sTime As String = DateTime.Time(DateTime.Now) + Return sDate & sTime +End Sub + +'Guarda el nombre y version de la app en CAT_VARIABLES. +Sub guardaAppInfo(skmt As SQL) 'ignore + skmt.ExecNonQuery("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = 'EMPRESA' or CAT_VA_DESCRIPCION = 'APP_NAME' or CAT_VA_DESCRIPCION = 'APP_VERSION'") + skmt.ExecNonQuery($"insert into CAT_VARIABLES (CAT_VA_DESCRIPCION, CAT_VA_VALOR) values ('APP_NAME', '${Application.LabelName}')"$) + skmt.ExecNonQuery($"insert into CAT_VARIABLES (CAT_VA_DESCRIPCION, CAT_VA_VALOR) values ('APP_VERSION', '${Application.VersionName}')"$) +End Sub + +'Muestra en el Log los campos y valores que regresan en el JobDone. +Sub logJobDoneResultados(resultado As DBResult) 'ignore + For Each records() As Object In resultado.Rows + LogColor($"====== ${resultado.Tag} - REGISTROS = ${resultado.Rows.Size}"$, Colors.RGB(215,37,0)) + For Each k As String In resultado.Columns.Keys + LogColor(k & " = " & records(resultado.Columns.Get(k)), Colors.RGB(215,37,0)) + Next + Next +End Sub + +'Regresa la base de datos especificada ya inicializada. +Sub inicializaBD(ruta As String, BDName As String) As SQL 'ignore + Dim skmt As SQL + If File.Exists(ruta, BDName) = False Then + File.Copy(File.DirAssets, BDName, ruta, BDName) + LogColor($"Copiamos ${BDName} de ${File.DirAssets} a ${ruta}"$,Colors.Green) + End If + skmt.Initialize(ruta, BDName, True) + Return skmt +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) 'ignore + Try 'Intentamos usar "pragma_table_info" para revisar si existe la columna en la tabla + Private c As Cursor = db.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 + db.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 + db.ExecNonQuery($"ALTER TABLE ${tabla} ADD COLUMN ${columna} ${tipo}"$) + Log($"Columna "${columna} ${tipo}", agregada a "${tabla}".."$) + Catch + Log(LastException) + End Try + End Try +End Sub + +'Regresa el DBReqServer desde CAT_VARIABLES o "N/A" si no existe. +Sub traeDBReqServerDeBD(dbx As SQL) As String 'ignore + Dim srvr As String = "N/A" + Dim rs As ResultSet = dbx.ExecQuery("select CAT_VA_VALOR from cat_variables where CAT_VA_DESCRIPCION = 'SERVER'") + If rs.RowCount > 0 Then + rs.NextRow + srvr = rs.GetString("CAT_VA_VALOR") + End If + Return srvr +End Sub + +'Regresa el valor de intervalo desde CAT_VARIABLES o "30" si no existe. +Sub traeIntervaloDeBD As String 'ignore + Dim intrvl As String = "30" + Dim rs As ResultSet = db.ExecQuery("select valor from cat_variables where nombre = 'intervalo'") + If rs.RowCount > 0 Then + rs.NextRow + intrvl = rs.GetString("valor") + End If + Return intrvl +End Sub + +'Regresa el valor timeout desde CAT_VARIABLES o "9000" si no existe. +Sub traeTimeoutDeBD As String 'ignore + Dim tmout As String = "9000" + Dim rs As ResultSet = db.ExecQuery("select valor from cat_variables where nombre = 'timeout'") + If rs.RowCount > 0 Then + rs.NextRow + tmout = rs.GetString("valor") + End If + Return tmout +End Sub + +'Crea una notificación con el "body" dado y regresa el objeto. +Sub CreateNotification (Body As String) As Notification 'ignore + Dim notification As Notification + notification.Initialize2(notification.IMPORTANCE_LOW) + notification.Icon = "icon" + notification.SetInfo("Tester", Body, Main) + Return notification +End Sub + +'Genera una notificacion con importancia alta +Sub notiHigh(title As String, body As String, id As String, activity As Object) 'ignore + activity = Main + Private notif As Notification + notif.Initialize2(notif.IMPORTANCE_HIGH) + notif.Icon = "icon" + notif.Vibrate = False + notif.Sound = False + notif.AutoCancel = True +' If logger Then Log("notiHigh: "&title) + notif.SetInfo(title, body, activity) +' Log("notiHigh SetInfo") + notif.Notify(id) +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 + +'Regresa el almacen actual de la base de datos. +Sub traeAlmacen As String 'ignore + Private c As Cursor + Private a As String + c = db.ExecQuery("select ID_ALMACEN from CAT_ALMACEN") + c.Position = 0 + a = C.GetString("ID_ALMACEN") + c.Close + Return a +End Sub + +'Regresa la ruta actual de la base de datos. +Sub traeRuta As String 'ignore + Private c As Cursor + Private r As String + c = db.ExecQuery("select CAT_CL_RUTA from kmt_info where CAT_CL_CODIGO In (Select cuenta from cuentaa)") + r = "0" + If c.RowCount > 0 Then + c.Position=0 + r = c.GetString("CAT_CL_RUTA") + End If + c.Close + Return r +End Sub + +'Mandamos los pedidos pendientes (pc_envio_ok <> 1). +Sub mandaPendientes 'ignore + Private logger As Boolean = False + 'PEDIDO_CLIENTE (Pendientes) + Private c As Cursor = db.ExecQuery("SELECT PC_CLIENTE, PC_FECHA, PC_USER, PC_NOART, PC_MONTO,PC_LON, PC_LAT, PC_COSTO_SIN, PC_RUTA, PC_ALMACEN, PC_FACTURA FROM PEDIDO_CLIENTE where pc_envio_ok <> 1") + If logger Then Log($"Pedido_Cliente PENDIENTE: ${c.RowCount}"$) + Private almacen As String = traeAlmacen + Private ruta As String = traeRuta + If c.RowCount>0 Then + For i = 0 To c.RowCount - 1 + c.Position = i + Dim cmd As DBCommand + cmd.Initialize + cmd.Name = "DELETE_PEDIDO_MARDS_PC" + cmd.Parameters = Array As Object(almacen, ruta, c.GetString("PC_CLIENTE") ) + reqManager.ExecuteCommand(cmd , "DEL_PC") + + Dim cmd As DBCommand + cmd.Initialize + cmd.Name = "insert_pedidos_MARDS" + If logger Then Log($"${c.GetString("PC_CLIENTE")}, ${almacen}"$) + cmd.Parameters = Array As Object(C.GetString("PC_CLIENTE"), C.GetString("PC_FECHA"), C.GetString("PC_USER"), C.GetString("PC_NOART"), C.GetString("PC_MONTO"), C.GetString("PC_LON"), C.GetString("PC_LAT"), almacen, ruta, C.GetString("PC_COSTO_SIN"), C.GetString("PC_FACTURA")) + reqManager.ExecuteCommand(cmd , $"ins_pedidosPendientes_head_${c.GetString("PC_CLIENTE")}"$) + Next + End If + + 'PEDIDO (Pendientes) + c=Starter.skmt.ExecQuery("SELECT PC_ENVIO_OK, PE_CEDIS, PE_COSTO_TOT, PE_COSTOU, PE_CANT, PE_PRONOMBRE, PE_PROID, PE_CLIENTE, PE_FECHA, PE_USUARIO, PE_COSTO_SIN, PE_RUTA, PE_DESC, PE_FOLIO FROM pedido_cliente left join PEDIDO where pc_cliente = pe_cliente and pc_envio_ok <> 1") + If logger Then Log($"Pedido PENDIENTE: ${c.RowCount}"$) + If c.RowCount>0 Then + For i = 0 To c.RowCount - 1 + c.Position = i + Dim cmd As DBCommand + + cmd.Initialize + cmd.Name = "DELETE_PEDIDO_MARDS_PE" + cmd.Parameters = Array As Object(almacen, ruta,c.GetString("PE_CLIENTE") ) + reqManager.ExecuteCommand(cmd , "DEL_PE") + + cmd.Initialize + cmd.Name = "insert_pedido_MARDS" + cmd.Parameters = Array As Object(c.GetString("PE_CEDIS"), almacen, c.GetString("PE_COSTO_TOT"), c.GetString("PE_COSTOU"), c.GetString("PE_CANT"), c.GetString("PE_PRONOMBRE"), c.GetString("PE_PROID"), c.GetString("PE_CLIENTE"), c.GetString("PE_FECHA"), c.GetString("PE_USUARIO"), c.GetString("PE_RUTA"), C.GetString("PE_COSTO_SIN"), c.GetString("PE_DESC"), c.GetString("PE_FOLIO")) + reqManager.ExecuteCommand(cmd , $"ins_pedidosPendientes_prods_${c.GetString("PE_CLIENTE")}"$) + Next + End If + + 'ABONOS + Dim ab As Cursor = db.ExecQuery($"SELECT * from ABONOS where a_enviado is null"$) + If logger Then Log(ab.RowCount) + If ab.RowCount > 0 Then + For i = 0 To ab.RowCount - 1 + ab.Position = i + Dim cmd As DBCommand + cmd.Initialize + cmd.Name = "insert_abono_MARDS" + cmd.Parameters = Array As Object( ab.GetString("a_usuario"), ab.GetString("a_ruta"), ab.GetString("a_cliente"), ab.GetString("a_abono"), ab.GetString("a_fecha") ) + reqManager.ExecuteCommand(cmd , $"ins_abonosPendientes_${ab.GetString("a_cliente")}"$) + If logger Then Log($"ins_abonosPendientes_${ab.GetString("a_cliente")}"$) + Next + End If + ab.Close +End Sub + +'Revisa si la aplicación tiene permiso para acceder a las notificaciones. +Sub CheckNotificationAccess As Boolean 'ignore + Dim ph As Phone + Dim nstr, pstr As String + Dim r As Reflector + pstr = r.GetStaticField("anywheresoftware.b4a.BA", "packageName") + nstr = ph.GetSettings("enabled_notification_listeners") + Return nstr.Contains(pstr) +End Sub \ No newline at end of file diff --git a/B4A/INTMEX_LL.b4a.meta b/B4A/INTMEX_LL.b4a.meta index 7c61618..0f3aa7c 100644 --- a/B4A/INTMEX_LL.b4a.meta +++ b/B4A/INTMEX_LL.b4a.meta @@ -82,6 +82,6 @@ ModuleClosedNodes6= ModuleClosedNodes7= ModuleClosedNodes8=1 ModuleClosedNodes9= -NavigationStack=C_Subs,mandaPendientes,592,0,B4XMainPage,B4XPage_Appear,244,1,NotificationService,Service_Destroy,72,0,NotificationService,NotiMon_NotificationPosted,83,0,B4XMainPage,i_engrane_Click,659,0,C_RespaldoDiario,Class_Globals,0,0,C_RespaldoDiario,Initialize,23,6,B4XMainPage,ocultaProgreso,653,0,B4XMainPage,lv_server_ItemClick,684,0,B4XMainPage,Entrar_LongClick,676,0,B4XMainPage,i_engrane_LongClick,672,0 +NavigationStack=B4XMainPage,B4XPage_Appear,244,1,NotificationService,Service_Destroy,72,0,NotificationService,NotiMon_NotificationPosted,83,0,B4XMainPage,i_engrane_Click,659,0,C_RespaldoDiario,Class_Globals,0,0,C_RespaldoDiario,Initialize,23,6,B4XMainPage,ocultaProgreso,653,0,B4XMainPage,Entrar_LongClick,676,0,B4XMainPage,i_engrane_LongClick,672,0,B4XMainPage,lv_server_ItemClick,681,0 SelectedBuild=0 VisibleModules=2,25,23,12,15,13,4,26,14,8,22,9,16,27 diff --git a/B4A/NotificationService.bas b/B4A/NotificationService.bas new file mode 100644 index 0000000..d56b2d2 --- /dev/null +++ b/B4A/NotificationService.bas @@ -0,0 +1,218 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Service +Version=11 +@EndOfDesignText@ +#Region Service Attributes + #StartAtBoot: False +#End Region + +'****************************************************************************** +'Se necesita la libreria ReplyAuto. + +'No olvidar agregar esta linea al editor de manifiesto: + +'AddApplicationText( +' +' +' ) + +'En B4XPage_Appear de MainPage agregar estas lineas: +' +'If Not(CheckNotificationAccess) Then +' Msgbox2Async($"Se necesita acceso a las notificaciones, haga clic en "Aceptar" y en la siguiente pantalla permita el acceso a la aplicación "${Application.LabelName}"."$, "Permisos necesarios", "Aceptar", "Cancelar", "", Null, True) +' Wait For Msgbox_Result (resultado As Int) +' If resultado = DialogResponse.POSITIVE Then +' Dim In As Intent +' In.Initialize("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS", "") +' StartActivity(In) +' End If +'End If +' +'Y al final de Mainpage agregar esta funcion: +' +''Revisa si la aplicación tiene permiso para acceder a las notificaciones. +'Sub CheckNotificationAccess As Boolean 'ignore +' Dim ph As Phone +' Dim nstr, pstr As String +' Dim r As Reflector +' pstr = r.GetStaticField("anywheresoftware.b4a.BA", "packageName") +' nstr = ph.GetSettings("enabled_notification_listeners") +' Return nstr.Contains(pstr) +'End Sub + +'****************************************************************************** + + + + +Sub Process_Globals + 'These global variables will be declared once when the application starts. + 'These variables can be accessed from all modules. + Dim rp As ReplyAuto +' Dim activo As Boolean = True +' Dim ultimaNoti As String + Dim logger As Boolean = False +End Sub + +Sub Service_Create + rp.Initialize("NotiMon") + #if not(DEBUG) + logger = False + #end if +' If logger Then Log("**************** Iniciamos Monitor Keymon ***********************") +End Sub + +Sub Service_Start (StartingIntent As Intent) +' Log("NotificationService Start") + If rp.HandleIntent(StartingIntent) Then Return +' DateTime.DateFormat = "mm" +' ultimaNoti = DateTime.Date(DateTime.now) +' If logger Then LogColor($"Ultima notificación en el minuto ${ultimaNoti}"$, Colors.green) +End Sub + +Sub Service_Destroy + +End Sub + +Sub NotiMon_NotificationPosted (SBN As StatusBarNotification) + Private logger As Boolean = True + If SBN.PackageName = "com.whatsapp" Then + If logger Then LogColor(SBN.PackageName, Colors.Red) + If logger Then LogColor("isGroupWA2: "&isGroupWA(SBN),Colors.Magenta) + If logger Then LogColor("isPersonWA: "&isPersonWA(SBN),Colors.Magenta) + If logger Then Log($"getGroupName: |${getGroupName(SBN.Title)}|"$) + Private cmd() As String = Regex.Split(" ", SBN.Message) + If SBN.Message.StartsWith("#NS") And cmd.Length = 2 Then 'Si el mensaje contiene "#NS" y tiene un segundo parametro ... + If esMensajeWAValido(SBN) Then +' Log(cmd(1)) + rp.ClearNotification(SBN) + Starter.reinicializaReqManager(cmd(1)) + rp.reply(SBN.Notification, SBN.PackageName, $"Servidor cambiado a ${cmd(1)} "$) + Sleep(1000) +' rp.ClearNotification(SBN) + rp.ClearAll + End If + End If + End If +End Sub + +'Regresa verdadero si el mensaje de whatsapp es un mensaje valido. +Sub esMensajeWAValido(SBN As StatusBarNotification) + Private valido As Boolean = False + Private ww() As String = Regex.Split("\|", SBN.Key) + If ww(3) <> Null And ww(3) <> "null" Then valido = True + Return valido +End Sub + +'Returns TRUE if the sender is a GROUP. +'Searches the provided sbn.title for the string ": " to know if the sender is a group. +Sub isGroupWA2(sbnTitle As String) As Boolean 'ignore + Private x As Boolean = Regex.ismatch(".*(: ).*", sbnTitle) + Return x +End Sub + +'Returns TRUE if the sender is a GROUP. +'Searches the provided notification object for the string "@g.us" and if found returns TRUE. +Sub isGroupWA(sbn As StatusBarNotification) As Boolean + Private a As Boolean = False + If sbn.As(String).IndexOf("@g.us") > -1 Then a = True 'ignore + Return a +End Sub + +'Returns TRUE if the sender is a PERSON. +'Searches the provided notification object for the string "@s.whatsapp.net" and if found returns TRUE. +Sub isPersonWA(sbn As StatusBarNotification) As Boolean 'ignore + Private a As Boolean = False + If sbn.As(String).IndexOf("@s.whatsapp.net") > -1 Then a = True 'ignore + Return a +End Sub + +'Returns TRUE if the sender is a PERSON. +'Searches the provided notification object for the string "channel=individual" and if found returns TRUE. +Sub isPersonWA2(sbn As StatusBarNotification) As Boolean 'ignore + Private a As Boolean = False + If sbn.As(String).IndexOf("channel=individual") > -1 Then a = True 'ignore + Return a +End Sub + +'Returns the sender's number. +'Searches the provided notification object and gets the numbers between "shortcut=" and "@s.whatsapp.net". +Sub getNumberWA(sbn As StatusBarNotification) As String + Private a As Int = sbn.As(String).IndexOf("@s.whatsapp.net") 'ignore + If a > -1 Then + Private x As String = sbn.As(String) 'ignore + Private y As Int = x.IndexOf("shortcut=") + If (y+9) > 0 And a > (y+9) Then x = x.SubString2(y+9, a) Else x = "Not a person" + Else 'It is probably is a group. + x = "Not a person" + End If + Return x +End Sub + +'Returns the name of the group from the given text. +'If it is not a group, then returns the notification's title. +Sub getGroupName(sbnTitle As String) As String 'ignore + Private a As Int = sbnTitle.IndexOf(": ") + Private x As String = sbnTitle + If a > -1 Then + Private b As String = sbnTitle.SubString2(0, a) + x = Regex.Replace(" \(.+\)", b, "") + End If + Return x +End Sub + +'Returns the name of the group from the given notification object. +'Searches the provided notification for the string "hiddenConversationTitle" and if found, gets the name. +'If it is not a group,then it returns the notification's title. +Sub getGroupName2(sbn As StatusBarNotification) As String 'ignore + Private inicio As Int = sbn.Extras.As(String).IndexOf("hiddenConversationTitle=") 'ignore + If inicio > -1 And sbn.Extras.As(String).IndexOf("hiddenConversationTitle=null") = -1 Then 'ignore + Private x As String = sbn.Extras.As(String) 'ignore + Private fin As Int = x.IndexOf(", android.reduced.images=") + x = x.SubString2(inicio+24, fin) + x = Regex.Replace(" \(.+\)", x, "") 'Replace anything between () with "", this en the case that we have something like "MyGroupName (5 messages)" + Else 'Is not from a group. + Private x As String = sbn.Title + End If + Return x +End Sub + +'Returns the person's name (or the number) when the message comes from a group. +'Searches the provided sbn.title for the string ": " in the title and returns the string after that, +'if it does not find ": " then returns the complete string. +Sub getPersonFromGroup(sbnTitle As String) As String 'ignore + Private a As Int = sbnTitle.IndexOf(": ") + If a = -1 Then a = -2 'Is not from a group. + Private b As String = sbnTitle.SubString(a+2) + Return b +End Sub + +'Returns the NUMBER of the sender and if NOT a person, then returns the name of the group. +Sub getNumberOrGroupWA(sbn As StatusBarNotification) As String 'ignore + Private numRemitente As String = getNumberWA(sbn) + If numRemitente = "Not a person" Then numRemitente = getGroupName(sbn.Title) + Return numRemitente +End Sub + +'Regresa el "shortcut" del remitente. +'Si es de un grupo, es algo como "120363023512345678@g.us" +'Si es de una persona, entonces "5215512345678@s.whatsapp.net" +Sub getShortcut(sbn As StatusBarNotification) As String 'ignore + Private ap As Int = sbn.As(String).IndexOf("@s.whatsapp.net") 'ignore + Private ag As Int = sbn.As(String).IndexOf("@g.us") 'ignore + Private x As String = sbn.As(String) 'ignore + Private y As Int = x.IndexOf("shortcut=") + If ap > -1 Then + Private x As String = sbn.As(String) 'ignore + Private y As Int = x.IndexOf("shortcut=") + x = x.SubString2(y+9, ap+15) + Else if ag > -1 Then 'It is probably is a group. + Private x As String = sbn.As(String) 'ignore + Private y As Int = x.IndexOf("shortcut=") + x = x.SubString2(y+9, ag+5) + End If + Return x +End Sub \ No newline at end of file