commit 94d176ea9eee4c60f7f7a8cd4b595df9b493ab7f Author: cheveguerra Date: Wed Sep 27 10:49:20 2023 -0600 Commit inicial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af94e9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/Objects +**/AutoBackups \ No newline at end of file diff --git a/DBRequestManager.bas b/DBRequestManager.bas new file mode 100644 index 0000000..7f9245a --- /dev/null +++ b/DBRequestManager.bas @@ -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 + + \ No newline at end of file diff --git a/DBRequestManagerV2.bas b/DBRequestManagerV2.bas new file mode 100644 index 0000000..93bff84 --- /dev/null +++ b/DBRequestManagerV2.bas @@ -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 + + diff --git a/FLP-ML.b4a b/FLP-ML.b4a new file mode 100644 index 0000000..596a5e1 --- /dev/null +++ b/FLP-ML.b4a @@ -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~~\n~)~\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(~\n~ ~\n~ ~\n~ ~\n~ ~\n~)~\n~~\n~CreateResource(xml, device_admin.xml,~\n~~\n~ ~\n~ ~\n~ ~\n~ ~\n~ ~\n~~\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~~\n~ ~\n~ ) +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 \ No newline at end of file diff --git a/FLP-ML.b4a.meta b/FLP-ML.b4a.meta new file mode 100644 index 0000000..106ee22 --- /dev/null +++ b/FLP-ML.b4a.meta @@ -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 diff --git a/FLP.bas b/FLP.bas new file mode 100644 index 0000000..0c08987 --- /dev/null +++ b/FLP.bas @@ -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 diff --git a/Files/gps_hist.db b/Files/gps_hist.db new file mode 100644 index 0000000..d306d9d Binary files /dev/null and b/Files/gps_hist.db differ diff --git a/Files/layout.bal b/Files/layout.bal new file mode 100644 index 0000000..3b69eae Binary files /dev/null and b/Files/layout.bal differ diff --git a/FirebaseMessaging.bas b/FirebaseMessaging.bas new file mode 100644 index 0000000..36eebce --- /dev/null +++ b/FirebaseMessaging.bas @@ -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 diff --git a/Mods.bas b/Mods.bas new file mode 100644 index 0000000..fad90bc --- /dev/null +++ b/Mods.bas @@ -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) diff --git a/NotificationService.bas b/NotificationService.bas new file mode 100644 index 0000000..6ee09c6 --- /dev/null +++ b/NotificationService.bas @@ -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( +' +' +' ) +' +'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 \ No newline at end of file diff --git a/Starter.bas b/Starter.bas new file mode 100644 index 0000000..679a5da --- /dev/null +++ b/Starter.bas @@ -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 diff --git a/Subs.bas b/Subs.bas new file mode 100644 index 0000000..a14c0d7 --- /dev/null +++ b/Subs.bas @@ -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 \ No newline at end of file diff --git a/Tracker.bas b/Tracker.bas new file mode 100644 index 0000000..b91d58a --- /dev/null +++ b/Tracker.bas @@ -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 diff --git a/google-services.json b/google-services.json new file mode 100644 index 0000000..7edcc98 --- /dev/null +++ b/google-services.json @@ -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" +} \ No newline at end of file