mirror of
https://github.com/cheveguerra/FLP_2.0.git
synced 2026-04-17 19:36:42 +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
|
||||||
273
DBRequestManager.bas
Normal file
273
DBRequestManager.bas
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
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 = 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))
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
149
DBRequestManagerV2.bas
Normal file
149
DBRequestManagerV2.bas
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
B4J=true
|
||||||
|
Group=Default Group
|
||||||
|
ModulesStructureVersion=1
|
||||||
|
Type=Class
|
||||||
|
Version=5.45
|
||||||
|
@EndOfDesignText@
|
||||||
|
'Requires support for resumable subs
|
||||||
|
'Class module
|
||||||
|
|
||||||
|
Sub Class_Globals
|
||||||
|
Private mTarget As Object
|
||||||
|
Private link As String
|
||||||
|
Private VERSION As Float = 2
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
'Target - The module that handles JobDone (usually Me).
|
||||||
|
'ConnectorLink - URL of the Java server.
|
||||||
|
Public Sub Initialize (Target As Object, ConnectorLink As String)
|
||||||
|
mTarget = Target
|
||||||
|
link = ConnectorLink
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
'Sends a query request.
|
||||||
|
'Command - Query name and parameters.
|
||||||
|
'Limit - Maximum rows to return or 0 for no limit.
|
||||||
|
'Tag - An object that will be returned in the result.
|
||||||
|
Public Sub ExecuteQuery(Command As DBCommand, Limit As Int, Tag As Object, Timeout As Int) As HttpJob
|
||||||
|
Dim ser As B4XSerializator
|
||||||
|
Dim data() As Byte = ser.ConvertObjectToBytes(CreateMap("command": Command, "limit": Limit, "version": VERSION))
|
||||||
|
Return SendJob(CreateJob, data, Tag, "query2", Timeout)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub SendJob(j As HttpJob, Data() As Byte, Tag As Object, Method As String, Timeout As Int) As HttpJob
|
||||||
|
j.Tag = Tag
|
||||||
|
j.PostBytes(link & "?method=" & Method , Data)
|
||||||
|
If Timeout <> 0 Then j.GetRequest.Timeout = Timeout
|
||||||
|
Return j
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub CreateJob As HttpJob
|
||||||
|
Dim j As HttpJob
|
||||||
|
j.Initialize("DBRequest", mTarget)
|
||||||
|
Return j
|
||||||
|
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) As HttpJob
|
||||||
|
Dim j As HttpJob = CreateJob
|
||||||
|
ExecuteBatchImpl(j, ListOfCommands, Tag)
|
||||||
|
Return j
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub ExecuteBatchImpl(Job As HttpJob, ListOfCommands As List, Tag As Object)
|
||||||
|
Dim ser As B4XSerializator
|
||||||
|
ser.ConvertObjectToBytesAsync(CreateMap("commands": ListOfCommands, "version": VERSION), "ser")
|
||||||
|
Wait For (ser) ser_ObjectToBytes (Success As Boolean, Bytes() As Byte)
|
||||||
|
If Success = False Then
|
||||||
|
Log("Error building command: " & LastException)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
Dim ser As B4XSerializator = Sender
|
||||||
|
SendJob(Job, Bytes, Tag, "batch2", 0)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
|
'Similar to ExecuteBatch. Sends a single command.
|
||||||
|
Public Sub ExecuteCommand(Command As DBCommand, Tag As Object) As HttpJob
|
||||||
|
Return ExecuteBatch(Array As DBCommand(Command), Tag)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
'Handles the Job result and returns a DBResult.
|
||||||
|
'It is recommended to use HandleJobAsync instead.
|
||||||
|
Public Sub HandleJob(Job As HttpJob) As DBResult
|
||||||
|
Dim ser As B4XSerializator
|
||||||
|
Dim data() As Byte = Bit.InputStreamToBytes(Job.GetInputStream)
|
||||||
|
Dim res As DBResult = ser.ConvertBytesToObject(data)
|
||||||
|
res.Tag = Job.Tag
|
||||||
|
Return res
|
||||||
|
End Sub
|
||||||
|
'Handles the Job result and raises the Result event when the data is ready.
|
||||||
|
|
||||||
|
Public Sub HandleJobAsync(Job As HttpJob, EventName As String)
|
||||||
|
Dim ser As B4XSerializator
|
||||||
|
Dim data() As Byte = Bit.InputStreamToBytes(Job.GetInputStream)
|
||||||
|
ser.ConvertBytesToObjectAsync(data, "ser")
|
||||||
|
Wait For (ser) ser_BytesToObject (Success As Boolean, NewObject As Object)
|
||||||
|
If Success = False Then
|
||||||
|
Log("Error reading response: " & LastException)
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
Dim res As DBResult = NewObject
|
||||||
|
res.Tag = Job.Tag
|
||||||
|
CallSubDelayed2(mTarget, EventName & "_result", res)
|
||||||
|
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
|
||||||
|
#if Not(B4J)
|
||||||
|
'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
|
||||||
|
#End If
|
||||||
|
|
||||||
|
'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
|
||||||
|
Log(sb.ToString)
|
||||||
|
Next
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
216
FLP-ML.b4a
Normal file
216
FLP-ML.b4a
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
Build1=Default,flp2.chv.com
|
||||||
|
File1=gps_hist.db
|
||||||
|
File2=Layout.bal
|
||||||
|
FileGroup1=Default Group
|
||||||
|
FileGroup2=Default Group
|
||||||
|
Group=Default Group
|
||||||
|
Library1=administrator
|
||||||
|
Library10=mlwifi400
|
||||||
|
Library11=notificationlistener
|
||||||
|
Library12=okhttputils2
|
||||||
|
Library13=phone
|
||||||
|
Library14=randomaccessfile
|
||||||
|
Library15=reflection
|
||||||
|
Library16=runtimepermissions
|
||||||
|
Library17=sql
|
||||||
|
Library18=replyauto
|
||||||
|
Library2=byteconverter
|
||||||
|
Library3=compressstrings
|
||||||
|
Library4=core
|
||||||
|
Library5=firebaseanalytics
|
||||||
|
Library6=firebasenotifications
|
||||||
|
Library7=fusedlocationprovider
|
||||||
|
Library8=gps
|
||||||
|
Library9=json
|
||||||
|
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="14" android:targetSdkVersion="27"/>~\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~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~~\n~AddApplicationText(<receiver android:name="anywheresoftware.b4a.objects.AdminReceiver2"~\n~ android:permission="android.permission.BIND_DEVICE_ADMIN">~\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" />~\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="Mariana" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">~\n~ <intent-filter><action android:name="android.service.notification.NotificationListenerService" /></intent-filter>~\n~ </service>)
|
||||||
|
Module1=DBRequestManager
|
||||||
|
Module2=FirebaseMessaging
|
||||||
|
Module3=Mods
|
||||||
|
Module4=NotificationService
|
||||||
|
Module5=Starter
|
||||||
|
Module6=Subs
|
||||||
|
Module7=Tracker
|
||||||
|
NumberOfFiles=2
|
||||||
|
NumberOfLibraries=18
|
||||||
|
NumberOfModules=7
|
||||||
|
Version=12.5
|
||||||
|
@EndOfDesignText@
|
||||||
|
#Region Project Attributes
|
||||||
|
#ApplicationLabel: FLP 2.0
|
||||||
|
#VersionCode: 1
|
||||||
|
#VersionName: 3.07.07
|
||||||
|
'SupportedOrientations possible values: unspecified, landscape or portrait.
|
||||||
|
#SupportedOrientations: unspecified
|
||||||
|
#CanInstallToExternalStorage: False
|
||||||
|
' #AdditionalJar: com.android.support:support-v4
|
||||||
|
#AdditionalJar: com.google.android.gms:play-services-location
|
||||||
|
#BridgeLogger:True
|
||||||
|
#End Region
|
||||||
|
|
||||||
|
#Region Activity Attributes
|
||||||
|
#FullScreen: False
|
||||||
|
#IncludeTitle: 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.
|
||||||
|
Dim wifi As MLwifi
|
||||||
|
Dim wifiS As MLScan
|
||||||
|
Public manager As AdminManager
|
||||||
|
' Dim ruta As String
|
||||||
|
Dim fechaRuta As String
|
||||||
|
Dim laUbicacion As Location
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Globals
|
||||||
|
'These global variables will be redeclared each time the activity is created.
|
||||||
|
Private Button1 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
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Activity_Create(FirstTime As Boolean)
|
||||||
|
Activity.LoadLayout("Layout")
|
||||||
|
' ruta = File.DirInternal
|
||||||
|
Subs.getPhnId
|
||||||
|
et_id.Text = Starter.devModel.trim
|
||||||
|
getSSID
|
||||||
|
Button1.Left = Round(Activity.Width/2)-(Button1.Width/2)
|
||||||
|
l_id.Left = (Activity.Width / 2) - (l_id.Width / 2)
|
||||||
|
l_lastUpdate.Left = (Activity.Width / 2) - (l_lastUpdate.Width / 2)
|
||||||
|
b_guardarId.Left = (Activity.Width / 2) - (b_guardarId.Width / 2)
|
||||||
|
et_id.Left = (Activity.Width / 2) - (et_id.Width / 2)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Activity_Resume
|
||||||
|
chkPermisosUbicacion 'Permisos de ubicacion para Tracker
|
||||||
|
chkPermisosAlmacenamientoExterno
|
||||||
|
Subs.getPhnId
|
||||||
|
et_id.Text = Starter.devModel.Trim
|
||||||
|
getSSID
|
||||||
|
getAdminRights
|
||||||
|
l_lastUpdate.Text = 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
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Activity_Pause (UserClosed As Boolean)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Button1_Click
|
||||||
|
Subs.mandaLocAServer(laUbicacion, 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 Button1_LongClick
|
||||||
|
copiaDB
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
' 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(Starter.ruta , "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 Tracker.FLP.IsInitialized Then Subs.mandaLocAServer(laUbicacion, Starter.devModel.Trim)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub ponCoords
|
||||||
|
l_coords.left = (Activity.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
|
||||||
27
FLP-ML.b4a.meta
Normal file
27
FLP-ML.b4a.meta
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
ModuleBookmarks0=
|
||||||
|
ModuleBookmarks1=
|
||||||
|
ModuleBookmarks2=
|
||||||
|
ModuleBookmarks3=
|
||||||
|
ModuleBookmarks4=
|
||||||
|
ModuleBookmarks5=
|
||||||
|
ModuleBookmarks6=
|
||||||
|
ModuleBookmarks7=
|
||||||
|
ModuleBreakpoints0=
|
||||||
|
ModuleBreakpoints1=
|
||||||
|
ModuleBreakpoints2=
|
||||||
|
ModuleBreakpoints3=
|
||||||
|
ModuleBreakpoints4=
|
||||||
|
ModuleBreakpoints5=
|
||||||
|
ModuleBreakpoints6=
|
||||||
|
ModuleBreakpoints7=
|
||||||
|
ModuleClosedNodes0=12,13
|
||||||
|
ModuleClosedNodes1=
|
||||||
|
ModuleClosedNodes2=
|
||||||
|
ModuleClosedNodes3=1
|
||||||
|
ModuleClosedNodes4=
|
||||||
|
ModuleClosedNodes5=
|
||||||
|
ModuleClosedNodes6=2,3,4,5,6,7,8,9,10,11,12,13,16
|
||||||
|
ModuleClosedNodes7=7,8
|
||||||
|
NavigationStack=Subs,ConvertMillisecondsToString,179,0,Main,actualizaLabelUU,173,5,Main,b_guardarId_Click,142,0,Visual Designer,Layout.bal,-100,6,Main,Globals,36,1,Main,Activity_Create,42,6,Starter,Timer1_Tick,54,0,Starter,Process_Globals,15,0,Subs,fechaKMT,141,0,Subs,mandaLocAServer,171,6
|
||||||
|
SelectedBuild=0
|
||||||
|
VisibleModules=5,2,7,3,6,4
|
||||||
180
FLP.bas
Normal file
180
FLP.bas
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
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 necesita la libreria FusedLocationProvider, Phone, GPS 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 GPS As GPS
|
||||||
|
Private Tracking As Boolean
|
||||||
|
Private LastUpdateTime As Long
|
||||||
|
Private lock As PhoneWakeState
|
||||||
|
'Para FusedLocationProvider (2 lineas)
|
||||||
|
Public FLP As FusedLocationProvider
|
||||||
|
Private flpStarted As Boolean
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Create
|
||||||
|
Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_NEVER 'we are handling it ourselves
|
||||||
|
'Para FusedLocationProvider (2 lineas)
|
||||||
|
FLP.Initialize("flp")
|
||||||
|
FLP.Connect
|
||||||
|
lock.PartialLock
|
||||||
|
StartFLP
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub flp_ConnectionSuccess
|
||||||
|
Log("Connected to location provider")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub flp_ConnectionFailed(ConnectionResult1 As Int)
|
||||||
|
Log("Failed to connect to location provider")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Start (StartingIntent As Intent)
|
||||||
|
'Para FusedLocationProvider (1 linea)
|
||||||
|
Service.StopAutomaticForeground
|
||||||
|
Service.StartForeground(nid, CreateNotification("..."))
|
||||||
|
StartServiceAt(Me, DateTime.Now + 30 * DateTime.TicksPerMinute, True)
|
||||||
|
Track
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Sub StartFLP
|
||||||
|
Log("StartFLP - flpStarted="&flpStarted)
|
||||||
|
Do While FLP.IsConnected = False
|
||||||
|
Sleep(500)
|
||||||
|
Log("sleeping")
|
||||||
|
Loop
|
||||||
|
If flpStarted = False Then
|
||||||
|
Log("RequestLocationUpdates")
|
||||||
|
FLP.RequestLocationUpdates(CreateLocationRequest) 'Buscamos ubicacion
|
||||||
|
Log("Buscamos ubicacion")
|
||||||
|
flpStarted = True
|
||||||
|
Else
|
||||||
|
FLP.RequestLocationUpdates(CreateLocationRequest2times) 'Buscamos ubicacion 2 peticiones
|
||||||
|
Log("Buscamos ubicacion 2 peticiones")
|
||||||
|
End If
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub CreateLocationRequest As LocationRequest
|
||||||
|
'Log("CreateLocationRequest")
|
||||||
|
Dim lr As LocationRequest
|
||||||
|
lr.Initialize
|
||||||
|
lr.SetInterval(10000)
|
||||||
|
lr.SetFastestInterval(lr.GetInterval / 2)
|
||||||
|
lr.SetSmallestDisplacement(10) 'Solo registra cambio de ubicacion si es mayor a 50 mts
|
||||||
|
lr.SetPriority(lr.Priority.PRIORITY_HIGH_ACCURACY)
|
||||||
|
Return lr
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub CreateLocationRequest2times As LocationRequest
|
||||||
|
'Log("CreateLocationRequest")
|
||||||
|
Dim lr As LocationRequest
|
||||||
|
lr.Initialize
|
||||||
|
lr.SetInterval(5000)
|
||||||
|
lr.SetFastestInterval(lr.GetInterval / 2)
|
||||||
|
lr.setNumUpdates(2)
|
||||||
|
lr.SetSmallestDisplacement(50) 'Solo registra cambio de ubicacion si es mayor a 50 mts
|
||||||
|
lr.SetPriority(lr.Priority.PRIORITY_HIGH_ACCURACY)
|
||||||
|
Return lr
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Sub StopFLP
|
||||||
|
'Log("StopFLP")
|
||||||
|
If flpStarted Then
|
||||||
|
FLP.RemoveLocationUpdates
|
||||||
|
flpStarted = False
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Sub Track
|
||||||
|
'Log("Track")
|
||||||
|
If Tracking Then Return
|
||||||
|
If Starter.rp.Check(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION) = False Then
|
||||||
|
Log("No permission")
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
'Para FusedLocationProvider (1 linea)
|
||||||
|
StartFLP
|
||||||
|
Tracking = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub flp_LocationChanged (Location1 As Location)
|
||||||
|
If DateTime.Now > LastUpdateTime + 10 * DateTime.TicksPerSecond Then
|
||||||
|
Dim n As Notification = CreateNotification($"$2.5{Location1.Latitude} / $2.5{Location1.Longitude}"$)
|
||||||
|
n.Notify(nid)
|
||||||
|
LastUpdateTime = DateTime.Now
|
||||||
|
End If
|
||||||
|
Log("loc changed")
|
||||||
|
Dim coords As String = Location1.Latitude&","&Location1.Longitude&","&Main.devModel
|
||||||
|
CallSub2(Main,"ubicacionRecibida",coords)
|
||||||
|
'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
|
||||||
|
|
||||||
|
'Escribimos coordenadas y fecha a un archivo de texto
|
||||||
|
' Dim ubic As String = Location1.Latitude&","&Location1.Longitude&"|"&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
|
||||||
|
|
||||||
|
Log("Loc changed : "&Location1.Latitude&","&Location1.Longitude&"|"&Location1.Accuracy&"|"&lastUpdate)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub CreateNotification (Body As String) As Notification
|
||||||
|
Dim notification As Notification
|
||||||
|
notification.Initialize2(notification.IMPORTANCE_LOW)
|
||||||
|
notification.Icon = "icon"
|
||||||
|
notification.SetInfo("Tracking location", Body, Main)
|
||||||
|
Return notification
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Destroy
|
||||||
|
If Tracking Then
|
||||||
|
StopFLP
|
||||||
|
End If
|
||||||
|
Tracking = False
|
||||||
|
lock.ReleasePartialLock
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
'//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
'//////////////////////////////// EXTRAS ///////////////////////////////////////////////////////
|
||||||
|
'//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Public Sub StartLocationUpdates
|
||||||
|
FLP.RequestLocationUpdates(CreateLocationRequest)
|
||||||
|
End Sub
|
||||||
BIN
Files/gps_hist.db
Normal file
BIN
Files/gps_hist.db
Normal file
Binary file not shown.
BIN
Files/layout.bal
Normal file
BIN
Files/layout.bal
Normal file
Binary file not shown.
195
FirebaseMessaging.bas
Normal file
195
FirebaseMessaging.bas
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
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
|
||||||
|
Starter.ruta = File.DirInternal
|
||||||
|
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
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Start (StartingIntent As Intent)
|
||||||
|
Subs.getPhnId
|
||||||
|
Subs.gps_hist.Initialize(Starter.ruta,"gps_hist.db", True)
|
||||||
|
Subs.gps_hist.ExecNonQuery("CREATE TABLE IF NOT EXISTS RUTA_GPS(FECHA INTEGER, LAT TEXT, LON TEXT)")
|
||||||
|
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 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.Latitude <> 0.0 Then
|
||||||
|
mandamosLoc($"${Starter.UUC.Latitude},${Starter.UUC.Longitude},${Subs.formatoFecha(Starter.UUC.Time)}"$)
|
||||||
|
If Starter.logger Then LogColor($"Mandamos UUC: ${Starter.UUC.Latitude},${Starter.UUC.Longitude},${Subs.formatoFecha(Starter.UUC.Time)}"$, Colors.Magenta)
|
||||||
|
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.GetRequest.SetContentType("application/json;charset=UTF-8")
|
||||||
|
Job.GetRequest.SetHeader("Authorization", "key=" & API_KEY)
|
||||||
|
If Starter.logger Then Log("Mandamos mensaje: " & m)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub mandamosLoc(coords As String)
|
||||||
|
If Starter.logger Then LogColor("Iniciamos mandamosLoc ("&coords&")", Colors.Magenta)
|
||||||
|
' Log("locRequest="&locRequest)
|
||||||
|
Subs.guardaInfoEnBD(coords)'Escribimos coordenadas y fecha a una bd
|
||||||
|
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)
|
||||||
|
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
|
||||||
35
Mods.bas
Normal file
35
Mods.bas
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
B4A=true
|
||||||
|
Group=Default Group
|
||||||
|
ModulesStructureVersion=1
|
||||||
|
Type=StaticCode
|
||||||
|
Version=11
|
||||||
|
@EndOfDesignText@
|
||||||
|
'Code module
|
||||||
|
Sub process_globals
|
||||||
|
End Sub
|
||||||
|
'Ver 3.07.07
|
||||||
|
'Se hicieron ajustes a la precision minima y a como y cuando manda los datos al servidor.
|
||||||
|
|
||||||
|
'Ver 2.01.29
|
||||||
|
'Se paso a "Starter.Service_Create" el código para al iniciar, copiar la base de datos a la tarjeta.
|
||||||
|
|
||||||
|
'Ver 2.01.14
|
||||||
|
'Se cambio codigo en "FirebaseMessaging.SendMessage" para que mande la version en cada mensaje "Application.VersionName"
|
||||||
|
|
||||||
|
'Agregué en Tracker:
|
||||||
|
'Sub formatoFecha(fecha As String) As String
|
||||||
|
' 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
|
||||||
|
|
||||||
|
'Modifique Tracker/flp_LocationChanged usando la funcion formatofecha:
|
||||||
|
|
||||||
|
' Dim coords As String = Location1.Latitude&","&Location1.Longitude&","&formatoFecha(DateTime.Now)
|
||||||
|
|
||||||
|
'Modifiqué Tracker/dameUltimaUbicacionConocida usando la funcion formatofecha:
|
||||||
|
' Dim coords As String = FLP.GetLastKnownLocation.Latitude&","&FLP.GetLastKnownLocation.Longitude&","&formatoFecha(FLP.GetLastKnownLocation.Time)
|
||||||
210
NotificationService.bas
Normal file
210
NotificationService.bas
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
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
|
||||||
|
' 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)
|
||||||
|
If not(Tracker.FLP.IsInitialized) then StartService(Tracker)
|
||||||
|
Private logger As Boolean = True
|
||||||
|
' 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
|
||||||
|
CallSub2(Tracker, "dameUltimaUbicacionConocida", Starter.UUC)
|
||||||
|
Log("Mandamos a Server")
|
||||||
|
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
|
||||||
76
Starter.bas
Normal file
76
Starter.bas
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
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 ruta As String
|
||||||
|
Dim reqManager As DBRequestManager
|
||||||
|
Dim cmd As DBCommand
|
||||||
|
Dim Timer1 As Timer
|
||||||
|
Dim interval As Int = 60 '600 segs (10 mins)
|
||||||
|
Dim UUC As Location
|
||||||
|
Dim run As Int = 0 'ignore
|
||||||
|
Dim devModel As String
|
||||||
|
Dim lastLocUpdate As String = 0
|
||||||
|
Dim logger As Boolean = True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Create
|
||||||
|
'This is the program entry point.
|
||||||
|
'This is a good place to load resources that are not specific to a single activity.
|
||||||
|
ruta = File.DirInternal 'Ruta de la base de datos por defecto.
|
||||||
|
If File.ExternalWritable Then ruta = rp.GetSafeDirDefaultExternal("") 'Si podemos escribir a la tarjeta, cambiamos la ruta.
|
||||||
|
If Not(File.Exists(ruta, "gps_hist.db")) Then File.Copy(File.DirAssets, "gps_hist.db", ruta, "gps_hist.db") 'Si no existe el archivo de la base de datos, lo copiamos.
|
||||||
|
If logger Then Log(ruta)
|
||||||
|
CallSubDelayed(FirebaseMessaging, "SubscribeToTopics") 'Para FirebaseMessaging
|
||||||
|
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://10.0.0.205:1782")
|
||||||
|
reqManager.Initialize(Me, "http://keymon.lat:1782")
|
||||||
|
Timer1.Initialize("Timer1", interval * 1000)
|
||||||
|
Timer1.Enabled = True
|
||||||
|
UUC.Initialize
|
||||||
|
Subs.getPhnId
|
||||||
|
StartService(Tracker)
|
||||||
|
#if RELEASE
|
||||||
|
logger = False
|
||||||
|
#end if
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub Timer1_Tick
|
||||||
|
' ToastMessageShow("Timer",False)
|
||||||
|
If logger Then Log("Next run " & DateTime.Time(DateTime.Now + interval * 1000))
|
||||||
|
' Log($"|${Tracker.FLP.IsInitialized}|${Tracker.FLP.GetLastKnownLocation.IsInitialized}|"$)If DateTime.DateForm
|
||||||
|
CallSub2(Tracker, "dameUltimaUbicacionConocida", UUC)
|
||||||
|
'Si ya pasaron mas de 15 minutos (900 segs) desde la ultima actualización, entonces mandamos UUC.
|
||||||
|
If ((DateTime.now - lastLocUpdate)/1000) > (interval * 1.5) Then
|
||||||
|
LogColor($"Mandamos ubicacion porque no se ha enviado en ${(interval * 1.5)} segs."$, Colors.red)
|
||||||
|
Subs.mandaLocAServer(Tracker.FLP.GetLastKnownLocation, devModel)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_TaskRemoved
|
||||||
|
'This event will be raised when the user removes the app from the recent apps list.
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
'Return true to allow the OS default exceptions handler to handle the uncaught exception.
|
||||||
|
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
|
||||||
|
Return True
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Destroy
|
||||||
|
|
||||||
|
End Sub
|
||||||
188
Subs.bas
Normal file
188
Subs.bas
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
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
|
||||||
|
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)
|
||||||
|
Log($"CompressedBytesLength: ${compressed.Length}"$)
|
||||||
|
Dim base64 As String = su.EncodeBase64(compressed)
|
||||||
|
Log($"CompressedBytes converted to base64 Length: ${base64.Length}"$)
|
||||||
|
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)
|
||||||
|
Log($"decompressedbytesLength: ${decompressedbytes.Length}"$)
|
||||||
|
Dim bc As ByteConverter
|
||||||
|
Dim uncompressed As String = bc.StringFromBytes(decompressedbytes,"UTF8")
|
||||||
|
Log($"uncompressedLength: ${uncompressed.Length}"$)
|
||||||
|
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
|
||||||
|
|
||||||
|
Sub guardaInfoEnBD(coords As String) 'Escribimos coordenadas y fecha a una BD
|
||||||
|
If Starter.logger Then Log("Guardamos ubicacion en db (" & coords & ")")
|
||||||
|
Dim latlon() As String = Regex.Split(",", coords)
|
||||||
|
If gps_hist.IsInitialized = False Then gps_hist.Initialize(Starter.ruta, "gps_hist.db", True)
|
||||||
|
gps_hist.ExecNonQuery2("INSERT INTO RUTA_GPS(fecha, lat, lon) VALUES (?,?,?)", Array As Object (latlon(2),latlon(0),latlon(1)))
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub dameRuta As String
|
||||||
|
Dim c As Cursor
|
||||||
|
If gps_hist.IsInitialized = False Then gps_hist.Initialize(Starter.ruta, "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")
|
||||||
|
Main.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;")
|
||||||
|
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
|
||||||
|
' Starter.ruta = File.DirInternal
|
||||||
|
If File.Exists(Starter.ruta, "gps_hist.db") = False Then
|
||||||
|
File.Copy(File.DirAssets, "gps_hist.db", Starter.ruta, "gps_hist.db")
|
||||||
|
Log("No existe gps_hist, copiamos gps_hist.db")
|
||||||
|
End If
|
||||||
|
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
|
||||||
|
|
||||||
|
'Sub dameUltimaUbicacionConocida(lastLocation As Location)
|
||||||
|
' Log(0)
|
||||||
|
' If Tracker.FLP.GetLastKnownLocation.IsInitialized Then 'Mandamos ultima ubicacion guardada
|
||||||
|
' Log("dameUltimaUbicacionConocida")
|
||||||
|
' If Tracker.FLP.GetLastKnownLocation.Accuracy < 30 And Tracker.FLP.GetLastKnownLocation.DistanceTo(lastLocation) > 50 Then
|
||||||
|
' Starter.UUC = Tracker.FLP.GetLastKnownLocation
|
||||||
|
' mandaLocAServer(Tracker.FLP.GetLastKnownLocation, Starter.devModel)
|
||||||
|
' Log($"UUC: ${Starter.UUC.Latitude},${Starter.UUC.Longitude}"$)
|
||||||
|
' End If
|
||||||
|
' End If
|
||||||
|
'End Sub
|
||||||
|
|
||||||
|
Sub mandaLocAServer(loc As Location, id As String)
|
||||||
|
Starter.lastLocUpdate = DateTime.Now
|
||||||
|
CallSubDelayed(Main, "actualizaLabelUU")
|
||||||
|
Starter.cmd.Initialize
|
||||||
|
Starter.cmd.Name = "guardaDatos"
|
||||||
|
Starter.cmd.Parameters = Array As Object(fechaKMT(DateTime.Now), id, fechaKMT(DateTime.Now), $"${loc.Latitude},${loc.Longitude},${loc.Accuracy},${loc.AccuracyValid},${loc.Speed},${loc.SpeedValid}"$, "Coords")
|
||||||
|
' If Starter.logger Then
|
||||||
|
Log($"Mandamos loc a server: ${fechaKMT(DateTime.Now)}|${id}|${fechaKMT(DateTime.Now)}|${loc.Latitude},${loc.Longitude}|Coords"$)
|
||||||
|
' End If
|
||||||
|
Starter.reqManager.ExecuteCommand(Starter.cmd,"guardaDatos")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub ConvertMillisecondsToString(t As Long) As String
|
||||||
|
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
|
||||||
160
Tracker.bas
Normal file
160
Tracker.bas
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
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
|
||||||
|
'Para FusedLocationProvider (2 lineas)
|
||||||
|
Public FLP As FusedLocationProvider
|
||||||
|
Private flpStarted As Boolean
|
||||||
|
Dim minAccuracy As Int = 50
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Create
|
||||||
|
Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_NEVER 'we are handling it ourselves
|
||||||
|
'Para FusedLocationProvider (2 lineas)
|
||||||
|
FLP.Initialize("flp")
|
||||||
|
FLP.Connect
|
||||||
|
lock.PartialLock
|
||||||
|
StartFLP
|
||||||
|
If Starter.logger Then Log("FLP initialized")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub flp_ConnectionSuccess
|
||||||
|
If Starter.logger Then Log("Connected to location provider")
|
||||||
|
'FLP.GetLastKnownLocation
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub flp_ConnectionFailed(ConnectionResult1 As Int)
|
||||||
|
if starter.logger then Log("Failed to connect to location provider")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Start (StartingIntent As Intent)
|
||||||
|
'Para FusedLocationProvider (1 linea)
|
||||||
|
Service.StopAutomaticForeground
|
||||||
|
Service.StartForeground(nid, Subs.CreateNotification("..."))
|
||||||
|
Track
|
||||||
|
StartServiceAt(Me, DateTime.Now + 10 * DateTime.TicksPerMinute, True)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Sub Track
|
||||||
|
'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)
|
||||||
|
Do While FLP.IsConnected = False
|
||||||
|
Sleep(500)
|
||||||
|
Log("sleeping")
|
||||||
|
Loop
|
||||||
|
' If flpStarted = False Then
|
||||||
|
Log("RequestLocationUpdates")
|
||||||
|
FLP.RequestLocationUpdates(CreateLocationRequest) 'Buscamos ubicacion
|
||||||
|
Log("Buscamos ubicacion")
|
||||||
|
flpStarted = True
|
||||||
|
' End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private 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 dameUltimaUbicacionConocida(lastLocation As Location)
|
||||||
|
If Starter.logger Then LogColor("dameUltimaUbicacionConocida", Colors.Magenta)
|
||||||
|
If FLP.GetLastKnownLocation.IsInitialized Then 'Mandamos ultima ubicacion guardada
|
||||||
|
If Starter.logger Then Log("This accuracy: " & FLP.GetLastKnownLocation.Accuracy)
|
||||||
|
If Starter.logger Then Log("This distance to previous: " & FLP.GetLastKnownLocation.DistanceTo(lastLocation))
|
||||||
|
Dim coords As String = FLP.GetLastKnownLocation.Latitude&","&FLP.GetLastKnownLocation.Longitude&","&Subs.formatoFecha(FLP.GetLastKnownLocation.Time)
|
||||||
|
If FLP.GetLastKnownLocation.Accuracy < 30 And FLP.GetLastKnownLocation.DistanceTo(lastLocation) > 25 Then
|
||||||
|
Starter.UUC = FLP.GetLastKnownLocation
|
||||||
|
Subs.mandaLocAServer(FLP.GetLastKnownLocation, Starter.devModel)
|
||||||
|
If Starter.logger Then Log("Mandamos GetLastKnownLocation : "&DateTime.Time(FLP.GetLastKnownLocation.Time))
|
||||||
|
CallSubDelayed2(FirebaseMessaging,"mandamosLoc",coords)
|
||||||
|
Log($"UUC: ${Starter.UUC.Latitude},${Starter.UUC.Longitude}"$)
|
||||||
|
End If
|
||||||
|
' Log($"ultima actualizacion: ${Starter.lastLocUpdate}"$)
|
||||||
|
' Log($"${DateTime.now} - ${Starter.lastLocUpdate} = ${(DateTime.Now - Starter.lastLocUpdate)/1000}"$)
|
||||||
|
' Log("||" & Subs.ConvertMillisecondsToString((DateTime.Now - Starter.lastLocUpdate)))
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Sub StopFLP
|
||||||
|
'Log("StopFLP")
|
||||||
|
If flpStarted Then
|
||||||
|
FLP.RemoveLocationUpdates 'Eliminamos todas las solicitudes de ubicacion
|
||||||
|
flpStarted = False
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub flp_LocationChanged (Location1 As Location)
|
||||||
|
If Not(Starter.Timer1.Enabled) Then Starter.Timer1.Enabled = True : Log("timer enabled")
|
||||||
|
If Starter.logger Then LogColor("FLP_LocationChanged", Colors.Red)
|
||||||
|
' ToastMessageShow("FLP_LocationChanged", False)
|
||||||
|
Dim coords As String = Location1.Latitude&","&Location1.Longitude&","&Subs.formatoFecha(DateTime.Now)
|
||||||
|
Main.laUbicacion = Location1
|
||||||
|
' ToastMessageShow(coords, False)
|
||||||
|
' Log("Mandamos Ubicacion")
|
||||||
|
If Starter.logger Then Log(FirebaseMessaging.locRequest)
|
||||||
|
If Starter.logger Then Log(Location1)
|
||||||
|
If Starter.logger Then Log(Location1.Accuracy&" - "&Location1.AccuracyValid)
|
||||||
|
' solo mandamos la ubicacion si la precision es dentro de XX mts
|
||||||
|
If Location1.Accuracy < minAccuracy Then CallSubDelayed2(FirebaseMessaging,"mandamosLoc",coords)
|
||||||
|
If Location1.Accuracy < minAccuracy Then Starter.UUC = Location1
|
||||||
|
If Location1.Accuracy < minAccuracy Then Subs.mandaLocAServer(Location1, Starter.devModel)
|
||||||
|
if starter.logger then Log("Loc changed : "&Location1.Latitude&","&Location1.Longitude&"|"&Starter.devModel&"|")
|
||||||
|
CallSubDelayed(Main, "ponCoords")
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Service_Destroy
|
||||||
|
If Tracking Then
|
||||||
|
StopFLP
|
||||||
|
End If
|
||||||
|
Tracking = False
|
||||||
|
lock.ReleasePartialLock
|
||||||
|
End Sub
|
||||||
126
google-services.json
Normal file
126
google-services.json
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "821860097209",
|
||||||
|
"project_id": "pusher-4c091",
|
||||||
|
"storage_bucket": "pusher-4c091.appspot.com"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"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: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