mirror of
https://github.com/cheveguerra/FLP_3.0.git
synced 2026-04-17 19:36:19 +00:00
. Commit inicial.
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
**/Objects
|
||||
**/AutoBackups
|
||||
242
B4A/B4XMainPage.bas
Normal file
242
B4A/B4XMainPage.bas
Normal 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
282
B4A/DBRequestManager.bas
Normal 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
113
B4A/FLP 3.0.b4a
Normal 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
36
B4A/FLP 3.0.b4a.meta
Normal 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
BIN
B4A/Files/gps_hist.db
Normal file
Binary file not shown.
BIN
B4A/Files/layout.bal
Normal file
BIN
B4A/Files/layout.bal
Normal file
Binary file not shown.
BIN
B4A/Files/mainpage.bal
Normal file
BIN
B4A/Files/mainpage.bal
Normal file
Binary file not shown.
87
B4A/FirebaseMessaging.bas
Normal file
87
B4A/FirebaseMessaging.bas
Normal 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
205
B4A/FirebaseMessaging0.bas
Normal 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
215
B4A/NotificationService.bas
Normal 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
18
B4A/R_Test.bas
Normal 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
269
B4A/Starter.bas
Normal 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
453
B4A/Subs.bas
Normal 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
221
B4A/Tracker.bas
Normal 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
164
B4A/errorManager.bas
Normal 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
213
B4A/google-services.json
Normal 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"
|
||||
}
|
||||
Reference in New Issue
Block a user