From 52bb35dbdc0b9a1560c5bcd856718b19e5d97127 Mon Sep 17 00:00:00 2001 From: cheveguerra Date: Tue, 3 Oct 2023 16:01:28 -0600 Subject: [PATCH] =?UTF-8?q?3/10/23=20-=20Se=20agreg=C3=B3=20el=20respaldo?= =?UTF-8?q?=20diario=20y=20intercepci=C3=B3n=20de=20notificaciones.=20-=20?= =?UTF-8?q?Se=20agreg=C3=B3=20el=20c=C3=B3digo=20para=20el=20respaldo=20di?= =?UTF-8?q?ario=20de=204=20tablas.=20-=20Se=20agreg=C3=B3el=20codigo=20par?= =?UTF-8?q?a=20interceptar=20notificacines=20y=20cambiar=20el=20servidor?= =?UTF-8?q?=20de=20DBRequest.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- B4A/B4XMainPage.bas | 50 +++- B4A/C_Cliente.bas | 4 +- B4A/C_Principal.bas | 116 +++++-- B4A/KelloggsV4.b4a | 22 +- B4A/KelloggsV4.b4a.meta | 15 +- B4A/ManageExternalStorage.bas | 79 +++++ B4A/NotificationService.bas | 178 +++++++++++ B4A/Starter.bas | 27 +- B4A/Subs.bas | 2 +- B4A/kms_helperSubs.bas | 550 ++++++++++++++++++++++++++++++++++ 10 files changed, 984 insertions(+), 59 deletions(-) create mode 100644 B4A/ManageExternalStorage.bas create mode 100644 B4A/NotificationService.bas create mode 100644 B4A/kms_helperSubs.bas diff --git a/B4A/B4XMainPage.bas b/B4A/B4XMainPage.bas index 36981d5..d4659a6 100644 --- a/B4A/B4XMainPage.bas +++ b/B4A/B4XMainPage.bas @@ -92,6 +92,8 @@ Sub Class_Globals Private l_server As Label Public rutaBDBackup As String = "" Private b_envioBD As Button + Dim MES1 As ManageExternalStorage + Dim device As Phone End Sub Public Sub Initialize @@ -185,14 +187,14 @@ Private Sub B4XPage_Created (Root1 As B4XView) End Try ' If sDate = "20190523" Then ' Starter.db.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("SERVER")) -' Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER", Starter.server)) +' Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER", Starter.DBReqServer)) ' End If ' Starter.db.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("ULTIMOMODULO")) ' Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("ULTIMOMODULO", "MAIN")) c=Starter.db.ExecQuery2("select count(*) as CUANTOS from CAT_VARIABLES WHERE CAT_VA_DESCRIPCION = ?", Array As String ("SERVER")) c.Position =0 If c.GetString("CUANTOS") = 0 Then - Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER", Starter.server)) + Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER", Starter.DBReqServer)) ' Else ' c=Starter.db.ExecQuery2("select CAT_VA_VALOR from CAT_VARIABLES WHERE CAT_VA_DESCRIPCION = ?", Array As String ("SERVER")) ' c.Position = 0 @@ -300,13 +302,37 @@ Private Sub B4XPage_Created (Root1 As B4XView) ' If Result Then Log("Tenemos permisos de bluetooth.") ' Log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") ' Log("Check phone state: " & rp.Check(rp.PERMISSION_READ_PHONE_STATE)) + + MES1.Initialize(Me, "MES1") + ' get the device SDK version + Dim SdkVersion As Int = device.SdkVersion + ' Choose which permission to request in order to access external storgage + If SdkVersion < 30 Then +' Log("SDK = " & SdkVersion & " : Requesting WRITE_EXTERNAL_STORAGE permission") + Dim rp As RuntimePermissions + rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE) ' Implicit read capability if granted + Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) +' Log($"PERMISSION_WRITE_EXTERNAL_STORAGE = ${Result}"$) + Else +' Log("SDK = " & SdkVersion & " : Requesting MANAGE_EXTERNAL_STORAGE permission") +' Log("On Entry MANAGE_EXTERNAL_STORAGE = " & MES1.HasPermission) + If Not(MES1.HasPermission) Then + Dim r As String = Msgbox2("This app requires access to all files, please enable the option", "Manage All Files", "OK", "", "", Null) + If r = DialogResponse.POSITIVE Then + MES1.GetPermission +' Wait For Msgbox_Result(Res As Int) +' Log("Getting permission") + Wait For MES_StorageAvailable + End If + End If + End If End Sub Sub B4XPage_Appear ' server = "http://keymon.com.mx:1782" ' server = "http://201.99.139.28:1782" ' server = "http://177.244.63.54:1782" - reqManager.Initialize(Me, Starter.server) + reqManager.Initialize(Me, Starter.DBReqServer) Starter.montoActual = 0 Starter.clientesTotal = 0 Starter.clientesVenta = 0 @@ -366,7 +392,7 @@ Sub Entrar_Click If user.Text = "ALTERNO" Then c=Starter.db.ExecQuery2("select CAT_CO_CONFIGURACION, CAT_CO_RESULTADO from CAT_CODIGOS where CAT_CO_PONDERACION =1 AND CAT_CO_ACCION = ?", Array As String("SERVER")) c.Position =0 - Starter.server = c.GetString("CAT_CO_CONFIGURACION") + Starter.DBReqServer = c.GetString("CAT_CO_CONFIGURACION") alterno = c.GetString("CAT_CO_RESULTADO") c.Close If alterno = 1 Then @@ -378,10 +404,10 @@ Sub Entrar_Click End If c=Starter.db.ExecQuery2("select CAT_CO_CONFIGURACION, CAT_CO_RESULTADO from CAT_CODIGOS where CAT_CO_PONDERACION =1 AND CAT_CO_ACCION = ?", Array As String("SERVER")) c.Position =0 - Starter.server = c.GetString("CAT_CO_CONFIGURACION") - user.Text = Starter.server + Starter.DBReqServer = c.GetString("CAT_CO_CONFIGURACION") + user.Text = Starter.DBReqServer c.Close -' reqManager.Initialize(Me, Starter.server) +' reqManager.Initialize(Me, Starter.DBReqServer) else if user.Text = "KMTSKLL1" Then Starter.db.ExecNonQuery("delete from usuarioa") Starter.db.ExecNonQuery2("INSERT INTO USUARIOA VALUES (?,?,?)", Array As Object(user.Text, pass.Text, DateTime.Date(DateTime.Now))) @@ -498,7 +524,7 @@ Private Sub B4XPage_CloseRequest As ResumableSub If Panel1.Visible Then Panel1.Visible = False Entrar.Visible = True - Return True + Return False Else If logger Then Log("Saliendo") B4XPages.ClosePage(Me) @@ -575,10 +601,10 @@ End Sub Sub B_SERVER_Click Starter.db.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("SERVER")) Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER",E_SERVER.text)) - Starter.server = E_SERVER.text - If logger Then Log("Inicializamos reqManager con " & Starter.server) - reqManager.Initialize(Me, Starter.server) - CallSubDelayed(Starter, "reinicializaReqManager") + Starter.DBReqServer = E_SERVER.text + If logger Then Log("Inicializamos reqManager con " & Starter.DBReqServer) + reqManager.Initialize(Me, Starter.DBReqServer) + CallSubDelayed2(Starter, "reinicializaReqManager", Starter.DBReqServer) Panel1.Visible = False Entrar.Visible = True End Sub diff --git a/B4A/C_Cliente.bas b/B4A/C_Cliente.bas index 382ffe8..3ebc52a 100644 --- a/B4A/C_Cliente.bas +++ b/B4A/C_Cliente.bas @@ -363,7 +363,7 @@ End Sub Sub B4XPage_Appear Log(Starter.rp.Check("android.permission.BLUETOOTH_CONNECT")) - reqManager.Initialize(Me, Starter.server) + reqManager.Initialize(Me, Starter.DBReqServer) ' Log(Subs.traeUltimaActividadBD) Subs.panelVisibleCompleto(P_INF_GENERAL, Root) ' P_INF_GENERAL.Height = Root.Height @@ -3719,7 +3719,7 @@ Private Sub b_geopass_Click cmd.Name = "select_geoPass" cmd.Parameters = Array As Object(et_geopass.Text, Subs.traeAlmacen, Subs.traeRuta) reqManager.ExecuteQuery(cmd , 0, "traeGeoPass") - Log($"${Starter.server}, ${et_geopass.Text}, ${Subs.traeAlmacen}, ${Subs.traeRuta}"$) + Log($"${Starter.DBReqServer}, ${et_geopass.Text}, ${Subs.traeAlmacen}, ${Subs.traeRuta}"$) et_geopass.Text = "" End If b_noVenta.Visible = True diff --git a/B4A/C_Principal.bas b/B4A/C_Principal.bas index 6130d77..7f3ff46 100644 --- a/B4A/C_Principal.bas +++ b/B4A/C_Principal.bas @@ -9,6 +9,8 @@ Sub Class_Globals Private Root As B4XView 'ignore Private xui As XUI 'ignore Dim reqManager As DBRequestManager + Dim device As Phone + Dim kh As kms_helperSubs Dim rp As RuntimePermissions Dim t1 As Timer Dim t2 As Timer @@ -58,7 +60,7 @@ Sub Class_Globals Dim Listo4 As String Dim Listo5 As String Dim EJECUTANDO As String - Dim res As String +' Dim res As String Dim inve As String Dim cuantos_pedidosc As String Dim cuantos_pedido As String @@ -182,10 +184,14 @@ Sub Class_Globals Private l_porcentaje As Label Private detenerLoop As Boolean = False Dim logger As Boolean = True + Private admin As BluetoothAdmin + Public BluetoothState, ConnectionState As Boolean + Private ion As Object End Sub 'You can add more parameters here. Public Sub Initialize As Object + admin.Initialize("admin") Return Me End Sub @@ -203,7 +209,7 @@ Private Sub B4XPage_Created (Root1 As B4XView) fecha=DateTime.Date(DateTime.Now) c=Starter.db.ExecQuery2("select CAT_CO_CONFIGURACION from CAT_CODIGOS where CAT_CO_PONDERACION =1 AND CAT_CO_ACCION = ?", Array As String("SERVER")) c.Position =0 - Starter.server = c.GetString("CAT_CO_CONFIGURACION") + Starter.DBReqServer = c.GetString("CAT_CO_CONFIGURACION") c.Close b=Starter.db.ExecQuery("Select count(*) as CUANTOS from pedido_cliente") b.Position=0 @@ -252,33 +258,97 @@ Private Sub B4XPage_Created (Root1 As B4XView) l_ctast.Text = d.GetString("TOTAL_VISITAR") 'l_porvisitar.Text = e.GetString("POR_VISITAR") End If - ' Log("Permisos BT: " & rp.Check("android.permission.BLUETOOTH_CONNECT")) - Log("XXXXXXXXXXXXXXXXXXXXXXXXX REVISAMOS PERMISOS DE BT") - rp.CheckAndRequest("android.permission.BLUETOOTH_CONNECT") - Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) - If Result Then Log("Tenemos permisos de bluetooth.") + kh.Initialize(Me, "kh") + kh.RD_Init + Log("XXXXXXXXXXXXXXXXXXXXXXXXX REVISAMOS PERMISOS DE BT - APPEAR -") + StartBluetooth Log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") -' Log("Check phone state: " & rp.Check(rp.PERMISSION_READ_PHONE_STATE)) + +End Sub + +Private Sub StartBluetooth + If admin.IsEnabled = False Then + Wait For (EnableBluetooth) Complete (Success As Boolean) + If Success = False Then + ToastMessageShow("Failed to enable bluetooth", True) + End If + End If + BluetoothState = admin.IsEnabled + StateChanged +End Sub + +Private Sub StateChanged +' btnSearchForDevices.Enabled = BluetoothState +' btnAllowConnection.Enabled = BluetoothState +' ChatPage1.btnSend.Enabled = ConnectionState +End Sub + +Private Sub EnableBluetooth As ResumableSub + ToastMessageShow("Enabling Bluetooth adapter...", False) + Dim ph As Phone + If ph.SdkVersion >= 31 Then + Log(31) + rp.CheckAndRequest("android.permission.BLUETOOTH_CONNECT") + Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) + Log(Result) + If Result = False Then Return False + If ph.SdkVersion >= 33 Then + Log(33) + Dim in As Intent + in.Initialize("android.bluetooth.adapter.action.REQUEST_ENABLE", "") + StartActivityForResult(in) + Wait For ion_Event (MethodName As String, Args() As Object) + Return admin.IsEnabled + End If + End If + Return admin.Enable +End Sub + +Private Sub StartActivityForResult(i As Intent) + Dim jo As JavaObject = GetBA + ion = jo.CreateEvent("anywheresoftware.b4a.IOnActivityResult", "ion", Null) + jo.RunMethod("startActivityForResult", Array As Object(ion, i)) +End Sub + +Sub GetBA As Object + Dim jo As JavaObject = Me + Return jo.RunMethod("getBA", Null) End Sub 'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage. Sub B4XPage_Appear + If Not(kh.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 If Subs.traeUltimaActividadBD <> "principal" Then Subs.iniciaActividad(Subs.traeUltimaActividadBD) - reqManager.Initialize(Me, Starter.server) - Starter.btAdmin.Initialize("btAdmin") - Log("BTADMIN INICIALIZADO: "&Starter.btAdmin.IsEnabled) - If Not(Starter.btAdmin.IsEnabled) Then Starter.btAdmin.Enable 'Si no esta prendido el BT, lo prendemos. + reqManager.Initialize(Me, Starter.DBReqServer) +' If Not(btAdmin.IsEnabled) Then btAdmin.Enable 'Si no esta prendido el BT, lo prendemos. + If kh.RD_Init_IsInitialized Then + kh.RD_respalda_cat_detalle_paq + kh.RD_respalda_cat_gunaprod + kh.RD_respalda_cat_gunaprod2 + kh.RD_respalda_kmt_info + kh.RD_respalda_pedido + Else + Log("****** RD NO INICIALIZADO ********") + End If e_ruta.Enabled = True Starter.rutaV = l_ruta.Text c=Starter.db.ExecQuery2("select count(*) as CUANTOS from CAT_VARIABLES WHERE CAT_VA_DESCRIPCION = ?", Array As String ("SERVER")) c.Position =0 If c.GetString("CUANTOS") = 0 Then - Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER", Starter.server)) + Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER", Starter.DBReqServer)) Else c=Starter.db.ExecQuery2("select CAT_VA_VALOR from CAT_VARIABLES WHERE CAT_VA_DESCRIPCION = ?", Array As String ("SERVER")) c.Position =0 - Starter.server = c.GetString("CAT_VA_VALOR") + Starter.DBReqServer = c.GetString("CAT_VA_VALOR") End If c=Starter.db.ExecQuery2("select CAT_VA_VALOR from CAT_VARIABLES WHERE CAT_VA_DESCRIPCION = ?", Array As String ("FECHA")) If c.RowCount > 0 Then @@ -350,10 +420,10 @@ Sub B4XPage_Appear Not(File.Exists(File.DirInternal,"FOTO2.jpg")) Or _ Not(File.Exists(File.DirInternal,"FOTO3.jpg")) Or _ Not(File.Exists(File.DirInternal,"FOTO4.jpg")) Then - If Not(File.Exists(File.DirInternal,"FOTO1.jpg")) Then Log("Falta foto1") - If Not(File.Exists(File.DirInternal,"FOTO2.jpg")) Then Log("Falta foto2") - If Not(File.Exists(File.DirInternal,"FOTO3.jpg")) Then Log("Falta foto3") - If Not(File.Exists(File.DirInternal,"FOTO4.jpg")) Then Log("Falta foto4") +' If Not(File.Exists(File.DirInternal,"FOTO1.jpg")) Then Log("Falta foto1") +' If Not(File.Exists(File.DirInternal,"FOTO2.jpg")) Then Log("Falta foto2") +' If Not(File.Exists(File.DirInternal,"FOTO3.jpg")) Then Log("Falta foto3") +' If Not(File.Exists(File.DirInternal,"FOTO4.jpg")) Then Log("Falta foto4") Cedis_Check = 0 End If If Cedis_Check = 0 And l_ruta.Text <> 0 Then @@ -380,17 +450,17 @@ Sub B4XPage_Appear ' Subs.guardaUltimaActividadBD("principal") - Log("Check phone state: " & rp.Check(rp.PERMISSION_READ_PHONE_STATE)) - Log("Pedimos permisos de estado del cel") +' Log("Check phone state: " & rp.Check(rp.PERMISSION_READ_PHONE_STATE)) +' Log("Pedimos permisos de estado del cel") rp.CheckAndRequest(rp.PERMISSION_READ_PHONE_STATE) Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) If Result Then Dim Phn As PhoneId ' IMEN.Text = "" 'Phn.GetDeviceId imei ="" ' Phn.GetDeviceId - If logger Then LogColor($"////////////////// IMEI: ${imei} ////////////////// "$, Colors.Blue) +' If logger Then LogColor($"////////////////// IMEI: ${imei} ////////////////// "$, Colors.Blue) End If - Log("Permisos cel terminados") +' Log("Permisos cel terminados") ' Log("Permisos BT: " & rp.Check("android.permission.BLUETOOTH_CONNECT")) ' Log("REVISAMOS PERMISOS DE BT") @@ -2881,7 +2951,7 @@ Sub descargaCartaPorte ' Log(cartaPortePDF) 'Para el servidor Private pdfServer As String = "keymon.lat" - If Starter.server.IndexOf("10.0.0.205") > -1 Then pdfServer = "10.0.0.205" + If Starter.DBReqServer.IndexOf("10.0.0.205") > -1 Then pdfServer = "10.0.0.205" ' Log(pdfServer) pdfURL = $"https://${pdfServer}/CartaPorteKelloggs/CartaPorteMovil${DateTime.Date(DateTime.now)}/${cartaPortePDF}"$ LogColor(pdfURL,Colors.Red) diff --git a/B4A/KelloggsV4.b4a b/B4A/KelloggsV4.b4a index 682811c..d06d6ec 100644 --- a/B4A/KelloggsV4.b4a +++ b/B4A/KelloggsV4.b4a @@ -129,13 +129,14 @@ Library27=xcustomlistview Library28=xui Library29=zxing_scanner Library3=baqrcode +Library30=replyauto Library4=bitmapcreator Library5=byteconverter Library6=camera Library7=contentresolver Library8=core Library9=fileprovider -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~AddApplicationText(~\n~)~\n~'Set activity to Landscape~\n~SetActivityAttribute(foto, android:screenOrientation, "landscape")~\n~AddApplicationText(~\n~~\n~ ~\n~)~\n~AddManifestText(~\n~~\n~)~\n~'''' para el teclado~\n~ SetActivityAttribute(main, android:windowSoftInputMode, adjustResize|stateHidden)~\n~ SetApplicationAttribute(android:allowBackup, "false")~\n~ SetServiceAttribute(Tracker, android:foregroundServiceType, "location")~\n~ ~\n~ AddManifestText(~\n~~\n~)~\n~''CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)~\n~ 'End of default text.~\n~ ~\n~SetApplicationAttribute(android:usesCleartextTraffic, "true")~\n~ AddManifestText(~\n~~\n~)~\n~AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)~\n~AddManifestText(~\n~~\n~)~\n~AddManifestText(~\n~~\n~)~\n~AddManifestText(~\n~~\n~)~\n~AddManifestText(~\n~~\n~)~\n~AddManifestText(~\n~~\n~)~\n~AddPermission(android.permission.ACCESS_FINE_LOCATION)~\n~AddPermission(android.permission.BLUETOOTH_ADVERTISE)~\n~AddPermission(android.permission.BLUETOOTH_CONNECT)~\n~AddPermission(android.permission.BLUETOOTH_SCAN)~\n~AddManifestText(~\n~~\n~) 'in order to access the device non-resettable identifiers such as IMEI and serial number.~\n~~\n~'///////////////////////// FLP Y PUSH /////////////~\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~'//////////////////////////////////////////////////////~\n~'Le da mas memoria a la aplicacion~\n~SetApplicationAttribute(android:largeHeap, "true")~\n~ AddApplicationText(~\n~ ~\n~ ~\n~ ~\n~ )~\n~ CreateResource(xml, provider_paths,~\n~ ~\n~ ~\n~ ~\n~ ~\n~ ~\n~ )~\n~~\n~'Si al cargar un mapa de google manda este error "java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion". agregar la siguiente linea:~\n~AddApplicationText()~\n~SetApplicationAttribute(android:allowBackup, "false")~\n~AddManifestText() +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~AddApplicationText(~\n~)~\n~'Set activity to Landscape~\n~SetActivityAttribute(foto, android:screenOrientation, "landscape")~\n~AddApplicationText(~\n~~\n~ ~\n~)~\n~AddManifestText(~\n~~\n~)~\n~'''' para el teclado~\n~ SetActivityAttribute(main, android:windowSoftInputMode, adjustResize|stateHidden)~\n~ SetApplicationAttribute(android:allowBackup, "false")~\n~ SetServiceAttribute(Tracker, android:foregroundServiceType, "location")~\n~ ~\n~ AddManifestText(~\n~~\n~)~\n~''CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)~\n~ 'End of default text.~\n~ ~\n~SetApplicationAttribute(android:usesCleartextTraffic, "true")~\n~ AddManifestText(~\n~~\n~)~\n~AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)~\n~AddManifestText(~\n~~\n~)~\n~AddManifestText()~\n~'AddManifestText()~\n~'AddManifestText()~\n~'AddManifestText()~\n~~\n~AddPermission(android.permission.ACCESS_FINE_LOCATION)~\n~AddPermission(android.permission.BLUETOOTH_ADVERTISE)~\n~AddPermission(android.permission.BLUETOOTH_CONNECT)~\n~AddPermission(android.permission.BLUETOOTH_SCAN)~\n~~\n~AddPermission(android.permission.MANAGE_EXTERNAL_STORAGE)~\n~AddManifestText() 'in order to access the device non-resettable identifiers such as IMEI and serial number.~\n~~\n~'///////////////////////// FLP Y PUSH /////////////~\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~'//////////////////////////////////////////////////////~\n~'Le da mas memoria a la aplicacion~\n~SetApplicationAttribute(android:largeHeap, "true")~\n~AddApplicationText(~\n~ ~\n~ ~\n~ ~\n~)~\n~CreateResource(xml, provider_paths, ~\n~~\n~ ~\n~ ~\n~ ~\n~~\n~)~\n~~\n~'Si al cargar un mapa de google manda este error "java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion". agregar la siguiente linea:~\n~AddApplicationText()~\n~SetApplicationAttribute(android:allowBackup, "false")~\n~AddManifestText()~\n~AddApplicationText(~\n~~\n~ ~\n~ ) Module1=B4XMainPage Module10=C_Pedidos Module11=C_Principal @@ -151,13 +152,16 @@ Module2=C_CheckList Module20=errorManager Module21=EscPosPrinter Module22=foto -Module23=MAPA_RUTAS -Module24=Mods -Module25=SD_Spinner -Module26=Starter -Module27=Subs -Module28=Tracker +Module23=kms_helperSubs +Module24=ManageExternalStorage +Module25=MAPA_RUTAS +Module26=Mods +Module27=NotificationService +Module28=SD_Spinner +Module29=Starter Module3=C_Cliente +Module30=Subs +Module31=Tracker Module4=C_Clientes Module5=C_Historico Module6=C_Mapas @@ -165,8 +169,8 @@ Module7=C_Nota Module8=C_NoVenta Module9=C_NuevoCliente NumberOfFiles=53 -NumberOfLibraries=29 -NumberOfModules=28 +NumberOfLibraries=30 +NumberOfModules=31 Version=12.5 @EndOfDesignText@ #Region Project Attributes diff --git a/B4A/KelloggsV4.b4a.meta b/B4A/KelloggsV4.b4a.meta index 8f24261..1a26da9 100644 --- a/B4A/KelloggsV4.b4a.meta +++ b/B4A/KelloggsV4.b4a.meta @@ -20,7 +20,10 @@ ModuleBookmarks25= ModuleBookmarks26= ModuleBookmarks27= ModuleBookmarks28= +ModuleBookmarks29= ModuleBookmarks3= +ModuleBookmarks30= +ModuleBookmarks31= ModuleBookmarks4= ModuleBookmarks5= ModuleBookmarks6= @@ -49,7 +52,10 @@ ModuleBreakpoints25= ModuleBreakpoints26= ModuleBreakpoints27= ModuleBreakpoints28= +ModuleBreakpoints29= ModuleBreakpoints3= +ModuleBreakpoints30= +ModuleBreakpoints31= ModuleBreakpoints4= ModuleBreakpoints5= ModuleBreakpoints6= @@ -72,19 +78,22 @@ ModuleClosedNodes2= ModuleClosedNodes20= ModuleClosedNodes21=20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39 ModuleClosedNodes22= -ModuleClosedNodes23= +ModuleClosedNodes23=6,7,8,9,10 ModuleClosedNodes24= ModuleClosedNodes25= ModuleClosedNodes26= ModuleClosedNodes27= ModuleClosedNodes28= +ModuleClosedNodes29= ModuleClosedNodes3=1 +ModuleClosedNodes30= +ModuleClosedNodes31= ModuleClosedNodes4= ModuleClosedNodes5= ModuleClosedNodes6= ModuleClosedNodes7= ModuleClosedNodes8= ModuleClosedNodes9= -NavigationStack=C_Pedidos,Class_Globals,4,0,C_Cliente,Class_Globals,0,0,C_Cliente,B4XPage_Created,281,0,C_Cliente,Initialize,278,0,C_Cliente,B_VENTA_Click,1918,0,C_Cliente,B4XPage_Appear,452,0,Visual Designer,cliente.bal,-100,2,C_Cliente,ListView1_ItemLongClick,708,0,C_Cliente,GPS_LocationChanged,695,5,C_Productos,lv_prodsPedido_ItemLongClick,886,6,C_Productos,clv_prods_ll_VisibleRangeChanged,1030,0 +NavigationStack=kms_helperSubs,logJobDoneResultados,410,0,kms_helperSubs,CheckNotificationAccess,413,0,C_Principal,descargaCartaPorte,2940,0,C_Principal,cargar_Click,561,0,C_Principal,B4XPage_Appear,321,2,C_Principal,EnableBluetooth,297,0,B4XMainPage,B_SERVER_Click,600,0,B4XMainPage,B4XPage_CloseRequest,520,1,B4XMainPage,JobDone,510,0,C_Principal,GetBA,312,0 SelectedBuild=0 -VisibleModules=1,26,11,14,27,3,4,13,12,2,10 +VisibleModules=1,29,11,23,27,14,30,3,4,13,12 diff --git a/B4A/ManageExternalStorage.bas b/B4A/ManageExternalStorage.bas new file mode 100644 index 0000000..3b05516 --- /dev/null +++ b/B4A/ManageExternalStorage.bas @@ -0,0 +1,79 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=10.7 +@EndOfDesignText@ +' Version 1.00 +#Event: StorageAvailable +Sub Class_Globals + Private ion As Object + Private mCallback As Object + Private mEventName As String + +End Sub + + +' This pretty trivial class is modeled on (plagiarised from!) Erel's ExternalStorage class +' It applies to devices implementing SDK30 and later +' It allows apps to access the internal 'external' storage as was possible on earlier Android versions ussing traditional file I/O +' You must manually add 'AddPermission(android.permission.MANAGE_EXTERNAL_STORAGE)' to the manifest +' You must ensure that you provide the package name of your app in Sub GetPermission +' This class uses the MANAGE_APP_ALL_FILES_ACCESS_PERMISSION intent action to direct users to a system settings page +' They must enable the option on that page to give permission + +'Initializes the object +Public Sub Initialize (Callback As Object, EventName As String) + mCallback = Callback + mEventName = EventName +End Sub + + +' Determine if the app already has MANAGE_EXTERNAL_STORAGE call Environment.isExternalStorageManager() +' Return True if this app already has MANAGE_EXTERNAL_STORAGE permission +Public Sub HasPermission As Boolean + Dim has As Boolean + Dim jo As JavaObject + jo.InitializeStatic("android.os.Environment") + has = jo.RunMethod("isExternalStorageManager", Null) + Return has +End Sub + +' Check whether this app has MANAGE_EXTERNAL_STORAGE permission +' If not show the user a dialog to enable MANAGE_EXTERNAL_STORAGE permission for this app +' Raises the StorageAvailable event in the calling activity when complete +Public Sub GetPermission + If HasPermission Then + RaiseEvent + Return + End If + Dim in As Intent + ' Be sure to reference your app package name in "pakageg:xxx" + in.Initialize("android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION", $"package:${Application.PackageName}"$) + StartActivityForResult(in) +End Sub + + +Private Sub RaiseEvent + Log("Calling : " & mEventName & "_StorageAvailable") + CallSubDelayed(mCallback, mEventName & "_StorageAvailable") +End Sub + + +Private Sub ion_Event (MethodName As String, Args() As Object) As Object + RaiseEvent + Return Null +End Sub + + +Private Sub StartActivityForResult(i As Intent) + Dim jo As JavaObject = GetBA + ion = jo.CreateEvent("anywheresoftware.b4a.IOnActivityResult", "ion", Null) + jo.RunMethod("startActivityForResult", Array As Object(ion, i)) +End Sub + +Private Sub GetBA As Object + Dim jo As JavaObject = Me + Return jo.RunMethod("getBA", Null) +End Sub + diff --git a/B4A/NotificationService.bas b/B4A/NotificationService.bas new file mode 100644 index 0000000..8bd9e86 --- /dev/null +++ b/B4A/NotificationService.bas @@ -0,0 +1,178 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Service +Version=11 +@EndOfDesignText@ +#Region Service Attributes + #StartAtBoot: False +#End Region + +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) As Boolean + 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 diff --git a/B4A/Starter.bas b/B4A/Starter.bas index 58ad8ce..95d159e 100644 --- a/B4A/Starter.bas +++ b/B4A/Starter.bas @@ -26,7 +26,7 @@ Sub Process_Globals 'Para ENVIA_ULTIMA_GPS Dim Timer1 As Timer Dim Interval As Int = 300 - Dim server As String + Dim DBReqServer As String Dim pe As PhoneEvents Dim ph As Phone Dim marcaCel As String = ph.manufacturer @@ -66,15 +66,15 @@ Sub Service_Create ubicacionActual.Initialize pe.Initialize("pe") 'Para obtener la bateria db = s.dbInit 'Inicializamos BD. - server = "http://keymon.lat:1782" + DBReqServer = "http://keymon.lat:1782" Private c As Cursor = db.ExecQuery($"select CAT_VA_VALOR from CAT_VARIABLES WHERE CAT_VA_DESCRIPCION = 'SERVER'"$) If c.RowCount > 0 Then c.Position = 0 - server = c.GetString("CAT_VA_VALOR") + DBReqServer = c.GetString("CAT_VA_VALOR") End If c.Close - reqManager.Initialize(Me, server) 'Inicializamos reqManager. - If Logger Then Log($"Starter reqManager server: ${server}"$) + reqManager.Initialize(Me, DBReqServer) 'Inicializamos reqManager. + If Logger Then Log($"Starter reqManager server: ${DBReqServer}"$) 'Para los Logs #if RELEASE logcat.LogCatStart(Array As String("-v","raw","*:F","B4A:v"), "logcat") @@ -133,10 +133,10 @@ Private Sub Timer1_Tick ENVIA_ULTIMA_GPS 'Comentado para que no estorbe hasta que no esten los queries correctos en el config.properties End Sub -Sub reinicializaReqManager - reqManager.Initialize(Me, server) - If Logger Then Log(server) -End Sub +'Sub reinicializaReqManager +' reqManager.Initialize(Me, server) +' If Logger Then Log(server) +'End Sub Sub ENVIA_ULTIMA_GPS If Logger Then Log("Iniciamos ENVIA_ULTIMA_GPS") @@ -227,3 +227,12 @@ Sub revisaBD 'ignore If Not(File.Exists(ruta, "kmt.db")) Then File.Copy(File.DirAssets, "kmt.db", ruta, "kmt.db") If Not(db.IsInitialized) Then db.Initialize(ruta, "kmt.db", True) End Sub + +'Inicializa el reqServer con la dirección dada y lo guarda en CAT_VARIABLES. +Sub reinicializaReqManager(srv As String) + db.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("SERVER")) + db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("SERVER", srv)) + DBReqServer = srv + reqManager.Initialize(Me, srv) +' LogColor(srv, Colors.red) +End Sub \ No newline at end of file diff --git a/B4A/Subs.bas b/B4A/Subs.bas index 40c027f..992507a 100644 --- a/B4A/Subs.bas +++ b/B4A/Subs.bas @@ -687,7 +687,7 @@ End Sub 'Guarda el nombre de la pagina en base de datos la muestra. Sub iniciaActividad(ia As String) If ia <> "" And ia <> Null Then - If Starter.logger Then LogColor($"Guardamos en BD '${ia}'"$, Colors.Yellow) +' If Starter.logger Then LogColor($"Guardamos en BD '${ia}'"$, Colors.Yellow) Starter.db.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("ULTIMOMODULO")) Starter.db.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("ULTIMOMODULO", ia)) B4XPages.ShowPage(ia) diff --git a/B4A/kms_helperSubs.bas b/B4A/kms_helperSubs.bas new file mode 100644 index 0000000..979f055 --- /dev/null +++ b/B4A/kms_helperSubs.bas @@ -0,0 +1,550 @@ +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 skmt, rkmt As SQL + Private EventName As String 'ignore + Private CallBack As Object 'ignore + Dim rp As RuntimePermissions + Dim safePath As String + Dim fechaHoy As String + Dim skmtAttached As Boolean = False + '####### MES Vars ###### + Private ion As Object + Dim device As Phone + Private mesCallback As Object + Private mesEventName As String + Dim RD_Init_IsInitialized As Boolean = False + Dim btAdmin As BluetoothAdmin +End Sub + +'Inicializa la clase "kms_helperSubs". +Public Sub Initialize (vCallback As Object, vEventName As String) As Object + EventName = vEventName + CallBack = vCallback + 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 +'End Sub + +'RD - Inicializa Respaldo Diario +Sub RD_Init + Log("************************** " & safePath) + Dim Dirp As String = File.DirRootExternal + Dim Dir As String +' Dim Dir2 As String + Try + File.MakeDir(Dirp,"/kmts") + Dir = "/kmts" +' Log("creado en kmts " & Dirp & Dir) + Catch + Dir = "" +' Log("creado en raiz") + End Try + safePath = Dirp & Dir + Log($"Safepath:${safePath}"$) + Private name() As String = Regex.split(" ", Application.LabelName) + rkmt.Initialize(safePath,$"${name(0)}.rkmt.km"$, True) + skmt.Initialize(File.DirInternal,"kmt.db", False) +' rkmt.ExecNonQuery($"create table if not exists pedidos (pe_folio NUMERIC, pe_desc NUMERIC, pe_costo_sin TEXT, pe_ruta TEXT, pe_cedis TEXT, pe_costo_tot NUMERIC, pe_costou NUMERIC, pe_cant NUMERIC, pe_pronombre TEXT, pe_proid TEXT, pe_cliente TEXT, pe_fecha TEXT, pe_usuario TEXT, pe_envio_ok TEXT)"$) +' rkmt.ExecNonQuery($"create table if not exists inventarios (cat_gp_iniciativa TEXT, cat_gp_tipoprod TEXT, cat_gp_dev TEXT, cat_gp_almacen NUMERIC, cat_gp_id TEXT, cat_gp_nombre TEXT, cat_gp_imp1 TEXT, cat_gp_imp2 TEXT, cat_gp_precio TEXT, cat_gp_clasif TEXT, cat_gp_sts TEXT, cat_gp_tipo TEXT, cat_gp_subtipo TEXT, cat_gp_tipoprod2 TEXT, fecha TEXT)"$) +'' rkmt.ExecNonQuery($"create table if not exists inventarios2 (cat_gp_iniciativa TEXT, cat_gp_tipoprod TEXT, cat_gp_dev TEXT, cat_gp_almacen NUMERIC, cat_gp_id TEXT, cat_gp_nombre TEXT, cat_gp_imp1 TEXT, cat_gp_imp2 TEXT, cat_gp_precio TEXT, cat_gp_clasif TEXT, cat_gp_sts TEXT, cat_gp_tipo TEXT, cat_gp_subtipo TEXT, cat_gp_tipoprod2 TEXT, fecha TEXT)"$) +' rkmt.ExecNonQuery($"create table if not exists paquetes (cat_dp_precio_simptos TEXT, cat_dp_precio TEXT, cat_dp_almacen TEXT, cat_dp_id TEXT, cat_dp_idprod TEXT, cat_dp_tipo TEXT, cat_dp_pzas TEXT, cat_dp_usuario TEXT, cat_dp_fecha TEXT, cat_dp_regalo TEXT, cat_dp_clasif TEXT, fecha TEXT)"$) + If chkIfTableExists(skmt, "PEDIDO") Then rkmt.ExecNonQuery($"create table if not exists PEDIDO (${getTableColumnList(skmt, "PEDIDO")}, FECHA TEXT)"$) + If chkIfTableExists(skmt, "CAT_DETALLES_PAQ") Then rkmt.ExecNonQuery($"create table if not exists CAT_DETALLES_PAQ (${getTableColumnList(skmt, "CAT_DETALLES_PAQ")}, FECHA TEXT)"$) + If chkIfTableExists(skmt, "CAT_GUNAPROD") Then rkmt.ExecNonQuery($"create table if not exists CAT_GUNAPROD (${getTableColumnList(skmt, "CAT_GUNAPROD")}, FECHA TEXT)"$) + If chkIfTableExists(skmt, "CAT_GUNAPROD2") Then rkmt.ExecNonQuery($"create table if not exists CAT_GUNAPROD2 (${getTableColumnList(skmt, "CAT_GUNAPROD2")}, FECHA TEXT)"$) + If chkIfTableExists(skmt, "kmt_info") Then rkmt.ExecNonQuery($"create table if not exists kmt_info (${getTableColumnList(skmt, "kmt_info")}, FECHA TEXT)"$) + DateTime.DateFormat = "MM/dd/yyyy" + fechaHoy = DateTime.Date(DateTime.Now) + Log("RKMTS: " & rkmt.IsInitialized) + If revisaSkmtAttached And rkmt.IsInitialized Then RD_Init_IsInitialized = True Else RD_Init_IsInitialized = False +End Sub + +'RD - Revisa si esta montada "kmt.db" como "skmt1" y si no, la monta +'Para que "rkmt" vea a "skmt", es necesario montarla (attach). +Sub revisaSkmtAttached As Boolean + skmtAttached = False + Dim rs As ResultSet = rkmt.ExecQuery("SELECT * FROM pragma_database_list") + Do While rs.NextRow 'Revisamos si esta montada "kmt.db" como "skmt1" y si no, la montamos. + If rs.GetString("name") = "skmt1" Then skmtAttached = True + Loop + If Not(skmtAttached) Then + rkmt.ExecNonQuery($"attach database '${File.Combine(File.DirInternal, "kmt.db")}' as skmt1;"$) + skmtAttached = True + End If + Return skmtAttached +End Sub + +'Inicializa la BD con "kmt.db" en "File.DirInternal", si el archivo no existe, lo copia desde "File.DirAssets". +'Ej: dim skmt as sql = dbInit +Sub dbInit As SQL 'ignore + Private db 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 + +'RD - Copia la tabla PEDIDO a rkmt.db en la tarjeta del celular. +Sub RD_respalda_pedido + Private inicio As String = DateTime.Now +' Log("Copiando PEDIDO ...") + Private lasCols As String = getTableColumnListName(skmt, "PEDIDO") + rkmt.BeginTransaction + rkmt.ExecNonQuery($"delete from PEDIDO where FECHA = '${fechaHoy}'"$) + rkmt.ExecNonQuery($"insert into PEDIDO (${lasCols}, FECHA) select ${lasCols}, '${fechaHoy}' as FECHA from skmt1.PEDIDO where substr(pe_fecha, 1, 10) = '${fechaHoy}'"$) + rkmt.TransactionSuccessful 'Si no se pone TransactionSuccessful no se escribe NADA!! + rkmt.EndTransaction + Log(((DateTime.Now - inicio)/1000) & " segs") +End Sub + +'RD - Copia la tabla CAT_GUNAPRODS a rkmt.db en la tarjeta del celular. +Sub RD_respalda_cat_gunaprod + Private inicio As String = DateTime.Now +' Log("Copiando CAT_GUNAPROD ...") + Private lasCols As String = getTableColumnListName(skmt, "CAT_GUNAPROD") + lasCols = lasCols.Replace(", CAT_GP_IMG", "") 'Quitamos la imagen del respaldo. + rkmt.BeginTransaction + rkmt.ExecNonQuery($"delete from CAT_GUNAPROD where FECHA = '${fechaHoy}'"$) + rkmt.ExecNonQuery($"insert into CAT_GUNAPROD (${lasCols}, FECHA) select ${lasCols}, '${fechaHoy}' as FECHA from skmt1.CAT_GUNAPROD"$) + rkmt.TransactionSuccessful 'Si no se pone TransactionSuccessful no se escribe NADA!! + rkmt.EndTransaction + Log(((DateTime.Now - inicio)/1000) & " segs") +End Sub + +'RD - Copia la tabla CAT_GUNAPROD2 a rkmt.db en la tarjeta del celular. +Sub RD_respalda_cat_gunaprod2 + Private inicio As String = DateTime.Now +' Log("Copiando CAT_GUNAPROD2 ...") + Private lasCols As String = getTableColumnListName(skmt, "CAT_GUNAPROD2") + lasCols = lasCols.Replace(", CAT_GP_IMG", "") 'Quitamos la imagen del respaldo. + rkmt.BeginTransaction + rkmt.ExecNonQuery($"delete from CAT_GUNAPROD2 where FECHA = '${fechaHoy}'"$) + rkmt.ExecNonQuery($"insert into CAT_GUNAPROD2 (${lasCols}, FECHA) select ${lasCols}, '${fechaHoy}' as FECHA from skmt1.CAT_GUNAPROD2"$) + rkmt.TransactionSuccessful 'Si no se pone TransactionSuccessful no se escribe NADA!! + rkmt.EndTransaction + Log(((DateTime.Now - inicio)/1000) & " segs") +End Sub + +'RD - Copia la tabla CAT_DETALLE_PAQ a rkmt.db en la tarjeta del celular. +Sub RD_respalda_cat_detalle_paq + Private inicio As String = DateTime.Now +' Log("Copiando CAT_DETALLES_PAQ ...") + Private lasCols As String = getTableColumnListName(skmt, "CAT_DETALLES_PAQ") + If rkmt.IsInitialized Then + rkmt.BeginTransaction + rkmt.ExecNonQuery($"delete from CAT_DETALLES_PAQ where fecha = '${fechaHoy}'"$) + rkmt.ExecNonQuery($"insert into CAT_DETALLES_PAQ (${lasCols}, FECHA) select ${lasCols}, '${fechaHoy}' as FECHA from skmt1.CAT_DETALLES_PAQ"$) + rkmt.TransactionSuccessful 'Si no se pone TransactionSuccessful no se escribe NADA!! + rkmt.EndTransaction + Log(((DateTime.Now - inicio)/1000) & " segs") + End If +End Sub + +'RD - Copia la tabla CAT_DETALLE_PAQ a rkmt.db en la tarjeta del celular. +Sub RD_respalda_kmt_info + Private inicio As String = DateTime.Now +' Log("Copiando kmt_info ...") + Private lasCols As String = getTableColumnListName(skmt, "kmt_info") + rkmt.BeginTransaction + rkmt.ExecNonQuery($"delete from kmt_info where fecha = '${fechaHoy}'"$) + rkmt.ExecNonQuery($"insert into kmt_info (${lasCols}, FECHA) select ${lasCols}, '${fechaHoy}' as FECHA from skmt1.kmt_info"$) + rkmt.TransactionSuccessful 'Si no se pone TransactionSuccessful no se escribe NADA!! + rkmt.EndTransaction + Log(((DateTime.Now - inicio)/1000) & " segs") +End Sub + +'RD - Realiza un "vacuum" de la base de datos "rkmt". +Sub RD_vacuum 'ignore + Log("Vacuum") + rkmt.ExecNonQuery("vacuum;") +End Sub + +'Agrega una columna a la tabla especificada. +'Hay que indicar el "tipo" de la columna (TEXT, INTEGER, ETC) +'Ej. agregaColumna(DB, "TABLA", "COLUMNA", "TIPO") +Sub agregaColumna(db As SQL, 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 los nombres y tipos de las columnas de una tabla dada. +Sub getTableColumnList(db As SQL, table As String) As String 'ignore + Private l As String = "" + If chkIfTableExists(db, table) Then + Private c As Cursor = db.ExecQuery($"pragma table_info(${table})"$) + If c.RowCount > 0 Then + For i = 0 To c.RowCount - 1 + c.Position = i + If l.Length = 0 Then + l = $"${c.GetString("name")} ${c.GetString("type")}"$ + Else + l = $"${l}, ${c.GetString("name")} ${c.GetString("type")}"$ + End If + Next + End If + Else + Return "No existe la tabla." + End If + c.Close + Return l +End Sub + +'Regresa solo los nombres de las columnas de una tabla dada. +Sub getTableColumnListName(db As SQL, table As String) As String 'ignore + Private l As String = "" + If chkIfTableExists(db, table) Then + Private c As Cursor = db.ExecQuery($"pragma table_info(${table})"$) + If c.RowCount > 0 Then + For i = 0 To c.RowCount - 1 + c.Position = i + If l.Length = 0 Then + l = $"${c.GetString("name")}"$ + Else + l = $"${l}, ${c.GetString("name")}"$ + End If + Next + End If + Else + Return "No existe la tabla." + End If + c.Close + Return l +End Sub + +'Revisa si una tabla dada existe en una base de datos dada, regresa true o false. +Sub chkIfTableExists(db As SQL, table As String) As Boolean 'ignore + Private t As Boolean = False 'ignore + If db.IsInitialized Then + Private c As Cursor = db.ExecQuery($"SELECT name FROM sqlite_master WHERE type='table' AND name='${table}'"$) + If c.RowCount > 0 Then t = True + c.Close + End If + Return t +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) + etiquetaCentrada(True) +End Sub + +Sub etiquetaCentrada(Success As Boolean) + If SubExists(CallBack, EventName & "_etiquetaCentrada") Then + CallSub2(CallBack, EventName & "_etiquetaCentrada", Success) + End If +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 no lo encuentra regresa "SinUsuario" +Sub traeUsuarioDeDB(db As SQL) As String 'ignore + Private c As Cursor + Private u As String = "SinUsuario" + c = db.ExecQuery("select USUARIO from usuarioa") + c.Position=0 + If c.RowCount > 0 Then u = c.GetString("USUARIO") + c.Close + Return u +End Sub + +'Regresa el almacen actual de la base de datos. +Sub traeAlmacen(db As SQL) 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 el nombre del producto desde CAT_GUNAPROD. +Sub traeProdNombre(db As SQL, id As String) As String 'ignore + Private h As Cursor + Private n As String + h = db.ExecQuery2("select CAT_GP_NOMBRE from CAT_GUNAPROD where CAT_GP_ID = ? ", Array As String(id.Trim)) + If h.RowCount > 0 Then + h.Position = 0 + n = h.GetString("CAT_GP_NOMBRE") +' Log(h.RowCount&"|"&id&"|"&n&"|") + End If + h.Close + If n = Null Or n="" Then n = "N/A" +' Log(h.RowCount&"|"&id&"|"&n&"|") + Return n +End Sub + +'Regresa la ruta actual de la base de datos. +Sub traeRuta(db As SQL) 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 + +'Regresa el cliente actual de la base de dtos (CUENTAA). +Sub traeCliente(db As SQL) As String 'ignore + Private c As Cursor + Private cl As String + c = db.ExecQuery("Select CUENTA from cuentaa") + c.Position=0 + cl = c.GetString("CUENTA") + c.Close + Return cl +End Sub + +'Regresa en un mapa el total de productos y monto del pedido del cliente actual +'resultado = {"productos":"antidad_de_productos", "monto":"costo_total"} +Sub traeTotalesClienteActual(db As SQL) As Map 'ignore + Private m As Map + m.Initialize + Private c_prodsX As Cursor = db.ExecQuery("select ifnull(sum(PE_CANT), 0) as cantProds, ifnull(sum(PE_COSTO_TOT), 0) as costoTotal FROM PEDIDO WHERE PE_CLIENTE IN (Select CUENTA from cuentaa) order by PE_PRONOMBRE asc") + c_prodsX.Position = 0 +' LogColor($"Productos de la orden: ${c_prodsX.GetString("cantProds")}, Total: ${c_prodsX.GetString("costoTotal")}"$, Colors.red) + m = CreateMap("productos": c_prodsX.GetString("cantProds"), "monto" : c_prodsX.GetString("costoTotal")) + Return m +End Sub + +'Borra el pedido del cliente actual. +'Borra los registros de la tabla "PEDIDO" y "PEDIDO_CLIENTE" +'Actualiza las tablas "cat_gunaprod" y "kmt_info". +Sub borraPedidoClienteActual(db As SQL) As String 'ignore + Private thisC As Cursor + thisC = db.ExecQuery("select PE_PROID,PE_CANT FROM PEDIDO where pe_cliente in (Select CUENTA from cuentaa) ") + If thisC.RowCount>0 Then + For i=0 To thisC.RowCount -1 + thisC.Position=i + db.ExecNonQuery2("update cat_gunaprod set cat_gp_almacen = cat_gp_almacen + ? where cat_gp_id = ?", Array As Object(thisC.GetString("PE_CANT"),thisC.GetString("PE_PROID"))) + db.ExecNonQuery2("INSERT INTO INVENT_X_ENVIAR (ALMACEN , PROID , CANTIDAD ) VALUES(?,?,?) ", Array As Object (traeAlmacen(db), thisC.GetString("PE_PROID"),thisC.GetString("PE_CANT")* -1)) + Next + End If + db.ExecNonQuery("delete from pedido_cliente where pc_cliente in (Select CUENTA from cuentaa)") + db.ExecNonQuery("delete from pedido where pe_cliente in (Select CUENTA from cuentaa)") + db.ExecNonQuery("UPDATE kmt_info set gestion = 0 where CAT_CL_CODIGO In (select cuenta from cuentaa)") + Return 1 +End Sub + +'Regresa verdadero si la columna gestion en la tabla "kmt_info" tene valor 2. +'si no, entonces regresa falso. +Sub pedidoGuardado(db As SQL) As Boolean 'ignore + Private guardado As Boolean = False + Private g As Cursor = db.ExecQuery("select gestion from kmt_info where CAT_CL_CODIGO in (Select CUENTA from cuentaa)") + If g.RowCount > 0 Then + g.Position=0 + If g.GetString("gestion") = "2" Then guardado = True + End If + Log($"Guardado=${guardado}"$) + Return guardado +End Sub + +'Regresa verdadero si hay pedido en la tabla "PEDIDO" del cliente actual. +Sub hayPedido(db As SQL) As Boolean 'ignore + Private thisC As Cursor = db.ExecQuery($"select count(PE_CLIENTE) as hayPedido from PEDIDO where PE_CLIENTE = '${traeCliente(db)}'"$) + thisC.Position = 0 + Private hay As Boolean = False + If thisC.GetInt("hayPedido") > 0 Then hay = True +' Log($"Cliente actual=${traeCliente}, hayPedido=${hay}"$) + Return hay +End Sub + +'Guarda el nombre y version de la app en CAT_VARIABLES. +Sub guardaAppInfo(db As SQL) 'ignore + db.ExecNonQuery("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = 'EMPRESA' or CAT_VA_DESCRIPCION = 'APP_NAME' or CAT_VA_DESCRIPCION = 'APP_VERSION'") + db.ExecNonQuery($"insert into CAT_VARIABLES (CAT_VA_DESCRIPCION, CAT_VA_VALOR) values ('APP_NAME', '${Application.LabelName}')"$) + db.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 + +'Revisa si la aplicación tiene permiso para acceder a las notificaciones. +Sub CheckNotificationAccess As Boolean + 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 + +'################ Manage External Storage (MES) ######################### +' +''Inicializa "Manage External Storage" (MES), que nos da acceso a la tarjeta de memoria en Android 11+ +'Public Sub MES_Init (mCallBack As Object, mEventName As String) +' mesCallback = mCallBack +' mesEventName = mEventName +'End Sub +' +'Sub MES_checkPermission 'ignore +'' ' get the device SDK version +'' Dim SdkVersion As Int = device.SdkVersion +'' ' Choose which permission to request in order to access external storgage +'' If SdkVersion < 30 Then +''' Log("SDK = " & SdkVersion & " : Requesting WRITE_EXTERNAL_STORAGE permission") +'' Dim rp As RuntimePermissions +'' rp.CheckAndRequestPermission(rp.PERMISSION_WRITE_EXTERNAL_STORAGE) ' Implicit read capability if granted +'' Wait For Activity_PermissionResult (Permission As String, Result As Boolean) +''' Log($"PERMISSION_WRITE_EXTERNAL_STORAGE = ${Result}"$) +'' Else +''' Log("SDK = " & SdkVersion & " : Requesting MANAGE_EXTERNAL_STORAGE permission") +''' Log("On Entry MANAGE_EXTERNAL_STORAGE = " & MES1.HasPermission) +'' If Not(MES_HasPermission) Then +'' MsgboxAsync("This app requires access to all files, please enable the option", "Manage All Files") +'' Wait For Msgbox_Result(Res As Int) +''' Log("Getting permission") +'' MES_GetPermission +'' Wait For MES_StorageAvailable +'' End If +'' End If +'End Sub +' +'' Determine if the app already has MANAGE_EXTERNAL_STORAGE call Environment.isExternalStorageManager() +'' Return True if this app already has MANAGE_EXTERNAL_STORAGE permission +'Public Sub MES_HasPermission As Boolean +' Dim has As Boolean +' Dim jo As JavaObject +' jo.InitializeStatic("android.os.Environment") +' has = jo.RunMethod("isExternalStorageManager", Null) +' Return has +'End Sub +' +'' Check whether this app has MANAGE_EXTERNAL_STORAGE permission +'' If not show the user a dialog to enable MANAGE_EXTERNAL_STORAGE permission for this app +'' Raises the StorageAvailable event in the calling activity when complete +'Public Sub MES_GetPermission +' If MES_HasPermission Then +' RaiseEvent +' Return +' End If +' Dim in As Intent +' ' Be sure to reference your app package name in "pakageg:xxx" +' in.Initialize("android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION", $"package:${Application.PackageName}"$) +' StartActivityForResult(in) +'End Sub +' +'Private Sub RaiseEvent +' Log("Calling : " & mesEventName & "_StorageAvailable") +' CallSubDelayed(mesCallback, mesEventName & "_StorageAvailable") +'End Sub +' +'Private Sub ion_Event (MethodName As String, Args() As Object) As Object +' RaiseEvent +' Return Null +'End Sub +' +'Private Sub StartActivityForResult(i As Intent) +' Dim jo As JavaObject = MES_GetBA +' ion = jo.CreateEvent("anywheresoftware.b4a.IOnActivityResult", "ion", Null) +' jo.RunMethod("startActivityForResult", Array As Object(ion, i)) +'End Sub +' +'Private Sub MES_GetBA As Object +' Dim jo As JavaObject = Me +' Return jo.RunMethod("getBA", Null) +'End Sub +'################ TERMINA Manage External Storage (MES) ######################### + + +'################ INICIA ENABLE BLUETOOTH ######################### +Sub StartBluetooth 'ignore + btAdmin.Initialize("btAdmin") + Log("btAdmin: " & btAdmin.IsEnabled) + If btAdmin.IsEnabled = False Then + Wait For (EnableBluetooth) Complete (Success As Boolean) + If Success = False Then + ToastMessageShow("Failed to enable bluetooth", True) + End If + Log(Success) + End If + Log($"BTADMIN: ${btAdmin.IsEnabled}"$) +End Sub + +Sub EnableBluetooth As ResumableSub + ToastMessageShow("Enabling Bluetooth adapter...", False) + Private ph As Phone + If ph.SdkVersion >= 31 Then + rp.CheckAndRequest("android.permission.BLUETOOTH_CONNECT") + Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) + If Result = False Then Return False + Log($"BTCONNECT: ${Result}"$) + If ph.SdkVersion >= 33 Then + Dim in As Intent + in.Initialize("android.bluetooth.adapter.action.REQUEST_ENABLE", "") + StartActivityForResult(in) + Wait For ion_Event (MethodName As String, Args() As Object) + Return btAdmin.IsEnabled + End If + End If + Return btAdmin.Enable +End Sub + +Private Sub GetBA As Object + Dim jo As JavaObject = Me + Return jo.RunMethod("getBA", Null) +End Sub + +Private Sub StartActivityForResult(i As Intent) + Dim jo As JavaObject = GetBA + ion = jo.CreateEvent("anywheresoftware.b4a.IOnActivityResult", "ion", Null) + jo.RunMethod("startActivityForResult", Array As Object(ion, i)) +End Sub +'################ TERMINA ENABLE BLUETOOTH ######################### \ No newline at end of file