. Commit inicial.

This commit is contained in:
Jose Alberto Guerra Ugalde
2024-11-07 02:41:50 -06:00
parent 0fcaea2441
commit f512b64a2e
17 changed files with 2520 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
**/Objects
**/AutoBackups

242
B4A/B4XMainPage.bas Normal file
View File

@@ -0,0 +1,242 @@
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=..\..\
'###########################################################################################################
'###################### PUSH TORTOISE GIT #########################################################
'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=TortoiseGitProc&Args=/command:commit&Args=/path:"./../../"&Args=/closeonend:2
'###########################################################################################################
#End Region
'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip
Sub Class_Globals
Private Root As B4XView
Private xui As XUI
Dim wifi As MLwifi
Dim wifiS As MLScan
Public manager As AdminManager
' Dim ruta As String
Dim fechaRuta As String
Dim laUbicacion As Location
Private b_pong As Button
Private et_id As EditText
Private b_guardarId As Button
Private l_coords As Label
Dim l_lastUpdate As Label
Private l_id As Label
' Private b_flpConnect As Button
Private b_exit As Button
Private l_version As Label
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
Root.LoadLayout("layout")
l_version.Text = Application.VersionName
' ruta = File.DirInternal
Subs.getPhnId
et_id.Text = Starter.devModel.trim
getSSID
b_pong.Left = Round(Root.Width/2)-(b_pong.Width/2)
' b_flpConnect.Left = Round(Activity.Width/2)-(b_flpConnect.Width/2)
b_exit.Left = Round(Root.Width/2)-(b_exit.Width/2)
l_id.Left = (Root.Width / 2) - (l_id.Width / 2)
l_lastUpdate.Left = (Root.Width / 2) - (l_lastUpdate.Width / 2)
b_guardarId.Left = (Root.Width / 2) - (b_guardarId.Width / 2)
et_id.Left = (Root.Width / 2) - (et_id.Width / 2)
chkPermisosUbicacion 'Permisos de ubicacion para Tracker
chkPermisosAlmacenamientoExterno
chkPermisosLeerLlamadas 'Permisos de telefono para registrar llamadas
chkPermisosEstadoTelefono
End Sub
Sub B4XPage_Appear
Subs.getPhnId
et_id.Text = Starter.devModel.Trim
getSSID
getAdminRights
l_lastUpdate.Text = Subs.fechaKMT(Starter.lastLocUpdate)
' ruta = File.DirInternal
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
ponCoords
End Sub
'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.
Sub b_pong_Click
CallSubDelayed(Tracker, "StartFLP")
If Starter.UUC.IsInitialized Then Subs.mandaLocAServer(Starter.devModel.Trim)
' Dim params As Map = CreateMap("topic": FireBaseMessaging.Sprvsr,"title":"Prueba Trckr", "body":"Prueba Trckr", "d":Starter.devModel, "t":"pong")
' CallSubDelayed2(FirebaseMessaging, "SendMessage",params)
If Starter.logger Then Log("Start wifi scan")
wifiS.startscan("WiFi", True)
Wait For WiFi_ScanDone (Results() As String, Count As Int)
End Sub
Sub b_pong_LongClick
' copiaDB
CallSubDelayed(Tracker, "StartFLP")
If Starter.UUC.IsInitialized Then Subs.mandaLocAServer(Starter.devModel.Trim)
' Dim params As Map = CreateMap("topic": FireBaseMessaging.Sprvsr,"title":"Prueba Trckr", "body":l_coords.Text, "d":Starter.devModel, "t":"au")
' CallSubDelayed2(FirebaseMessaging, "SendMessage",params)
If Starter.logger Then Log("Start wifi scan")
wifiS.startscan("WiFi", True)
Wait For WiFi_ScanDone (Results() As String, Count As Int)
End Sub
'Obtenemos permisos de almacenamiento.
Sub chkPermisosAlmacenamientoExterno
Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
If Result Then
' If Starter.logger Then Log("Permisos de almacenamiento externo OK")
Else
' ToastMessageShow("SIN permisos de almacenamiento externo", True)
End If
End Sub
'Obtenemos permisos de ubicacion.
Sub chkPermisosUbicacion
' If Starter.logger Then Log("Revisamos permisos de ubicación.")
Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION)
Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
If Result Then
StartService(Tracker)
If Starter.logger Then Log("Start Tracker")
Else
' ToastMessageShow("SIN permisos de ubicacion", True)
End If
' Starter.rp.CheckAndRequest(Starter.rp. )
' Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
' If Result Then
' StartService(Tracker)
' If Starter.logger Then Log("Start Tracker")
' Else
'' ToastMessageShow("SIN permisos de ubicacion", True)
' End If
End Sub
'Obtenemos permisos de llamadas.
Sub chkPermisosLeerLlamadas
Starter.rp.CheckAndRequest("android.permission.READ_CALL_LOG")
wait for Activity_PermissionResult(permission As String, result As Boolean)
Log("READ_CALL_LOG: " & result)
End Sub
'Obtenemos permisos de estado de telefono.
Sub chkPermisosEstadoTelefono
Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_READ_PHONE_STATE)
wait for Activity_PermissionResult(permission As String, result As Boolean)
If Starter.logger Then Log("READ_PHONE_STATE: " & result)
End Sub
Sub getSSID
If wifi.isWifiConnected Then
Subs.ssid = wifi.WifiSSID
End If
End Sub
Sub getAdminRights
If manager.Enabled = False Then
manager.Enable("Please enable in order to get access to the secured server.")
End If
End Sub
'Sub wifiScanned_ScanDone
' Log("//////////////////////////////wifi_conected_result")
' ToastMessageShow("Wifi_ConnectionResult",True)
' If wifi.isWifiConnected Then
' ssid = wifi.WifiSSID
' End If
'End Sub
Sub copiaDB 'ignore
' Log("ruta="&ruta)
' Log("File.DirInternal="&File.DirInternal)
' Log("File.DirRootExternal="&File.DirRootExternal)
' Log("File.DirDefaultExternal="&File.DirDefaultExternal)
' Log(Starter.rp.GetSafeDirDefaultExternal(""))
' Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
' Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
' If Result Then
' If Starter.logger Then Log("Tenemos permisos de escritura.")
' File.Copy(File.DirInternal , "gps_hist.db", File.DirDefaultExternal, "gps_hist.db")
' If Starter.logger Then Log($"DB escrita a ${File.DirDefaultExternal}"$)
' ToastMessageShow($"DB escrita a ${File.DirDefaultExternal}"$, True)
' End If
End Sub
Private Sub b_guardarId_Click
If et_id.Text.Length > 2 Then 'Si tenemos valor para ID
File.WriteString(File.DirInternal, "phnId.txt", et_id.Text.trim) 'Sobreescribimos archivo IdPersonal.txt con ID
Starter.devModel = et_id.Text.Trim
If Starter.logger Then Log("Tenemos ID: "& et_id.Text.Trim & " "&File.DirInternal&"/phnId.txt sobreescrito")
Else If et_id.Text.Length < 3 Then ' Si no tenemos valor, lo leemos de IdPersonal.txt
Dim s As String = File.ReadString(File.DirInternal, "phnId.txt")
Starter.devModel = s
If Starter.logger Then Log("Leemos id de "&File.DirInternal&"/phnId.txt")
et_id.Text = Starter.devModel.Trim
If Starter.logger Then Log(Starter.devModel.Trim)
End If
If laUbicacion.IsInitialized Then Subs.mandaLocAServer(Starter.devModel.Trim)
End Sub
Sub ponCoords
l_coords.left = (Root.Width/2) - (l_coords.Width/2)
l_coords.Text = $"${Starter.UUC.Latitude},${Starter.UUC.Longitude}"$
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
Sub actualizaLabelUU
l_lastUpdate.Text = Subs.fechaKMT(Starter.lastLocUpdate)
End Sub
'Private Sub b_flpConnect_Click
' Log("Conectamos a FLP")
' CallSubDelayed(Tracker, "flpReConnect")
'End Sub
Private Sub b_exit_Click
' CallSubDelayed(Tracker, "flpReConnect")
Starter.restartTracker
End Sub
Sub b_exit_LongClick
ExitApplication
End Sub

282
B4A/DBRequestManager.bas Normal file
View File

@@ -0,0 +1,282 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Class
Version=6.8
@EndOfDesignText@
'Necesita la libreria RandomAccessFile
'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 - 211027
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.
'Timeout - The http request timeout in ms, or 0 if default (30 secs)
Public Sub ExecuteQuery(Command As DBCommand, Limit As Int, Tag As Object, Timeout As Int) 'Mod por CHV, agregué el parametro Timeout - 211229
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)
If Timeout <> 0 Then j.GetRequest.Timeout = Timeout
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 = ""
Try
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
' Log("HandleJob: " & (DateTime.Now - start))
Catch
Log(LastException)
End Try
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

113
B4A/FLP 3.0.b4a Normal file
View File

@@ -0,0 +1,113 @@
Build1=Default,flp2.chv.com
File1=gps_hist.db
File2=layout.bal
File3=MainPage.bal
FileGroup1=Default Group
FileGroup2=Default Group
FileGroup3=Default Group
Group=Default Group
Library1=administrator
Library10=javaobject
Library11=json
Library12=mlwifi400
Library13=okhttputils2
Library14=phone
Library15=randomaccessfile
Library16=reflection
Library17=replyauto
Library18=runtimepermissions
Library19=sql
Library2=b4xpages
Library20=broadcastreceiver
Library3=byteconverter
Library4=compressstrings
Library5=core
Library6=firebaseanalytics
Library7=firebasenotifications
Library8=fusedlocationprovider
Library9=gps
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~<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33"/>~\n~<supports-screens android:largeScreens="true" ~\n~ android:normalScreens="true" ~\n~ android:smallScreens="true" ~\n~ android:anyDensity="true"/>)~\n~SetApplicationAttribute(android:icon, "@drawable/icon")~\n~SetApplicationAttribute(android:label, "$LABEL$")~\n~CreateResourceFromFile(Macro, Themes.LightTheme)~\n~'End of default text.~\n~AddPermission(android.permission.ACCESS_FINE_LOCATION)~\n~~\n~'Para que aparezca la opcion de ALLOW ALL THE TIME~\n~SetServiceAttribute(Tracker, android:foregroundServiceType, "location")~\n~AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)~\n~~\n~AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)~\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~SetApplicationAttribute(android:usesCleartextTraffic, "true")~\n~AddApplicationText(<receiver android:name="anywheresoftware.b4a.objects.AdminReceiver2"~\n~ android:permission="android.permission.BIND_DEVICE_ADMIN" android:exported="true">~\n~ <meta-data android:name="android.app.device_admin"~\n~ android:resource="@xml/device_admin" />~\n~ <intent-filter>~\n~ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" android:exported="true" />~\n~ </intent-filter>~\n~</receiver>)~\n~~\n~CreateResource(xml, device_admin.xml,~\n~<device-admin xmlns:android="http://schemas.android.com/apk/res/android">~\n~ <uses-policies>~\n~ <limit-password />~\n~ <reset-password />~\n~ <force-lock />~\n~ </uses-policies>~\n~</device-admin>~\n~)~\n~AddPermission(android.permission.SEND_SMS)~\n~AddPermission(android.permission.RECEIVE_SMS)~\n~AddPermission(android.permission.READ_PHONE_STATE)~\n~AddPermission(android.permission.READ_CALL_LOG)~\n~AddApplicationText(~\n~<service android:name="b4a.jsaplication.com.br.ReplyAuto"~\n~ android:label="FLP" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" android:exported="true">~\n~ <intent-filter><action android:name="android.service.notification.NotificationListenerService" android:exported="true" /></intent-filter>~\n~ </service>)~\n~ ~\n~AddPermission(android.permission.RECEIVE_BOOT_COMPLETED)~\n~AddReceiverText(R_Test, <intent-filter>~\n~<action android:name="android.intent.action.BOOT_COMPLETED" android:exported="true"/>~\n~</intent-filter>)
Module1=B4XMainPage
Module10=Tracker
Module2=DBRequestManager
Module3=errorManager
Module4=FirebaseMessaging
Module5=FirebaseMessaging0
Module6=NotificationService
Module7=R_Test
Module8=Starter
Module9=Subs
NumberOfFiles=3
NumberOfLibraries=20
NumberOfModules=10
Version=12.8
@EndOfDesignText@
#Region Project Attributes
#ApplicationLabel: FLP 3.0
#VersionCode: 1
#VersionName: 4.11.06
'SupportedOrientations possible values: unspecified, landscape or portrait.
#SupportedOrientations: portrait
#CanInstallToExternalStorage: False
#AdditionalJar: com.google.android.gms:play-services-location
#End Region
#Region Activity Attributes
#FullScreen: False
#IncludeTitle: True
#End Region
'#BridgeLogger: True
Sub Process_Globals
Public ActionBarHomeClicked As Boolean
End Sub
Sub Globals
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.

36
B4A/FLP 3.0.b4a.meta Normal file
View File

@@ -0,0 +1,36 @@
ModuleBookmarks0=
ModuleBookmarks1=
ModuleBookmarks10=
ModuleBookmarks2=
ModuleBookmarks3=
ModuleBookmarks4=
ModuleBookmarks5=
ModuleBookmarks6=
ModuleBookmarks7=
ModuleBookmarks8=
ModuleBookmarks9=
ModuleBreakpoints0=
ModuleBreakpoints1=
ModuleBreakpoints10=
ModuleBreakpoints2=
ModuleBreakpoints3=
ModuleBreakpoints4=
ModuleBreakpoints5=
ModuleBreakpoints6=
ModuleBreakpoints7=
ModuleBreakpoints8=
ModuleBreakpoints9=
ModuleClosedNodes0=6
ModuleClosedNodes1=
ModuleClosedNodes10=2,3,5,6,7,8,9,10,11,12,14,15
ModuleClosedNodes2=6,7,8,9,10,11,12,13,15,16,17,18
ModuleClosedNodes3=
ModuleClosedNodes4=
ModuleClosedNodes5=
ModuleClosedNodes6=
ModuleClosedNodes7=
ModuleClosedNodes8=3,5,8,9,10,11,12
ModuleClosedNodes9=13
NavigationStack=DBRequestManager,HandleJob,196,5,DBRequestManager,FileToBytes,236,0,DBRequestManager,ImageToBytes,245,0,DBRequestManager,BytesToImage,254,0,Subs,getSSID,166,0,Subs,fechaKMTms,179,0,Subs,fechaKMT,178,2,Subs,guardaInfoEnBD,110,3,Starter,JobDone,259,1,Starter,PE_PhoneStateChanged,189,0,B4XMainPage,b_pong_LongClick,88,0
SelectedBuild=0
VisibleModules=1,8,10,4,9,6,7,2

BIN
B4A/Files/gps_hist.db Normal file

Binary file not shown.

BIN
B4A/Files/layout.bal Normal file

Binary file not shown.

BIN
B4A/Files/mainpage.bal Normal file

Binary file not shown.

87
B4A/FirebaseMessaging.bas Normal file
View File

@@ -0,0 +1,87 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Receiver
Version=12.8
@EndOfDesignText@
'///////////////////////////////////////////////////////////////////////////////////////
'/// Agregar estas lineas al editor de manifiestos
'
' CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)
' CreateResourceFromFile(Macro, FirebaseAnalytics.Firebase)
' CreateResourceFromFile(Macro, FirebaseAnalytics.FirebaseAnalytics)
' CreateResourceFromFile(Macro, FirebaseNotifications.FirebaseNotifications)
'
'/// Agregar modulo de servicio nuevo FirebaseMessaging y copiar este modulo
'
'/// Bajar el archivo google-services.json de la consola de Firebase (https://console.firebase.google.com/)
'/// El nombre de la app en el archivo json tiene que ser el mismo que el nombre del paquete (Proyecto/Conf de Compilacion/Paquete)
'
'/// En Starter agregar esta linea
'
' Sub Service_Create
' CallSubDelayed(FirebaseMessaging, "SubscribeToTopics")
' End Sub
'
'/// En Main en Sub Process_Globals agregar esta linea
'
' Private const API_KEY As String = "AAAAv__xxxxxxxxxxxxx-xxxxxxxxxxxxxx-xxxxxxxxxxxx"
'
'/// Esta llave se consigue igualmente en la consola de Firebase, configuracion de proyecto, Cloud Messaging,
'/// es la clave de servidor.
'///
'/// Se necesitan agregar las librerías: FirebaseAnalitics, FirebaseNotifications, JSON y OkHttpUtils
'/// ... JSON es necesario si se van a enviar mensajes, si solo se van a recibir, no es necesario.
'
'///////////////////////////////////////////////////////////////////////////////////////
Sub Process_Globals
Private fm As FirebaseMessaging
Dim locRequest As String
Dim pe As PhoneEvents
Dim batt As Int
Dim au As String
Dim Sprvsr As String = "Sprv-ML"
End Sub
'Called when an intent is received.
'Do not assume that anything else, including the starter service, has run before this method.
Private Sub Receiver_Receive (FirstTime As Boolean, StartingIntent As Intent)
Subs.revisaBD
fm.Initialize("fm") 'Inicializamos FirebaseMessaging
Subs.getPhnId
pe.Initialize("pe") 'Para obtener la bateria
Subs.revisaBD
End Sub
Public Sub SubscribeToTopics
fm.SubscribeToTopic("Trckr") 'Global (you can subscribe to more topics)
fm.SubscribeToTopic("Trckr") 'Tracker Global
If Starter.logger Then Log("Subscrito a tracker global")
fm.SubscribeToTopic("Trckr-ML") 'Global (you can subscribe to more topics)
If Starter.logger Then Log("Subscrito a Trckr-ML")
fm.SubscribeToTopic(Starter.devModel) 'Propio (you can subscribe to more topics)
If Starter.logger Then Log("Subscrito a "&Starter.devModel)
If Starter.logger Then Log(fm.token)
fm.UnsubscribeFromTopic("Sprvsr") 'Unsubscribe from topic
' fm.UnsubscribeFromTopic("Trckr") 'Unsubscribe from topic
' fm.UnsubscribeFromTopic("Trckr-ML") 'Unsubscribe from topic
' fm.UnsubscribeFromTopic(Starter.devModel) 'Unsubscribe from topic
End Sub
Sub fm_MessageArrived (Message As RemoteMessage)
Log("Message arrived")
Log($"Message data: ${Message.GetData}"$)
If B4XPages.IsInitialized And B4XPages.GetManager.IsForeground Then
Log("App is in the foreground. In iOS a notification will not appear while the app is in the foreground (unless UserNotificationCenter is used).")
End If
Dim n2 As Notification
n2.Initialize2(n2.IMPORTANCE_HIGH)
n2.Icon = "icon"
n2.SetInfo(Message.GetData.Get("title"), Message.GetData.Get("body"), Main)
n2.Notify(1)
End Sub
Sub fm_TokenRefresh (Token As String)
Log("TokenRefresh: " & Token)
End Sub

205
B4A/FirebaseMessaging0.bas Normal file
View File

@@ -0,0 +1,205 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Service
Version=10.5
@EndOfDesignText@
'///////////////////////////////////////////////////////////////////////////////////////
'/// Agregar estas lineas al editor de manifiestos
'
' CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)
' CreateResourceFromFile(Macro, FirebaseAnalytics.Firebase)
' CreateResourceFromFile(Macro, FirebaseAnalytics.FirebaseAnalytics)
' CreateResourceFromFile(Macro, FirebaseNotifications.FirebaseNotifications)
'
'/// Agregar modulo de servicio nuevo FirebaseMessaging y copiar este modulo
'
'/// Bajar el archivo google-services.json de la consola de Firebase (https://console.firebase.google.com/)
'/// El nombre de la app en el archivo json tiene que ser el mismo que el nombre del paquete (Proyecto/Conf de Compilacion/Paquete)
'
'/// En Starter agregar esta linea
'
' Sub Service_Create
' CallSubDelayed(FirebaseMessaging, "SubscribeToTopics")
' End Sub
'
'/// En Main en Sub Process_Globals agregar esta linea
'
' Private const API_KEY As String = "AAAAv__xxxxxxxxxxxxx-xxxxxxxxxxxxxx-xxxxxxxxxxxx"
'
'/// Esta llave se consigue igualmente en la consola de Firebase, configuracion de proyecto, Cloud Messaging,
'/// es la clave de servidor.
'///
'/// Se necesitan agregar las librerías: FirebaseAnalitics, FirebaseNotifications, JSON y OkHttpUtils
'/// ... JSON es necesario si se van a enviar mensajes, si solo se van a recibir, no es necesario.
'
'///////////////////////////////////////////////////////////////////////////////////////
Sub Process_Globals
Private fm As FirebaseMessaging
Private const API_KEY As String = "AAAAv1qt3Lk:APA91bECIR-pHn6ul53eYyoVlpPuOo85RO-0zcAgEXwE7vqw8DFSbBtCaCINiqWQAkBBZXxHtQMdpU6B-jHIqgFKVL196UgwHv0Gw6_IgmipfV_NiItjzlH9d2QNpGLp9y_JUKVjUEhP"
Dim locRequest As String
Dim pe As PhoneEvents
Dim batt As Int
Dim au As String
Dim Sprvsr As String = "Sprv-ML"
End Sub
Sub Service_Create
Subs.revisaBD
fm.Initialize("fm") 'Inicializamos FirebaseMessaging
Subs.getPhnId
pe.Initialize("pe") 'Para obtener la bateria
Subs.revisaBD
End Sub
Public Sub SubscribeToTopics
fm.SubscribeToTopic("Trckr") 'Global (you can subscribe to more topics)
fm.SubscribeToTopic("Trckr") 'Tracker Global
If Starter.logger Then Log("Subscrito a tracker global")
fm.SubscribeToTopic("Trckr-ML") 'Global (you can subscribe to more topics)
If Starter.logger Then Log("Subscrito a Trckr-ML")
fm.SubscribeToTopic(Starter.devModel) 'Propio (you can subscribe to more topics)
If Starter.logger Then Log("Subscrito a "&Starter.devModel)
If Starter.logger Then Log(fm.token)
fm.UnsubscribeFromTopic("Sprvsr") 'Unsubscribe from topic
' fm.UnsubscribeFromTopic("Trckr") 'Unsubscribe from topic
' fm.UnsubscribeFromTopic("Trckr-ML") 'Unsubscribe from topic
' fm.UnsubscribeFromTopic(Starter.devModel) 'Unsubscribe from topic
End Sub
Sub Service_Start (StartingIntent As Intent)
Subs.getPhnId
If StartingIntent.IsInitialized Then fm.HandleIntent(StartingIntent)
Sleep(0)
Service.StopAutomaticForeground 'remove if not using B4A v8+.
StartServiceAt(Me, DateTime.Now + 15 * DateTime.TicksPerMinute, True) 'Iniciamos servicio cada XX minutos
End Sub
Sub fm_MessageArrived (Message As RemoteMessage)
If Starter.logger Then Log("Message arrived")
If Starter.logger Then Log($"Message from: ${Message.From}"$)
If Starter.logger Then Log($"Message data: ${Message.GetData}"$)
Subs.getPhnId
Subs.getSSID
If Message.GetData.ContainsKey("t") Then
Dim tipos As List = Regex.Split(",",Message.GetData.Get("t"))
If tipos.IndexOf("pu") <> -1 Or tipos.IndexOf("au") <> -1 Then 'Si es una peticion de ubicacion
If Starter.logger Then Log("Es una peticion de ubicacion")
If Starter.logger Then Log($"UUC: ${Starter.UUC.Latitude},${Starter.UUC.Longitude}"$)
If Starter.UUC.IsInitialized And Starter.UUC.Latitude <> 0.0 Then
' mandaLocFM(Starter.UUC)
Subs.actualizaVar("solicitudFM", 1)
If Starter.logger Then LogColor($"Llamamos mandaLoc2: ${Starter.UUC.Latitude},${Starter.UUC.Longitude},${Subs.formatoFecha(Starter.UUC.Time)}"$, Colors.Magenta)
Subs.mandaLoc2(Starter.UUC, Starter.devModel)
End If
locRequest="Activa"
If Starter.logger Then Log("Llamamos StartFLP")
CallSubDelayed(Tracker, "StartFLP")
End If
If tipos.IndexOf("au") <> -1 Then 'Si es una actualizacion de ubicacion
au = 1
End If
If tipos.IndexOf("ping") <> -1 Then 'Si es un ping
' If Starter.logger Then Log("Es un ping")
' If Starter.logger Then Log("Mandamos pong")
' Dim params As Map = CreateMap("topic":Sprvsr,"title":"pong", "body":Starter.devModel&" - Recibi mensaje "&Message.GetData.Get("title"), "t":"pong")
' SendMessage(params)
End If
If tipos.IndexOf("bgps") <> -1 Then 'Si es una instruccion de borrar archivo gps
If Starter.logger Then Log("Es una instruccion de borrar archivo gps")
If Starter.logger Then Log("Borramos archivo gps")
Subs.borramosArchivoGPS
End If
If tipos.IndexOf("bgps2") <> -1 Then 'Si es una instruccion de borrar db gps
If Starter.logger Then Log("Es una instruccion de borrar archivo gps")
If Starter.logger Then Log("Borramos archivo gps")
Subs.deleteGPS_DB
End If
If tipos.IndexOf("dr") <> -1 Then 'Si es una peticion de ruta gps
' If Starter.logger Then Log("Es una peticion de Ruta GPS")
' Dim rutaGpsCmp As String = Subs.dameRuta
' Dim params As Map = CreateMap("topic":Sprvsr,"title":"ruta", "body":Starter.devModel&" - Recibi mensaje "&Message.GetData.Get("title"), "t":"ruta", "r":rutaGpsCmp, "fr": Main.fechaRuta)
' SendMessage(params)
End If
If tipos.IndexOf("pu") = -1 And tipos.IndexOf("ping") = -1 And tipos.IndexOf("dr") = -1 Then
If Starter.logger Then Log("No es ping ni solicitud de ubicacion o ruta, entonces no hacemos nada")
End If
End If
' Dim n As Notification
' n.Initialize
' n.Icon = "icon"
' n.SetInfo(Message.GetData.Get("title"), Message.GetData.Get("body"), Main)
' n.Notify(1)
End Sub
Sub Service_Destroy
End Sub
Sub SendMessage(params As Map)
' Dim topic As String= params.Get("topic")
' Dim title As String= params.Get("title")
' Dim body As String= params.Get("body")
' Dim tipo As String= params.Get("t")
' If params.ContainsKey("r") Then
' Dim rutaGpsCmp As String= params.Get("r")
' Else
' Dim rutaGpsCmp As String = ""
' End If
' Dim Job As HttpJob
' Job.Initialize("fcm", Me)
' Dim m As Map = CreateMap("to": $"/topics/${topic}"$)
' Dim data As Map = CreateMap("title":title, "body":body, "d":Starter.devModel.Trim, "t":tipo, "w":Subs.ssid, "b":batt, "r":rutaGpsCmp, "v":Application.VersionName)
' m.Put("data", data)
' Dim jg As JSONGenerator
' jg.Initialize(m)
'' Job.PostString("https://fcm.googleapis.com/fcm/send", jg.ToString)
' Job.PostString("https://fcm.googleapis.com/v1/projects/pusher-4c091/messages:send", jg.ToString)
'
'' POST https://fcm.googleapis.com/v1/projects/pusher-4c091/messages:send
'' "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
'
' Job.GetRequest.SetContentType("application/json;charset=UTF-8")
'' Job.GetRequest.SetHeader("Authorization", "key=" & API_KEY)
' Job.GetRequest.SetHeader("Authorization", "Bearer AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0")
' If Starter.logger Then Log("Mandamos mensaje: " & m)
End Sub
Sub mandaLocFM(loc As Location)
Dim coords As String = loc.Latitude & ","&loc.Longitude & ","&Subs.formatoFecha(DateTime.Now)
If Starter.logger Then LogColor("Iniciamos mandaLocFM ("&coords&")", Colors.Magenta)
Dim t As String
If locRequest="Activa" Then
If au = 1 Then
t = "au" ' es una actualizacion
Else
t = "u" ' es una peticion
End If
' Dim params As Map = CreateMap("topic":Sprvsr,"title":"ubicacionRecibida", "body":coords, "t":t)
' Log(params)
' SendMessage(params)
locRequest="Enviada"
CallSubDelayed(Tracker,"CreateLocationRequest")
End If
End Sub
Sub pe_BatteryChanged (Level As Int, Scale As Int, Plugged As Boolean, Intent As Intent)
batt=Level
End Sub
Sub PE_PhoneStateChanged (State As String, IncomingNumber As String, Intent As Intent)
If Starter.logger Then Log("Phone state: " & State)
If State = "RINGING" Then
If Starter.logger Then Log("The incoming number is: " & IncomingNumber)
Else
End If
End Sub
'Sub wifiScanned_ScanDone
' Log("//////////////////////////////wifi_conected_result")
' ToastMessageShow("Wifi_ConnectionResult",True)
' If Main.wifi.isWifiConnected Then
' ssid = Main.wifi.WifiSSID
' End If
'End Sub

215
B4A/NotificationService.bas Normal file
View File

@@ -0,0 +1,215 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Service
Version=11
@EndOfDesignText@
#Region Service Attributes
#StartAtBoot: False
#End Region
'##################################################################################################
'Requiere las liberias: Reflection y NotificationListener}
'##################################################################################################
'Agregar estas lienas al manifiesto:
'
'AddApplicationText(
'<Service android:name="b4a.jsaplication.com.br.ReplyAuto"
' android:label="Mariana" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
' <intent-filter><action android:name="android.service.notification.NotificationListenerService" /></intent-filter>
' </Service>)
'
'Lo siguiente es para revisar que tenga autorización para interceptar notificaciones, hay que ponerlo en Main o Starter:
' 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
'
''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
'##################################################################################################
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 'ignore
End Sub
Sub Service_Create
rp.Initialize("NotiMon")
#if not(DEBUG)
logger = False
#end if
Subs.revisaBD
' 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)
Subs.revisaYguardaUUC
If Starter.logger Then LogColor(SBN.PackageName & " - " & SBN.Message, Colors.blue)
' Log("-= Notificacion recibida =-")
' 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)}|"$)
' Si recibimos un mensaje con la palabra "donde", "Donde" o "bien", entonces mandamos la última ubicación conocida.
' If SBN.Message.Contains("donde") Or SBN.Message.Contains("Donde") Or SBN.Message.Contains("bien") Then 'Si el mensaje contiene "#NS" y tiene un segundo parametro ...
' If esMensajeWAValido(SBN) Then
' Subs.bitacora($"Recibimos notificación, pedimos actualización y mandamos UUC."$)
If Starter.logger Then LogColor($"Recibimos notificación, pedimos actualización y mandamos UUC."$, Colors.Green)
If Tracker.flp.IsInitialized And Tracker.flp.IsConnected Then Tracker.flp.RequestLocationUpdates(Tracker.locReqSmall)
Sleep(2000)
Private ultimaLoc As Location = Subs.traeUltimaUbicacionGuardada
Subs.mandaLoc2(ultimaLoc, Starter.devModel)
' 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 'ignore
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 'ignore
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

18
B4A/R_Test.bas Normal file
View File

@@ -0,0 +1,18 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Receiver
Version=12.5
@EndOfDesignText@
Sub Process_Globals
End Sub
'Called when an intent is received.
'Do not assume that anything else, including the starter service, has run before this method.
Private Sub Receiver_Receive (FirstTime As Boolean, StartingIntent As Intent)
Log("RECEIVER RECEIVED - BOOT COMPLETED")
Subs.revisaBD
Subs.bitacora("RECEIVER BOOT COMPLETED")
End Sub

269
B4A/Starter.bas Normal file
View File

@@ -0,0 +1,269 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Service
Version=9.9
@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 'Para obtener permisos android 6+
Public FLP As FusedLocationProvider 'Para Tracker
Dim reqManager As DBRequestManager
Dim cmd As DBCommand
Dim Timer1, Timer2 As Timer
Dim interval As Int = 300 '300 segs (5 mins)
Dim UUC As Location
Dim run As Int = 0 'ignore
Dim devModel As String
Dim lastLocUpdate As String = 0
Dim errorLog As SQL
Dim PE As PhoneEvents
Dim PhId As PhoneId
Dim callStartTime, callEndTime As Long
Dim isIncoming As Boolean
Dim lastState As String = "IDLE"
Dim savedNumber As String
Dim locAntTime As String = "0"
Dim logger As Boolean = True
Dim BroadCast As BroadCastReceiver
Dim T2Interval As Int = 600000
Dim pausarEnvio As Boolean = False
Dim IsNetAvailable As Boolean
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.
Subs.revisaBD
CallSubDelayed(FirebaseMessaging, "SubscribeToTopics") 'Para FirebaseMessaging
lastState = "IDLE"
PE.InitializeWithPhoneState("PE",PhId)
End Sub
Sub Service_Start (StartingIntent As Intent)
Service.StopAutomaticForeground 'Starter service can start in the foreground state in some edge cases.
' reqManager.Initialize(Me, "http://keymon.lat:1781")
reqManager.Initialize(Me, "http://keymon.lat:9000")
Timer1.Initialize("Timer1", interval * 1000)
Timer2.Initialize("Timer2", T2Interval) ' Timer para que si hay un error al conectarse con el servidor de DBRequest, no mande nada en 120 segs.
Timer1.Enabled = True
UUC.Initialize
UUC.Accuracy = 1000
Subs.getPhnId
Subs.bitacora($"Starter - Service_Start"$)
StartService(Tracker)
StartServiceAt(Tracker, DateTime.Now + 30 * DateTime.TicksPerMinute, True)
#if RELEASE
logger = False
#end if
Subs.revisaYguardaUUC
BroadCast.Initialize("BroadcastReceiver") ' Inicializa el receptor de difusión con el nombre "BroadcastReceiver"
BroadCast.addAction("android.net.conn.CONNECTIVITY_CHANGE") ' Agrega una acción para escuchar los cambios en la conectividad de red
BroadCast.SetPriority(100) ' Establece la prioridad del receptor de difusión (BroadCast) a 100
BroadCast.registerReceiver("") ' Registra el receptor de difusión sin un filtro específico
End Sub
Sub BroadcastReceiver_OnReceive (Action As String, i As Object)
' Declaración de una variable Intent para manejar el objeto recibido
Dim retIn As Intent
' Declaración de una variable booleana para verificar si hay red disponible
' Asignación del objeto recibido al Intent
retIn = i
' Declaración de variables para almacenar el estado de la conexión y el tipo de red
Dim IsConnected As String
Dim TheType As String
' Verifica si la acción recibida es un cambio de conectividad
If Action = "android.net.conn.CONNECTIVITY_CHANGE" Then
' Crea un objeto JavaObject basado en el intent recibido para acceder a métodos específicos
Dim jo As JavaObject = retIn
' Obtener información de red desde el Intent
Dim NetworkInfo As JavaObject = jo.RunMethod("getParcelableExtra", Array("networkInfo"))
' Obtener el tipo de red (WiFi, Móvil, etc.)
TheType = NetworkInfo.RunMethod("getTypeName", Null)
' Obtener el estado de la conexión (Conectado, Desconectado, etc.)
IsConnected = NetworkInfo.RunMethod("getState", Null)
' Loguear y mostrar un mensaje Toast con el tipo y estado de la conexión
' Log($"TheType: ${TheType}, IsConnected: ${IsConnected}"$)
' ToastMessageShow($"TheType: ${TheType}, IsConnected: ${IsConnected}"$, False)
' Verifica si el dispositivo está conectado
If IsConnected.EqualsIgnoreCase("CONNECTED") Then
' Si está conectado, establece que la red está disponible
IsNetAvailable = True
Else
' Si no está conectado, establece que la red no está disponible
IsNetAvailable = False
End If
' Log(IsNetAvailable)
If IsNetAvailable Then
Log(">>>>> MANDAMOS INFO A SERVER")
Subs.mandaLocAServer(devModel.Trim)
End If
End If
' Finaliza la transmisión actual
BroadCast.AbortBroadcast
End Sub
Private Sub Timer1_Tick
' Log("TIMER1: " & Timer1)
Subs.borraArribaDeXXXBitacora(3000)
Subs.borraArribaDeXXXUbicaciones(5000)
End Sub
Private Sub Timer2_Tick
' Log("TIMER2: " & Timer1)
LogColor(">>>>>>>> PAUSAR ENVIO FALSE", Colors.Red)
pausarEnvio = False
Timer2.Enabled = False
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
Subs.bitacora($"ERROR -> ${Error}"$)
Return True
End Sub
Sub Service_Destroy
Subs.bitacora($"Starter - Service destroyed"$)
' Subs.gps_hist.ExecNonQuery($"insert into BITACORA (RUTA, TEXTO, FECHA) values ('${devModel}', 'Starter - Service destroyed')"$)
End Sub
Sub restartTracker
If logger Then Log("Llamamos RESTART-TRACKER")
Subs.bitacora("Llamamos RESTART-TRACKER")
StopService(Tracker)
Sleep(1000)
StartService(Tracker)
End Sub
Sub PE_PhoneStateChanged (State As String, IncomingNumber As String, Intent As Intent)
'Incoming call- goes from IDLE To RINGING when it rings, To OFFHOOK when it's answered, to IDLE when its hung up
'Outgoing call- goes from IDLE To OFFHOOK when it dials out, To IDLE when hung up
Log($">>>>> Phone State Changed -> ${State} -> "$ & IncomingNumber)
If IncomingNumber = "" Then
Return
End If
Log($">>>>> Phone State Changed 2 -> ${State} -> "$ & IncomingNumber)
Select State
Case "RINGING"
'calling in progress
isIncoming = True
callStartTime = DateTime.Now
savedNumber = IncomingNumber
Subs.bitacora($"RINGING - ${IncomingNumber}"$)
Exit
Case "OFFHOOK"
'Transition of ringing->offhook are pickups of incoming calls. Nothing donw on them
If lastState <> "RINGING" Then
'outgoing call start
isIncoming = False
callStartTime = DateTime.Now
Subs.bitacora($"OFFHOOK - ${savedNumber}"$)
End If
Exit
Case "IDLE"
'Went to idle- this is the end of a call. What type depends on previous state(s)
If lastState = "RINGING" Then
'missed call
callEndTime = 0
Subs.bitacora($"IDLE - Missed call (${IncomingNumber}): ${callEndTime}"$)
else if isIncoming Then
'incoming call is finished
callEndTime = DateTime.Now
Subs.bitacora($"IDLE - Incoming call is finished (${IncomingNumber}): ${callEndTime}"$)
Else
'outgoing call is finished
callEndTime = DateTime.Now
Subs.bitacora($"IDLE - Outgoing call is finished (${IncomingNumber}): ${callEndTime}"$)
End If
Exit
End Select
lastState = State
'Log("PhoneStateChanged, State = " & State & ", IncomingNumber = " & IncomingNumber & "; PhoneFlag = " & PhoneFlag)
End Sub
Sub JobDone(Job As HttpJob)
Log("JOBDONE STARTER")
Try
If Job.JobName = "DBRequest" Then
Dim RESULT As DBResult = reqManager.HandleJob(Job)
Log($"Tag: ${RESULT.tag}, success=${Job.Success}"$)
End If
'Log(Job.Tag)
If Job.Success = False Then
' Log("JOBDONE ERROR")
LogColor("Error: " & Job.ErrorMessage, Colors.red)
If Job.ErrorMessage.Contains("java.net.SocketTimeoutException") Then ' Si hubo error, pausamos los siguientes envios por 120 segs (pausarEnvio = True).
Timer2_Tick
Timer2.Enabled = False
Timer2.Interval = T2Interval
Timer2.Enabled = True
LogColor(">>>>>> PAUSAR ENVIO TRUE REINICIO", Colors.Red)
End If
' If Job.ErrorMessage.Contains("ORA-00001") Then ' Si hubo error, pausamos los siguientes envios por 120 segs (pausarEnvio = True).
' pausarEnvio = False
' If Job.JobName = "DBRequest" Then
' Dim RESULT As DBResult = reqManager.HandleJob(Job)
' If RESULT.Tag.As(String).StartsWith("guardaDatos_") Then 'query tag
' LogColor(">>>>>> YA EXISTE EN WEB", Colors.Red)
' Private id() As String = Regex.Split("_", RESULT.tag)
' Private id1 As String = id(1)
' For Each records() As Object In RESULT.Rows
' Subs.gps_hist.ExecNonQuery($"update RUTA_GPS set ENVIADO = 2 where FECHA = '${id1}'"$)
' Next
' LogColor($"Actualizamos ${id1}"$, Colors.red)
' End If
' End If
' End If
Else 'If Job Success then ...
' Log("JOBDONE SUCCESS")
Timer2_Tick
If Job.JobName = "DBRequest" Then
Dim RESULT As DBResult = reqManager.HandleJob(Job)
' Si ya no existe la ubicacion en web, la insertamos nuevamente.
If RESULT.Tag.As(String).StartsWith("borraDatos_") Then 'query tag
Private id() As String = Regex.Split("_", RESULT.tag)
Private id1 As String = id(1)
For Each records() As Object In RESULT.Rows
' Traemos la ubicacion de RUTA_GPS y la mandamos a web.
Private g As ResultSet = Subs.gps_hist.ExecQuery($"select * from RUTA_GPS where FECHA = '${id1}'"$)
cmd.Initialize
Do While g.NextRow
cmd.Name = "guardaDatos"
cmd.Parameters = Array As Object(g.GetString("FECHA"), devModel, g.GetString("FECHA").SubString2(0,12), $"${g.GetString("LAT")},${g.GetString("LON")},${g.GetString("ACC")},True,${g.GetString("SPEED")},True"$, "Coords")
reqManager.ExecuteCommand(cmd,$"guardaDatos_${id1}"$)
If logger Then LogColor($">>>> Mandamos loc a server: ${g.GetString("FECHA")}, ${g.GetString("LAT")},${g.GetString("LON")},${g.GetString("ACC")},True,${g.GetString("SPEED")},True"$, Colors.Blue)
Loop
g.Close
Next
LogColor($"Actualizamos ${id1}"$, Colors.red)
End If
' Si se guardo bien la ubicacion en web, actualizamos la columna ENVIADO en RUTA_GPS.
If RESULT.Tag.As(String).StartsWith("guardaDatos_") Then 'query tag
Private id() As String = Regex.Split("_", RESULT.tag)
Private id1 As String = id(1)
For Each records() As Object In RESULT.Rows
Subs.gps_hist.ExecNonQuery($"update RUTA_GPS set ENVIADO = 1 where FECHA = '${id1}'"$)
Next
LogColor($"Actualizamos ${id1}"$, Colors.red)
End If
End If
End If
Catch
Log(LastException)
End Try
End Sub

453
B4A/Subs.bas Normal file
View File

@@ -0,0 +1,453 @@
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 gps_hist As SQL
Dim wifi As MLwifi
Dim ssid As String
Dim locAntTime As String = "0"
Dim solicitudFM As Int = 0
End Sub
Sub getPhnId 'Pone el valor de phn.Model en la variable global "devModel"
Private elId As String
If File.Exists(File.DirInternal, "phnId.txt") Then
elId = File.ReadString(File.DirInternal, "phnId.txt")
Else
File.WriteString(File.DirInternal, "phnId.txt", "") 'Creamos el archivo
End If
If elId.Length < 3 Then 'Si el modelo del archivo es menos de 2, lo sustituimos con devmodel
devModel = phn.Model
If devModel.Length > 1 Then elId = devModel
End If
If elId.Length < 3 Then 'Si el modelo del archivo es menos de 2, lo sustituimos con android_id
elId = phn.GetSettings("android_id") 'Intentamos con "android_id"
End If
If elId.Length < 3 Then elId = $"dev${DateTime.GetHour(DateTime.Now)}"$
File.WriteString(File.DirInternal, "phnId.txt", elId) 'Sobreescribimos archivo phnId.txt with elId
' If Starter.logger Then Log("Escribimos phnId: "&elId&" a "&File.DirInternal&"/phnId.txt")
Starter.devModel = elId
' If Starter.logger Then Log(Starter.devModel)
End Sub
Sub compress(str As String) As String ' Compresion
Dim compressed() As Byte = GZip.compress(str)
If Starter.logger Then Log($"CompressedBytesLength: ${compressed.Length}"$)
Dim base64 As String = su.EncodeBase64(compressed)
If Starter.logger Then Log($"CompressedBytes converted to base64 Length: ${base64.Length}"$)
If Starter.logger Then Log($"CompressedBytes converted to base64: ${base64}"$)
Return base64
End Sub
Sub decompress(base64 As String) As String ' Descompresion 'ignore
Dim decompressedbytes() As Byte = su.DecodeBase64(base64)
If Starter.logger Then Log($"decompressedbytesLength: ${decompressedbytes.Length}"$)
Dim bc As ByteConverter
Dim uncompressed As String = bc.StringFromBytes(decompressedbytes,"UTF8")
If Starter.logger Then Log($"uncompressedLength: ${uncompressed.Length}"$)
If Starter.logger Then Log($"Decompressed String = ${uncompressed}"$)
Return uncompressed
End Sub
Sub formatoFecha(fecha As String) As String 'Convierte una fecha al formato yyMMddHHmmss
' Log(fecha)
Dim OrigFormat As String = DateTime.DateFormat 'save orig date format
DateTime.DateFormat="yyMMddHHmmss"
Dim lastUpdate As String=DateTime.Date(fecha)
DateTime.DateFormat=OrigFormat 'return to orig date format
' Log(lastUpdate)
Return lastUpdate
End Sub
Sub CreateNotification (Body As String) As Notification
Dim notification As Notification
notification.Initialize2(notification.IMPORTANCE_LOW)
notification.Icon = "icon"
notification.SetInfo("FLP", Body, Main)
Return notification
End Sub
Sub guardaInfoEnArchivo(coords As String) 'Escribimos coordenadas y fecha a un archivo de texto '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
'Guarda la ubicacion dada en la tabla "RUTA_GPS".
Sub guardaInfoEnBD(loc As Location) 'Escribimos coordenadas y fecha a una BD
If loc.Latitude <> "0.0" Then
revisaBD
Private bearingDiff As String = "31"
Private distanceDiff As String = "21"
Private tmpLoc As Location
If Starter.logger Then Log($"Guardamos ubicacion en db (${loc.Latitude},${loc.Longitude})"$)
'Traemos la ultima ubicacion guardada.
Private locAnt As ResultSet = gps_hist.ExecQuery($"select FECHA, LAT, LON, ACC, TIME, ifnull(BEARING, 0) as BEARING, ifnull(BEARING_DIFF, 0) as BEARING_DIFF, ifnull(DISTANCE_DIFF, 0) as DISTANCE_DIFF, ifnull(SPEED, 0) as SPEED, ifnull(ENVIADO, 0) as ENVIADO from RUTA_GPS order by time desc limit 1"$)
Do While locAnt.NextRow
'Calculamos el cambio de direccion.
bearingDiff = loc.Bearing - locAnt.GetString("BEARING")
If locAnt.GetString("BEARING") > loc.Bearing Then bearingDiff = locAnt.GetString("BEARING") - loc.Bearing
'Calculamos la distancia recorrida.
tmpLoc.Initialize2(locAnt.GetString("LAT"), locAnt.GetString("LON"))
distanceDiff = loc.DistanceTo(tmpLoc)
' Log($"${loc.Accuracy}, ${distanceDiff}, ${bearingDiff}"$)
Loop
' Si la precision es menor a 50 y la dirección cambió o la distancia es mayor a 20 mts, la guardamos.
If loc.Accuracy < 50 And (bearingDiff > 30 Or distanceDiff > 20) Then
gps_hist.ExecNonQuery2("INSERT INTO RUTA_GPS(fecha, lat, lon, acc, time, bearing, bearing_diff, distance_diff, speed) VALUES (?,?,?,?,?,?,?,?,?)", Array As Object (fechaKMTms(loc.time),loc.Latitude,loc.Longitude, loc.Accuracy, loc.time, loc.Bearing, bearingDiff, distanceDiff, loc.Speed))
End If
End If
End Sub
Sub dameRuta As String
Dim c As Cursor
If gps_hist.IsInitialized = False Then gps_hist.Initialize(File.DirInternal, "gps_hist.db", True)
c = gps_hist.ExecQuery("select FECHA, LAT, LON from RUTA_GPS order by FECHA desc limit 380")
c.Position = 0
Dim ruta2 As String = ""
If c.RowCount>0 Then
For i=0 To c.RowCount -1
c.Position=i
ruta2=ruta2&CRLF&c.GetString("LAT")&","&c.GetString("LON")
B4XPages.MainPage.fechaRuta = c.GetString("FECHA")
Next
End If
c.Close
Return compress(ruta2)
End Sub
Sub deleteGPS_DB
' gps_hist.ExecQuery
gps_hist.ExecNonQuery("delete from RUTA_GPS")
gps_hist.ExecNonQuery("vacuum;")
If Starter.logger Then Log("RUTA_GPS borrada")
End Sub
Sub borramosArchivoGPS
Dim out As OutputStream = File.OpenOutput(File.DirRootExternal, "gps.txt", False)
Dim s As String = ""
Dim t() As Byte = s.GetBytes("UTF-8")
out.WriteBytes(t, 0, t.Length)
out.Close
End Sub
Sub revisaBD
If Not(File.Exists(File.DirInternal, "gps_hist.db")) Then File.Copy(File.DirAssets, "gps_hist.db", File.DirInternal, "gps_hist.db")
If Not(gps_hist.IsInitialized) Then gps_hist.Initialize(File.DirInternal, "gps_hist.db", True)
If Not(Starter.errorLog.IsInitialized) Then Starter.errorLog.Initialize(File.DirInternal, "errorLog.db", True)
gps_hist.ExecNonQuery("CREATE TABLE IF NOT EXISTS BITACORA(RUTA TEXT, TEXTO TEXT, FECHA TEXT)")
gps_hist.ExecNonQuery("CREATE TABLE IF NOT EXISTS RUTA_GPS(FECHA INTEGER, LAT TEXT, LON TEXT, ACC INT, TIME INT)")
gps_hist.ExecNonQuery("CREATE TABLE IF NOT EXISTS CAT_VARIABLES(NOMBRE TEXT, VALOR TEXT)")
agregaColumna("RUTA_GPS", "BEARING", "TEXT")
agregaColumna("RUTA_GPS", "BEARING_DIFF", "TEXT")
agregaColumna("RUTA_GPS", "DISTANCE_DIFF", "TEXT")
agregaColumna("RUTA_GPS", "SPEED", "TEXT")
agregaColumna("RUTA_GPS", "ENVIADO", "TEXT")
End Sub
Sub getSSID
If wifi.isWifiConnected Then
ssid = wifi.WifiSSID
End If
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
'Convierte una fecha al formato yyMMddHHmmssSSS -- con milisegundos
Sub fechaKMTms(fecha As String) As String 'ignore
' Log(fecha)
Dim OrigFormat As String = DateTime.DateFormat 'save orig date format
DateTime.DateFormat="yyMMddHHmmssSSS"
Dim nuevaFecha As String=DateTime.Date(fecha)
DateTime.DateFormat=OrigFormat 'return to orig date format
' Log(nuevaFecha)
Return nuevaFecha
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
If Starter.logger Then Log("Formato de fecha incorrecto, debe de ser 'YYMMDDHHMMSS', no '"&fKMT&"' largo="&fKMT.Length)
Return 0
End If
Catch
Log("FLP-fechaKMT2Ticks Error -> " & LastException)
If Starter.logger Then LogColor($"Fecha dada: ${fKMT}, Parte Fecha: ${parteFecha}, Parte Hora: ${parteHora}"$, Colors.Red)
Return 0
End Try
End Sub
'Convierte una fecha al formato yyMMddHHmmss
Sub fechaNormal(fecha As String) As String 'ignore
' Log(fecha)
Dim OrigFormat As String = DateTime.DateFormat 'save orig date format
DateTime.DateFormat="MM/dd HH:mm:ss"
Dim nuevaFecha As String = DateTime.Date(fecha)
DateTime.DateFormat=OrigFormat 'return to orig date format
Return nuevaFecha
End Sub
Sub mandaLocAServer( id As String)
Starter.lastLocUpdate = DateTime.Now
If Not(IsPaused(Main)) Then CallSubDelayed(Main, "actualizaLabelUU")
Try
If Starter.IsNetAvailable Then
' Traemos las ubicaciones de RUTA_GPS que no estan ENVIADAS.
Private g0 As ResultSet = gps_hist.ExecQuery($"select * from RUTA_GPS where ifNull(ENVIADO,'0') = '0'"$)
Do While g0.NextRow
Starter.cmd.Initialize
Starter.cmd.Name = "borraDatos"
Starter.cmd.Parameters = Array As Object(g0.GetString("FECHA"), id)
If Starter.logger Then LogColor($">>>> Borramos loc de server: ${g0.GetString("FECHA")}, ${id}"$, Colors.Blue)
' Borramos de web la ubicacion, para despues en JobDone volverla a insertar, esto es porque si ya existe en web, causa un error por indices unicos y no se actualiza nada!
Starter.reqManager.ExecuteCommand(Starter.cmd,$"borraDatos_${g0.GetString("FECHA")}"$)
Loop
g0.close
End If
' Sleep(10000)
' Log($"PAUSAR_ENVIO: ${Starter.pausarEnvio}, IS_NET_AVAILABLE: ${Starter.IsNetAvailable}"$)
' If Not(Starter.pausarEnvio) And Starter.IsNetAvailable Then
' Private g As ResultSet = gps_hist.ExecQuery($"select * from RUTA_GPS where ifNull(ENVIADO,'0') = '0'"$)
' Do While g.NextRow
' Starter.pausarEnvio = True
' Starter.Timer2.Enabled = False
' Starter.Timer2.Interval = Starter.T2Interval
' Starter.Timer2.Enabled = True
' LogColor("PAUSAR ENVIO TRUE", Colors.Red)
' Starter.cmd.Initialize
' Starter.cmd.Name = "guardaDatos"
'' Log($"Time: ${g.GetString("TIME")}, Acc: ${g.GetString("ACC")}, Enviado: ${g.GetString("ENVIADO")}"$)
' Starter.cmd.Parameters = Array As Object(g.GetString("FECHA"), id, g.GetString("FECHA"), $"${g.GetString("LAT")},${g.GetString("LON")},${g.GetString("ACC")},True,${g.GetString("SPEED")},True"$, "Coords")
' If Starter.logger Then
' If Starter.logger Then LogColor($">>>> Mandamos loc a server: ${g.GetString("LAT")},${g.GetString("LON")},${g.GetString("ACC")},True,${g.GetString("SPEED")},True"$, Colors.Blue)
' End If
' Starter.reqManager.ExecuteCommand(Starter.cmd,$"guardaDatos_${g.GetString("FECHA")}"$)
' Loop
' g.close
' End If
Catch
Log(LastException)
End Try
End Sub
'Manda la ubicacion al servidor de BD y a FirebaseMessage.
Sub mandaLoc2(loc As Location, id As String) 'ignore
Try
Private minsTranscurridosLoc As String = ticksAMins(loc.time - traeVar("locAntTime", 0)) 'Minutos transcurridos desde la ultima ubicacion ACTUALIZADA.
Private minsTranscurridos As String = ticksAMins(DateTime.Now - traeUltimaUbicacionGuardada.Time) 'Minutos transcurridos desde la ultima ubicacion guardada.
Dim el_texto As String = ""
If Starter.logger Then LogColor("Guardada: " & minsTranscurridos & " mins., Actualizada: " & minsTranscurridosLoc & " mins.", Colors.green)
' If traeVar("solicitudFM", 0) = 1 Or minsTranscurridos >= 3 Or minsTranscurridosLoc >= 3 Then ' Para que no mande mensajes constantes, minimo 1 minuto entre mensajes.
' CallSubDelayed(Tracker,"CreateLocationRequest")
Tracker.flp.RequestLocationUpdates(Tracker.locReqNormal)
'Solo mandamos la ubicacion si la precision es dentro de XX mts
el_texto = $"LocChange - Coords NO enviadas (Acc:${loc.Accuracy})."$
If loc.Accuracy < 50 Then
If Starter.logger Then LogColor("Guardamos y enviamos ubicacion.", Colors.green)
guardaInfoEnBD(loc) 'Escribimos coordenadas y fecha a una bd
mandaLocAServer(id)
' FirebaseMessaging.locRequest = "Activa"
' CallSubDelayed2(FirebaseMessaging, "mandaLocFM", loc)
el_texto = $"LocChange - Coords enviadas (Acc:${loc.Accuracy})."$
End If
bitacora($"${el_texto}"$)
actualizaVar("solicitudFM", 0)
' ToastMessageShow("LocChanged MORE than a min.", False)
' Else
'' ToastMessageShow("Locatin changed but less than a min!.", False)
' End If
actualizaVar("locAntTime", loc.time)
Catch
CreateNotification(LastException)
Log(LastException)
End Try
End Sub
Sub ConvertMillisecondsToString(t As Long) As String 'ignore
Dim hours, minutes, seconds As Int
hours = t / DateTime.TicksPerHour
minutes = (t Mod DateTime.TicksPerHour) / DateTime.TicksPerMinute
seconds = (t Mod DateTime.TicksPerMinute) / DateTime.TicksPerSecond
Return $"$1.0{hours}:$2.0{minutes}:$2.0{seconds}"$
End Sub
'Convierte ticks a minutos.
Sub ticksAMins(ts As Long) As Long 'ignore
Private m As Long = ((ts/1000)/60)
Return m
End Sub
Sub bitacora(texto As String) 'ignore
revisaBD
' Log(fechaNormal(DateTime.now))
Try
gps_hist.ExecNonQuery($"insert into BITACORA (RUTA, TEXTO, FECHA) values ('${Starter.devModel}', '${texto}', '${fechaNormal(DateTime.now)}')"$)
Catch
Log(LastException)
End Try
End Sub
'Borramos renglones extra de la tabla de errores
Sub borraArribaDeXXXBitacora(limite As Int) 'ignore
If Starter.logger Then LogColor("Recortamos la tabla de bitacora, limite de 10,000", Colors.Magenta)
gps_hist.ExecNonQuery($"DELETE FROM bitacora WHERE fecha NOT in (SELECT fecha FROM bitacora ORDER BY fecha desc LIMIT ${limite})"$)
gps_hist.ExecNonQuery("vacuum;")
' if starter.logger then Log("Borramos mas de 100 de errorLog")
End Sub
'Borramos renglones extra de la tabla RUTA_GPS
Sub borraArribaDeXXXUbicaciones(limite As Int) 'ignore
If Starter.logger Then LogColor("Recortamos la tabla RUTA_GPS, limite de 10,000", Colors.Magenta)
gps_hist.ExecNonQuery($"DELETE FROM RUTA_GPS WHERE fecha NOT in (SELECT fecha FROM RUTA_GPS ORDER BY fecha desc LIMIT ${limite})"$)
gps_hist.ExecNonQuery("vacuum;")
' if starter.logger then Log("Borramos mas de 100 de errorLog")
End Sub
'Regresa la ultima ubicacion guardada o una ubicacion sin inicializar si no encuentra nada.
Sub traeUltimaUbicacionGuardada As Location 'ignore
Private loc As Location
loc.Initialize
Private c As Cursor = gps_hist.ExecQuery($"select FECHA, LAT, LON, ACC, TIME, ifnull(BEARING, 0) as BEARING, ifnull(BEARING_DIFF, 0) as BEARING_DIFF, ifnull(DISTANCE_DIFF, 0) as DISTANCE_DIFF, ifnull(SPEED, 0) as SPEED, ifnull(ENVIADO, 0) as ENVIADO from RUTA_GPS order by fecha desc limit 1"$)
If c.RowCount > 0 Then
c.Position = 0
loc.Latitude = c.GetString("LAT")
loc.Longitude = c.GetString("LON")
loc.Bearing = c.GetString("BEARING")
loc.Speed = c.GetString("SPEED")
loc.Accuracy = 0
If c.GetString("ACC") <> Null Then loc.Accuracy = c.GetString("ACC")
loc.Time = 0
If c.GetString("TIME") <> Null Then loc.Time = c.GetString("TIME")
End If
c.Close
Return loc
End Sub
'Busca la ultima ubicacion guardada en la table GPS_HIST, y dependiendo del tiempo transcurrido hace lo siguiente:
' - Mas de 10 minutos -> Pide actualización de ubicacion.
' - Mas de 20 minutos -> Apaga y prende el servicio de FLP.
' - Mas de 30 minutos -> Reinicia la aplicación.
Sub revisaYguardaUUC
Private ultimaLoc As Location = traeUltimaUbicacionGuardada
If ultimaLoc.IsInitialized Then
Starter.UUC = ultimaLoc
Private minsTranscurridos As String = ticksAMins(DateTime.Now - ultimaLoc.Time) 'Minutos transcurridos desde la ultima ubicacion guardada.
If Starter.logger Then Log($"Ultima ubicacion guardada hace ${minsTranscurridos} mins."$)
If minsTranscurridos > 10 And minsTranscurridos < 20 Then
bitacora("Mas de 10 mins - REQ-UPDATE")
LogColor($"Ubicacion vieja (mas de 10 mins.)"$, Colors.Red)
LogColor("Pedimos actualizacion!", Colors.blue)
If Tracker.flp.IsInitialized And Tracker.flp.IsConnected And Tracker.locReqSmall.IsInitialized Then
bitacora("REQ-UPDATE") : LogColor("REQ-UPDATE", Colors.magenta)
Try
Tracker.flp.RequestLocationUpdates(Tracker.locReqSmall)
Catch
Log(LastException)
End Try
Else
bitacora("TRACKER APAGADO - RESTART-TRACKER") : LogColor("RESTART-TRACKER", Colors.magenta)
StopService(Tracker)
Sleep(5000)
StartService(Tracker)
End If
else if minsTranscurridos >= 20 And minsTranscurridos < 30 Then
LogColor("RESTART-TRACKER", Colors.red)
bitacora("Mas de 20 mins - RESTART-TRACKER")
' bitacora(Tracker.flp.SuspendedCause)
StopService(Tracker)
Sleep(5000)
StartService(Tracker)
else If minsTranscurridos >= 30 Then
If Tracker.flp.IsInitialized And Tracker.flp.IsConnected Then LogColor($"FLP.Connected: ${Tracker.flp.IsConnected}"$, Colors.Red)
If Tracker.flp.IsInitialized And Not(Tracker.flp.IsConnecting) Then 'Si NO esta en proceso de conectarse ...
LogColor("RESTART-APP", Colors.red)
bitacora("Mas de 30 mins - RESTART-APP")
' bitacora(Tracker.flp.SuspendedCause) 'ignore
Starter.UUC.Time = DateTime.Now
guardaInfoEnBD(Starter.UUC) 'Guardamos la ultima ubicacion con la hora actual, para que no se reinicie la app si no consigue una ubicacion nueva.
' Sleep(1000)
StopService(Tracker)
Sleep(5000)
StartService(Tracker)
CallSubDelayed(Tracker, "StartFLP")
' ExitApplication
End If
End If
' LogColor($"Ultima loc: ${Subs.fechaNormal(ultimaLoc.Time)}"$, Colors.blue)
End If
End Sub
Sub actualizaVar(nombre As String, valor As String)
gps_hist.ExecNonQuery($"delete from CAT_VARIABLES where NOMBRE = '${nombre}'"$)
gps_hist.ExecNonQuery($"insert into CAT_VARIABLES (NOMBRE, VALOR) values ('${nombre}', '${valor}')"$)
End Sub
'Regresa el valor desde CAT_VARIABLES o del default espacificado en DEFAULT
Sub traeVar(nombre As String, default As String) As String
Private v As String = default
Private c As Cursor = gps_hist.ExecQuery2("select VALOR from CAT_VARIABLES WHERE NOMBRE = ?", Array As String (nombre))
If c.RowCount > 0 Then
c.Position = 0
v = c.GetString("VALOR")
End If
Return v
End Sub
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 = gps_hist.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
gps_hist.ExecNonQuery($"ALTER TABLE ${tabla} ADD COLUMN ${columna} ${tipo}"$)
Log($"Columna "${columna} ${tipo}", agregada a "${tabla}"."$)
End If
' Log(1)
Catch 'Si no funciona "pragma_table_info" lo hacemos con try/catch
Try
gps_hist.ExecNonQuery($"ALTER TABLE ${tabla} ADD COLUMN ${columna} ${tipo}"$)
Log($"Columna "${columna} ${tipo}", agregada a "${tabla}".."$)
Catch
Log(LastException)
End Try
Log(2)
End Try
End Sub

221
B4A/Tracker.bas Normal file
View File

@@ -0,0 +1,221 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Service
Version=10.5
@EndOfDesignText@
#Region Service Attributes
#StartAtBoot: True
#End Region
'******************************************************************************
'No olvidar agregar esta linea al editor de manifiesto:
' SetServiceAttribute(Tracker, android:foregroundServiceType, "location")
'
'En Starter agregar estas lineas en Process_Globals
' Public rp As RuntimePermissions
' Public FLP As FusedLocationProvider
' Private flpStarted As Boolean
'
'En Main agregar estas lineas a Activity_Resume
' Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION)
' Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
' If Result Then
' StartService(Tracker)
' Log("Start Tracker")
' Else
' ToastMessageShow("No permission", True)
' End If
'
'Se necesitan las librerias FusedLocationProvider, GPS, Phone y RunTimePermissions
'
'Y en Main agregar estas dos lineas:
'#AdditionalJar: com.android.support:support-v4
'#AdditionalJar: com.google.android.gms:play-services-location
Sub Process_Globals
Private nid As Int = 1
Private Tracking As Boolean
Private lock As PhoneWakeState
Public flp As FusedLocationProvider
Private flpStarted As Boolean
Dim minAccuracy As Int = 50
Dim killerCalled As Int = 0
Dim locReqSmall, locReqNormal As LocationRequest
End Sub
Sub Service_Create
Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_NEVER 'we are handling it ourselves
Subs.revisaBD
flp.Initialize("flp")
flp.Connect
lock.PartialLock
StartFLP
' If Starter.logger Then Log("FLP initialized")
Subs.bitacora($"Iniciamos Tracker"$)
End Sub
Sub Service_Start (StartingIntent As Intent)
locReqSmall = CreateLocationRequest2(1000, 0) 'ignore
locReqNormal = CreateLocationRequest2(30000, 30) 'ignore
Service.StopAutomaticForeground
Service.StartForeground(nid, Subs.CreateNotification("..."))
Track
StartServiceAt(Me, DateTime.Now + 60 * DateTime.TicksPerMinute, True)
Subs.bitacora($"Tracker - Service_Start"$)
End Sub
'Apagamos y prendemos sel servicio "Tracker" o reinicamos la aplicacion.
'killerCalled = 0 -> Apagamos y prendemos.
'killerCalled = 1 -> ExitApplication (se reinican todos los servicios).
Sub flpReConnect
Try
If killerCalled = 0 Then
killerCalled = 1
CallSubDelayed(Starter, "restartTracker")
Else
Subs.bitacora("Llamamos EXIT-APP")
ExitApplication
End If
Catch
Log("FLP-Tracker Error -> " & LastException)
End Try
End Sub
Sub flp_ConnectionSuccess
' If Starter.logger Then Log("FLP - Connected to location provider")
Subs.bitacora("FLP - Connection Success")
End Sub
Sub flp_ConnectionFailed(ConnectionResult1 As Int)
Log("Failed to connect to location provider")
Subs.bitacora("FLP - Connection Failed")
End Sub
Public Sub Track
If Starter.logger Then Log("Track")
If Tracking Then Return 'Si ya estamos "rastreando" no hacemos nada (return)
If Starter.rp.Check(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION) = False Then
Log("No permission")
Return
End If
StartFLP 'Iniciamos FusedLocationProvider
Tracking = True
End Sub
Public Sub StartFLP
' Log("StartFLP - flpStarted="&flpStarted)
Private cont As Int = 0
Do While flp.IsConnected = False
Sleep(500)
' If Starter.logger Then Log($"FLP Sleeping - ${cont}"$)
Subs.bitacora($"Sleeping - ${cont}"$)
cont = cont + 1
If cont > 70 Then
cont = 0
LogColor("Reiniciamos FLP", Colors.red)
killerCalled = 1 : flpReConnect
End If
Loop
flp.RequestLocationUpdates(CreateLocationRequest) 'Buscamos ubicacion
flpStarted = True
' End If
End Sub
Sub CreateLocationRequest As LocationRequest
' Log("CreateLocationRequest")
Dim lr As LocationRequest
lr.Initialize
lr.SetInterval(30000) 'Intervalo deseado para actualizaciones de ubicacion en milisegundos
lr.SetFastestInterval(lr.GetInterval / 2) 'Intervalo minimo para actualizaciones de ubicacion
lr.SetSmallestDisplacement(30) 'Solo registra cambio de ubicacion si es mayor a XX mts
lr.SetPriority(lr.Priority.PRIORITY_HIGH_ACCURACY)
Return lr
End Sub
Sub CreateLocationRequest2(interval0 As Int, displacement0 As Int) As LocationRequest 'ignore
' Log("CreateLocationRequestSmall")
Dim lr As LocationRequest
lr.Initialize
lr.SetInterval(interval0) 'Intervalo deseado para actualizaciones de ubicacion en milisegundos
lr.SetFastestInterval(lr.GetInterval / 2) 'Intervalo minimo para actualizaciones de ubicacion
lr.SetSmallestDisplacement(displacement0) 'Solo registra cambio de ubicacion si es mayor a XX mts
lr.SetPriority(lr.Priority.PRIORITY_HIGH_ACCURACY)
Return lr
End Sub
Public Sub StopFLP
If Starter.logger Then Log("StopFLP")
If flpStarted Then
If flp.IsConnected Then flp.RemoveLocationUpdates 'Eliminamos todas las solicitudes de ubicacion
flpStarted = False
End If
End Sub
Sub flp_LocationChanged (Location1 As Location)
Starter.UUC = Location1
' If Starter.logger Then LogColor("FLP_LocationChanged", Colors.Red)
If Starter.logger Then LogColor($"FLP_LocationChanged - Acc: ${Location1.Accuracy}"$, Colors.Red)
Private vel As String = (Location1.Speed * 60 * 60) / 1000 ' Kms x hora de ultima ubicacion.
' If Starter.logger Then Log((Location1.time & " - " & Starter.locAntTime))
If Starter.logger Then Log(((Location1.time - Subs.traeVar("locAntTime", 0)) / 1000) & " segs")
If Location1.Latitude <> 0 Then Subs.guardaInfoEnBD(Location1)
' Private minsTranscurridosLoc As String = Subs.ticksAMins(Location1.time - Starter.locAntTime) 'Minutos transcurridos desde la ultima ubicacion ACTUALIZADA.
' Private minsTranscurridos As String = Subs.ticksAMins(DateTime.Now - Subs.traeUltimaUbicacionGuardada.Time) 'Minutos transcurridos desde la ultima ubicacion guardada.
' If Starter.logger Then LogColor(">>>>>>>> Guardada: " & minsTranscurridos & " mins., Actualizada: " & minsTranscurridosLoc & " mins.", Colors.red)
' If Not(IsPaused(Main)) Then
' Main.laUbicacion = Location1 ' Actualizamos la etiqueta de ubicacion en la pantalla principal.
' If Starter.logger Then Log("Main.laubicacion actializada")
' End If
' Dim el_texto As String = ""
' If Starter.logger Then Log(Location1.Accuracy&" - "&Starter.UUC.AccuracyValid)
' If minsTranscurridosLoc > 1 Or minsTranscurridos >= 15 Then ' Para que no mande mensajes constantes, minimo 1 minuto entre mensajes.
' flp.RequestLocationUpdates(CreateLocationRequest)
' 'Solo mandamos la ubicacion si la precision es dentro de XX mts
' el_texto = $"LocChange - Coords NO enviadas (Acc:${Location1.Accuracy})."$
' If Location1.Accuracy < minAccuracy Then
' If Starter.logger Then LogColor("Guardamos y enviamos ubicacion.", Colors.green)
Subs.mandaLoc2(Location1, Starter.devModel)
' el_texto = $"LocChange - Coords enviadas (Acc:${Location1.Accuracy})."$
' End If
' ' If Starter.logger Then Log("Loc changed : "&Location1.Latitude&","&Location1.Longitude&"|"&Starter.devModel&"|")
' Subs.bitacora($"${el_texto}"$)
'' ToastMessageShow("LocChanged MORE than a min.", False)
' Else
'' ToastMessageShow("Locatin changed but less than a min!.", False)
' End If
' Subs.actualizaVar("locAntTime", Location1.time)
End Sub
Sub flp_ConnectionSuspended(SuspendedCause1 As Int)
Dim Cause As String
Log("ConnectionSuspended")
Subs.bitacora("ConnectionSuspended")
If(SuspendedCause1=flp.SuspendedCause.CAUSE_NETWORK_LOST) Then
Cause="Suspended by NetworkLost"
Else If(SuspendedCause1=flp.SuspendedCause.CAUSE_SERVICE_DISCONNECTED) Then
Cause="Suspended by Disconnected"
Else
Cause="Suspended: Unknow cause"
End If
Cause = Cause&": "& Subs.fechaNormal(DateTime.Now)
LogColor(Cause, Colors.magenta)
Subs.bitacora(Cause)
flp.Disconnect
Sleep(5000)
flp.Connect
End Sub
Sub Service_Destroy
If Tracking Then
Try
StopFLP
Catch
Log(LastException)
End Try
End If
Tracking = False
lock.ReleasePartialLock
Subs.bitacora($"Tracker - Service_Destroy"$)
End Sub

164
B4A/errorManager.bas Normal file
View File

@@ -0,0 +1,164 @@
B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Activity
Version=10.2
@EndOfDesignText@
#Region Activity Attributes
#FullScreen: False
#IncludeTitle: True
#End Region
'******************************************************************************
'Este modulo intercepta los errores de la aplicación mediante "Starter.Application_Error" y muestra una pantalla
'con el log del error y lo manda al servidor con un query de DBRequestManager, se necesita que exista el query
'en el "config.properties" llamado "guardaErrores" y que tenga el siguiente texto:
'
'sql.guardaErrores=INSERT INTO KELLOGGS.PUSH_INFO (ID, RUTA, FECHA, DATOS) VALUES((?),(?),(?),(?))
'
'Agregar estas lineas a "Starter.Process_Globals"
' 'Para los Logs
' Dim logs As StringBuilder
' Private logcat As LogCat
'
'Agregar estas lineas a "Starter.Service_Create"
' 'Para los Logs
' #if RELEASE
' logcat.LogCatStart(Array As String("-v","raw","*:F","B4A:v"), "logcat")
' #end if
' logs.Initialize
'
'Agregar este Sub a "Starter"
'
'Return true to allow the OS default exceptions handler to handle the uncaught exception. 'Para los Logs
'Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
' 'wait for 500ms to allow the logs to be updated.
' Dim jo As JavaObject
' Dim l As Long = 500: jo.InitializeStatic("java.lang.Thread").RunMethod("sleep", Array(l)) 'Sleep 500ms
' logcat.LogCatStop
' logs.Append(StackTrace)
' Subs.revisaBD
' Subs.errorLog.ExecNonQuery2("INSERT INTO errores(fecha, error) VALUES (?,?)", Array As Object (Subs.fechaKMT(DateTime.now), logs))
' StartActivity(errorManager)
' Return True
'End Sub
'******************************************************************************
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
End Sub
Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.
' Dim errorLog As SQL
Dim c As Cursor
' Private p_principal As Panel
' Private l_titulo As Label
' Private svScroll As ScrollView
' Private etText As EditText
' Private c_continuar As Button
' Private p_botones As Panel
' Private b_salir As Button
End Sub
Sub Activity_Create(FirstTime As Boolean)
'Do not forget to load the layout file created with the visual designer. For example:
' Activity.LoadLayout("errorManager")
End Sub
Sub Activity_Resume
Dim elError As String = ""
Dim laFecha As String = ""
' svScroll.Initialize(500dip)
' Activity.AddView(svScroll, 0, 300, 100%x, 80%y)
' p_principal.Height = Activity.Height
' p_principal.Width = Activity.Width
' svScroll.Width = Round(p_principal.Width * 0.9)
' svScroll.Left = Round(p_principal.Width/2)-Round(svScroll.Width/2)
' p_botones.Left = Round(p_principal.Width/2)-Round(p_botones.Width/2)
' p_botones.Top = Activity.Height - (p_botones.Height + 80)
' etText.Initialize("")
' etText.TextSize = 13
' etText.Wrap = True
' Activity.RemoveViewAt(1)
' svScroll.Panel.AddView(etText, 0, 0, 90%x, 80%y)
'' etText.Width = svScroll.Width - 100
' etText.InputType = etText.INPUT_TYPE_NONE
' etText.Gravity = Gravity.TOP
' etText.SingleLine = False
' etText.Wrap = True
' Dim lblText, edtText As StringBuilder
' Dim lbl As Label
' lbl.Initialize("")
' Activity.AddView(lbl, 0, 300, 100%x, 100%y) 'ignore
' etText.Text = ""
' Subs.revisaBD
c = Starter.errorLog.ExecQuery("select * from errores order by fecha desc limit 1")
If c.RowCount > 0 Then
c.Position = 0
elError = c.GetString("error")
laFecha = c.GetString("fecha")
' etText.Text = elError
End If
c.Close
' Log("++++++" & Starter.logsStr)
' etText.Text = etText.Text & Starter.logsStr
' lbl.TextSize = etText.TextSize
' lbl.Text = etText.Text
' Dim su As StringUtils
' Dim edheight As Int = su.MeasureMultilineTextHeight(lbl, lbl.Text)
' lbl.RemoveView
' etText.Height = edheight
' svScroll.Panel.Height = edheight
' svScroll.Height = Round(Activity.Height * 0.9)
' Log(edheight)
Dim cmd As DBCommand
cmd.Initialize
cmd.Name = "guardaErrores"
cmd.Parameters = Array As Object(laFecha, Starter.devModel, laFecha, elError)
Log($"Mandamos: ${Subs.fechaKMT(DateTime.Now)}, |${Starter.devModel}|, ${Subs.fechaKMT(DateTime.Now)}"$)
Starter.reqManager.ExecuteCommand(cmd,"guardaErrores")
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub JobDone(Job As HttpJob)
If Job.Success = False Then
ToastMessageShow("Error: " & Job.ErrorMessage, True)
Else
LogColor("JobDone: '" & Starter.reqManager.HandleJob(Job).tag & "' - Registros: " & Starter.reqManager.HandleJob(Job).Rows.Size, Colors.Green) 'Mod por CHV - 211110
If Job.JobName = "DBRequest" Then
Dim result As DBResult = Starter.reqManager.HandleJob(Job)
If result.Tag = "guardaErrores" Then 'query tag
For Each records() As Object In result.Rows
For Each k As String In result.Columns.Keys
Log("GuardaErrores: " & k & ": " & records(result.Columns.Get(k)))
Next
Next
End If
End If
End If
Job.Release
End Sub
Private Sub c_continuar_Click
' Subs.iniciaActividad("Principal")
' B4XPages.ShowPage("Principal")
End Sub
Private Sub b_salir_Click
cierraActividades
End Sub
Sub cierraActividades
Log("closing activities")
Dim jo As JavaObject
jo.InitializeContext
jo.RunMethod("finishAffinity", Null)
End Sub

213
B4A/google-services.json Normal file
View File

@@ -0,0 +1,213 @@
{
"project_info": {
"project_number": "821860097209",
"project_id": "pusher-4c091",
"storage_bucket": "pusher-4c091.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:821860097209:android:328e84bfb7adb112f24f68",
"android_client_info": {
"package_name": "dreparto.keymon.com.mx"
}
},
"oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:821860097209:android:7bdc730c1cad5927f24f68",
"android_client_info": {
"package_name": "durakelo.keymon.com.mx"
}
},
"oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:821860097209:android:4a9c1af4c93ba100f24f68",
"android_client_info": {
"package_name": "flp2.chv.com"
}
},
"oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:821860097209:android:7b6620b2a870f23cf24f68",
"android_client_info": {
"package_name": "gunav2.keymon.com.mx"
}
},
"oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:821860097209:android:f0e04307b3842e25f24f68",
"android_client_info": {
"package_name": "prof_rep.keymon.com.mx"
}
},
"oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:821860097209:android:7780f81ae43bf0f3f24f68",
"android_client_info": {
"package_name": "pusher.chv.com"
}
},
"oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:821860097209:android:7c55bc95da6d952df24f68",
"android_client_info": {
"package_name": "ths.keymon.com.mx"
}
},
"oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}