commit 63ae2cda9e52d9496da6e42c41746034aa25122f Author: cheveguerra Date: Mon Sep 18 06:43:57 2023 -0600 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..618d244 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/Objects +**/AutoBackups +*.meta \ No newline at end of file diff --git a/DBRequestManager.bas b/DBRequestManager.bas new file mode 100644 index 0000000..06d44f7 --- /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/DateTimePicker.bas b/DateTimePicker.bas new file mode 100644 index 0000000..2dcbbf9 --- /dev/null +++ b/DateTimePicker.bas @@ -0,0 +1,649 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=7.3 +@EndOfDesignText@ +'Custom View class +'Requiere las librerias XUI y xCustomListView +'version: 1.4 +Sub Class_Globals + Private mEventName As String 'ignore + Private mCallBack As Object 'ignore + Private xui As XUI + Private mBase As B4XView + Private minDate,maxDate As Long + Private clv1,clv2,clv3 As CustomListView + Private Label1,Label2,Label3 As B4XView + Private initValue As Long = DateTime.Now + Private layoutLoaded As Boolean = False + Private ScrollChangedIndex1,ScrollChangedIndex2,ScrollChangedIndex3 As Int + Private xui As XUI 'ignore + Public InactiveDuration As Int = 200 + Public lineColor As Int = xui.Color_Gray + Public backgroundColor As Int = xui.Color_Transparent + Public focusedTextColor As Int = xui.Color_Black + Public notFocusedTextColor As Int = xui.Color_Gray + Public fadeAwayEffect As Boolean = True +End Sub + +Public Sub Initialize (Callback As Object, EventName As String) + mEventName = EventName + mCallBack = Callback +End Sub + +Public Sub DesignerCreateView (Base As Object, lbl As Label, Props As Map) + mBase = Base + mBase.Tag = Me +End Sub + + +Private Sub load + mBase.LoadLayout("datetimelayout") + layoutLoaded = True + Base_Resize(mBase.Width, mBase.Height) + clv1.AsView.Color = backgroundColor + clv2.AsView.Color = backgroundColor + clv3.AsView.Color = backgroundColor + clv1.sv.Color = backgroundColor + clv2.sv.Color = backgroundColor + clv3.sv.Color = backgroundColor + mBase.Color = backgroundColor + If mBase.Height < 150dip Then + Log("DateTimePicker suggested view height is 150dip") + End If +End Sub + +Private Sub Base_Resize (Width As Double, Height As Double) + #if B4J + If layoutLoaded = False Then load + #End If + clv1.AsView.SetLayoutAnimated(0,0,0,Width*0.4,Height) + Dim centerIndex As Int = Floor((Height/30dip)/2) + centerIndex = centerIndex*30dip + 3dip + Label1.SetLayoutAnimated(0,0,centerIndex,clv1.AsView.Width,24dip) + + clv2.AsView.SetLayoutAnimated(0,clv1.AsView.Left+clv1.AsView.Width,0,Width*0.25,Height) + Label2.SetLayoutAnimated(0,clv2.AsView.Left,centerIndex,clv2.AsView.Width,24dip) + + clv3.AsView.SetLayoutAnimated(0,clv2.AsView.Left+clv2.AsView.Width,0,Width*0.35,Height) + Label3.SetLayoutAnimated(0,clv3.AsView.Left,centerIndex,clv3.AsView.Width,24dip) + + #if b4i or b4a + applyLineColor + #End If + + mBase.Color = backgroundColor +End Sub + +Private Sub applyLineColor + Dim cvs As B4XCanvas + cvs.Initialize(Label1) + cvs.ClearRect(cvs.TargetRect) + Dim path As B4XPath + path.Initialize(0,0) + path.LineTo(cvs.TargetRect.Width,0) + #if b4j + path.LineTo(cvs.TargetRect.Width,1dip) + path.LineTo(0,1dip) + #end if + cvs.DrawPath(path,lineColor,False,1dip) + path.Initialize(0,cvs.TargetRect.Height) + path.LineTo(cvs.TargetRect.Width,cvs.TargetRect.Height) + #if b4j + path.LineTo(cvs.TargetRect.Width,cvs.TargetRect.Height-2dip) + path.LineTo(0,cvs.TargetRect.Height-2dip) + #end if + cvs.DrawPath(path,lineColor,False,1dip) + cvs.Invalidate + + Dim cvs As B4XCanvas + cvs.Initialize(Label2) + cvs.ClearRect(cvs.TargetRect) + Dim path As B4XPath + path.Initialize(0,0) + path.LineTo(cvs.TargetRect.Width,0) + #if b4j + path.LineTo(cvs.TargetRect.Width,1dip) + path.LineTo(0,1dip) + #end if + cvs.DrawPath(path,lineColor,False,1dip) + path.Initialize(0,cvs.TargetRect.Height) + path.LineTo(cvs.TargetRect.Width,cvs.TargetRect.Height) + #if b4j + path.LineTo(cvs.TargetRect.Width,cvs.TargetRect.Height-2dip) + path.LineTo(0,cvs.TargetRect.Height-2dip) + #end if + cvs.DrawPath(path,lineColor,False,1dip) + cvs.Invalidate + + + Dim cvs As B4XCanvas + cvs.Initialize(Label3) + cvs.ClearRect(cvs.TargetRect) + Dim path As B4XPath + path.Initialize(0,0) + path.LineTo(cvs.TargetRect.Width,0) + #if b4j + path.LineTo(cvs.TargetRect.Width,1dip) + path.LineTo(0,1dip) + #end if + cvs.DrawPath(path,lineColor,False,1dip) + path.Initialize(0,cvs.TargetRect.Height) + path.LineTo(cvs.TargetRect.Width,cvs.TargetRect.Height) + #if b4j + path.LineTo(cvs.TargetRect.Width,cvs.TargetRect.Height-2dip) + path.LineTo(0,cvs.TargetRect.Height-2dip) + #end if + cvs.DrawPath(path,lineColor,False,1dip) + cvs.Invalidate +End Sub + +'Set the min date +Public Sub SetMinDate(md As Long) + minDate = md +End Sub + +'Set the max date +Public Sub SetMaxDate(md As Long) + maxDate = md +End Sub + +'Add the items to the lists based on the min and max date +Public Sub Show + If layoutLoaded = False Then load + clv1.Clear + clv2.Clear + clv3.Clear + For i = 1 To 5 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv1.AsView.Width, 30dip) + clv1.Add(p, -1) + Next + Dim temMax As Long = maxDate-DateTime.GetHour(maxDate)*DateTime.TicksPerHour-DateTime.GetMinute(maxDate)*DateTime.TicksPerMinute +1 + Dim temMin As Long = minDate-DateTime.GetHour(minDate)*DateTime.TicksPerHour-DateTime.GetMinute(minDate)*DateTime.TicksPerMinute +1 + Dim numOfDays As Int = Floor((temMax-temMin)/DateTime.TicksPerDay) + For i = 0 To numOfDays + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv1.AsView.Width-2dip, 30dip) + Dim tmp As Label + tmp.Initialize("") + Dim lbl As B4XView = tmp + p.AddView(lbl,0,0,clv1.AsView.Width-2dip, 30dip) + DateTime.DateFormat=("MMM dd") + lbl.Text = $"$Date{temMax-DateTime.TicksPerDay*(numOfDays-i)}"$ + lbl.TextColor = notFocusedTextColor + lbl.TextSize = 12 + lbl.SetTextAlignment("CENTER","RIGHT") +' lbl.Gravity = Gravity.CENTER_VERTICAL+Gravity.RIGHT + clv1.Add(p, temMax-DateTime.TicksPerDay*(numOfDays-i)) + Next + DateTime.DateFormat = DateTime.DeviceDefaultDateFormat + For i = 1 To 5 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv1.AsView.Width, 30dip) + clv1.Add(p, -1) + Next + For i = 1 To 5 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv2.AsView.Width, 30dip) + clv2.Add(p, -1) + Next + For i = 0 To 23 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv2.AsView.Width, 30dip) + Dim tmp As Label + tmp.Initialize("") + Dim lbl As B4XView = tmp + p.AddView(lbl,0,0,clv2.AsView.Width,30dip) + lbl.Text = $"$2.0{i}"$ + lbl.TextColor = notFocusedTextColor + lbl.TextSize = 12 + lbl.SetTextAlignment("CENTER","CENTER") + clv2.Add(p, i) + Next + For i = 1 To 5 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv2.AsView.Width, 30dip) + clv2.Add(p, -1) + Next + + For i = 1 To 5 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv3.AsView.Width, 30dip) + clv3.Add(p, -1) + Next + For i = 0 To 59 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv3.AsView.Width, 30dip) + Dim tmp As Label + tmp.Initialize("") + Dim lbl As B4XView = tmp + p.AddView(lbl,0,0,clv3.AsView.Width,30dip) + lbl.Text = $"$2.0{i}"$ + lbl.TextColor = notFocusedTextColor + lbl.TextSize = 12 + lbl.SetTextAlignment("CENTER","LEFT") + clv3.Add(p, i) + Next + For i = 1 To 5 + Dim p As B4XView = xui.CreatePanel("") + p.Color = backgroundColor + p.SetLayoutAnimated(0, 0, 0, clv3.AsView.Width, 30dip) + clv3.Add(p, -1) + Next + + MoveToInitValues + + applyLineColor +End Sub + +'Value that will be selected by default +Public Sub SetSelectedValue(init As Long) + initValue = init +End Sub +Private Sub MoveToInitValues + Sleep(0) + For i=0 To clv1.Size-1 + If i+halfIndex1 > clv1.Size-1 Then + ScrollChanged1(0) + Exit + End If + If clv1.GetValue(i+halfIndex1) > -1 Then + If Abs(clv1.GetValue(i+halfIndex1) - initValue) < DateTime.TicksPerDay Then + If i = clv1.FirstVisibleIndex Then + clv1_ScrollChanged(clv1.sv.ScrollViewOffsetY) + End If + clv1.ScrollToItem(i) + Exit + End If + End If + Next + For i=0 To clv2.Size-1 + If i+halfIndex2 > clv2.Size-1 Then + ScrollChanged2(0) + Exit + End If + If clv2.GetValue(i+halfIndex2) > -1 Then + If DateTime.GetHour(initValue) = clv2.GetValue(i+halfIndex2) Then + If i = clv2.FirstVisibleIndex Then + clv2_ScrollChanged(clv2.sv.ScrollViewOffsetY) + End If + clv2.ScrollToItem(i) + Exit + End If + End If + Next + For i=0 To clv3.Size-1 + If i+halfIndex3 > clv3.Size-1 Then + ScrollChanged3(0) + Exit + End If + If clv3.GetValue(i+halfIndex3) > -1 Then + If DateTime.GetMinute(initValue) = clv3.GetValue(i+halfIndex3) Then + If i = clv3.FirstVisibleIndex Then + clv3_ScrollChanged(clv3.sv.ScrollViewOffsetY) + End If + clv3.ScrollToItem(i) + Exit + End If + End If + Next +End Sub + +'Returns selected value +Public Sub getSelected As Long + If layoutLoaded = False Then Return -1 +' If snapEnded1 And snapEnded2 And snapEnded3 Then + Dim date As Long = clv1.GetValue(clv1.FirstVisibleIndex+halfIndex1) + If date < 0 Then + If clv1.FirstVisibleIndex+halfIndex2 > 5 Then + date = clv1.GetValue(clv1.Size-6) + Else + date = clv1.GetValue(5) + End If + End If + Dim hour As Int = clv2.GetValue(clv2.FirstVisibleIndex+halfIndex2) + If hour < 0 Then + If clv2.FirstVisibleIndex+halfIndex2 > 5 Then + hour = clv2.GetValue(clv2.Size-6) + Else + hour = clv2.GetValue(5) + End If + End If + Dim minute As Int = clv3.GetValue(clv3.FirstVisibleIndex+halfIndex3) + If minute < 0 Then + If clv3.FirstVisibleIndex+halfIndex2 > 5 Then + minute = clv3.GetValue(clv3.Size-6) + Else + minute = clv3.GetValue(5) + End If + End If + DateTime.DateFormat = "MM/dd/yyyy HH:mm" + Dim parsed As Long = DateTime.DateParse($"${DateTime.GetMonth(date)}/${DateTime.GetDayOfMonth(date)}/${DateTime.GetYear(date)} ${hour}:${minute}"$) + DateTime.DateFormat = DateTime.DeviceDefaultDateFormat + Return parsed +' Else +' Return -1 +' End If +End Sub + +'Returns a list of the selected values, each as a string +Public Sub getSelectedRawValues As List + Dim response As List + response.Initialize + If layoutLoaded = False Then Return response + + Dim valueClv1 As String = clv1.GetPanel(clv1.FirstVisibleIndex+halfIndex1).GetView(0).Text + Dim valueClv2 As String = clv2.GetPanel(clv2.FirstVisibleIndex+halfIndex2).GetView(0).Text + Dim valueClv3 As String = clv3.GetPanel(clv3.FirstVisibleIndex+halfIndex3).GetView(0).Text + + response.Add(valueClv1) + response.Add(valueClv2) + response.Add(valueClv3) + + Return response +End Sub + +Private Sub clv1_ScrollChanged (Offset As Int) + 'Snap into place + ScrollChanged1(Offset) + 'Change text color and size + Dim i As Int = clv1.FirstVisibleIndex + Dim item As CLVItem = clv1.GetRawListItem(i) + Dim centerIndex As Int = Floor((clv1.sv.Height/item.Size)/2) + Dim visiblepart As Int = item.Offset + item.Size - Offset + If visiblepart / item.Size < 0.5 Then + i = i+1 + End If + + Dim m As Float = (255-80)/(item.Size*1.5-0) + Dim clr() As Int = GetARGB(notFocusedTextColor) + For x=Max(0,i-1) To Min(i+(clv1.sv.Height/item.Size),clv1.Size-1) + If clv1.GetValue(x)>-1 Then + If x=i+centerIndex Then + Dim lbl As B4XView = clv1.GetPanel(x).GetView(0) + lbl.TextColor = focusedTextColor + lbl.TextSize = 18 + Else + Dim lbl As B4XView = clv1.GetPanel(x).GetView(0) + If fadeAwayEffect Then + Dim item2 As CLVItem = clv1.GetRawListItem(x) + Dim visiblepart2 As Int = item2.Offset - Offset + Dim visibleItems As Int = Floor(clv1.sv.Height/item.Size) + + If x > i+centerIndex Then + visiblepart2 = visibleItems*item2.Size - visiblepart2 - item2.Size + End If + visiblepart2 = Min(Max(visiblepart2,0),visibleItems*item2.Size+1) + + + Dim alpha As Int = m*visiblepart2 + 80 + + lbl.TextColor = xui.Color_ARGB(alpha,clr(0),clr(1),clr(2)) + Else + lbl.TextColor = notFocusedTextColor + End If + lbl.TextSize = 12 + End If + End If + Next +End Sub + +private Sub clv2_ScrollChanged (Offset As Int) + ScrollChanged2(Offset) + Dim i As Int = clv2.FirstVisibleIndex + Dim item As CLVItem = clv2.GetRawListItem(i) + Dim centerIndex As Int = Floor((clv2.sv.Height/item.Size)/2) + Dim visiblepart As Int = item.Offset + item.Size - Offset + If visiblepart / item.Size < 0.5 Then + i = i+1 + End If + + Dim m As Float = (255-80)/(item.Size*1.5-0) + Dim clr() As Int = GetARGB(notFocusedTextColor) + For x=Max(0,i-1) To Min(i+(clv2.sv.Height/item.Size),clv2.Size-1) + If clv2.GetValue(x)>-1 Then + If x=i+centerIndex Then + Dim lbl As B4XView = clv2.GetPanel(x).GetView(0) + lbl.TextColor = focusedTextColor + lbl.TextSize = 18 + Else + Dim lbl As B4XView = clv2.GetPanel(x).GetView(0) + If fadeAwayEffect Then + Dim item2 As CLVItem = clv2.GetRawListItem(x) + Dim visiblepart2 As Int = item2.Offset - Offset + Dim visibleItems As Int = Floor(clv2.sv.Height/item.Size) + + If x > i+centerIndex Then + visiblepart2 = visibleItems*item2.Size - visiblepart2 - item2.Size + End If + visiblepart2 = Min(Max(visiblepart2,0),visibleItems*item2.Size+1) + + Dim alpha As Int = m*visiblepart2 + 80 + + lbl.TextColor = xui.Color_ARGB(alpha,clr(0),clr(1),clr(2)) + Else + lbl.TextColor = notFocusedTextColor + End If + lbl.TextSize = 12 + End If + End If + Next +End Sub + +Private Sub clv3_ScrollChanged (Offset As Int) + ScrollChanged3(Offset) + Dim i As Int = clv3.FirstVisibleIndex + Dim item As CLVItem = clv3.GetRawListItem(i) + Dim centerIndex As Int = Floor((clv3.sv.Height/item.Size)/2) + Dim visiblepart As Int = item.Offset + item.Size - Offset + If visiblepart / item.Size < 0.5 Then + i = i+1 + End If + + Dim m As Float = (255-80)/(item.Size*1.5-0) + Dim clr() As Int = GetARGB(notFocusedTextColor) + For x=Max(0,i-1) To Min(i+(clv3.sv.Height/item.Size),clv3.Size-1) + If clv3.GetValue(x)>-1 Then + If x=i+centerIndex Then + Dim lbl As B4XView = clv3.GetPanel(x).GetView(0) + lbl.TextColor = focusedTextColor + lbl.TextSize = 18 + Else + Dim lbl As B4XView = clv3.GetPanel(x).GetView(0) + If fadeAwayEffect Then + Dim item2 As CLVItem = clv3.GetRawListItem(x) + Dim visiblepart2 As Int = item2.Offset - Offset + Dim visibleItems As Int = Floor(clv3.sv.Height/item.Size) + + If x > i+centerIndex Then + visiblepart2 = visibleItems*item2.Size - visiblepart2 - item2.Size + End If + visiblepart2 = Min(Max(visiblepart2,0),visibleItems*item2.Size+1) + + Dim alpha As Int = m*visiblepart2 + 80 + + lbl.TextColor = xui.Color_ARGB(alpha,clr(0),clr(1),clr(2)) + Else + lbl.TextColor = notFocusedTextColor + End If + lbl.TextSize = 12 + End If + End If + Next +End Sub + +#Region Code modified from CLVSnap + +Private Sub ScrollChanged1 (Offset As Int) + ScrollChangedIndex1 = ScrollChangedIndex1 + 1 + Dim MyIndex As Int = ScrollChangedIndex1 + Sleep(InactiveDuration) + If ScrollChangedIndex1 = MyIndex Then + SnapCLV1(Offset) + End If +End Sub +Private Sub halfIndex1 As Int + Dim i As Int = clv1.FirstVisibleIndex + Dim item As CLVItem = clv1.GetRawListItem(i) + Return Floor((clv1.sv.Height/item.Size)/2) +End Sub +Private Sub SnapCLV1 (Offset As Int) + Dim i As Int = clv1.FirstVisibleIndex + Dim item As CLVItem = clv1.GetRawListItem(i) + Dim centerIndex As Int = Floor((clv1.sv.Height/item.Size)/2) + Dim visiblepart As Int = item.Offset + item.Size - Offset + If visiblepart / item.Size < 0.5 Then + i = i+1 + End If + Dim diff As Int = 0 + Dim found As Boolean = False + If i+centerIndex < clv1.Size-1 Then + If -1 = clv1.Getvalue(i+centerIndex) Then + For x=(i+centerIndex) To clv1.Size-1 + If clv1.GetValue(x)>-1 Then + found = True + diff = x-(i+centerIndex) + Exit + End If + Next + If found = False Then + Dim ici As Int = i+centerIndex + Do While True + If clv1.GetValue(ici)>-1 Then + found = True + diff = ici-(i+centerIndex) + Exit + End If + ici = ici-1 + Loop + End If + End If + End If + + clv1.ScrollToItem(i+diff) + +End Sub + +Private Sub ScrollChanged2 (Offset As Int) + ScrollChangedIndex2 = ScrollChangedIndex2 + 1 + Dim MyIndex As Int = ScrollChangedIndex2 + Sleep(InactiveDuration) + If ScrollChangedIndex2 = MyIndex Then + SnapCLV2(Offset) + End If +End Sub +Private Sub halfIndex2 As Int + Dim i As Int = clv2.FirstVisibleIndex + Dim item As CLVItem = clv2.GetRawListItem(i) + Return Floor((clv2.sv.Height/item.Size)/2) +End Sub +Private Sub SnapCLV2 (Offset As Int) + Dim i As Int = clv2.FirstVisibleIndex + Dim item As CLVItem = clv2.GetRawListItem(i) + Dim centerIndex As Int = Floor((clv2.sv.Height/item.Size)/2) + Dim visiblepart As Int = item.Offset + item.Size - Offset + If visiblepart / item.Size < 0.5 Then + i = i+1 + End If + Dim diff As Int = 0 + Dim found As Boolean = False + If i+centerIndex < clv2.Size-1 Then + If -1 = clv2.Getvalue(i+centerIndex) Then + For x=(i+centerIndex) To clv2.Size-1 + If clv2.GetValue(x)>-1 Then + found = True + diff = x-(i+centerIndex) + Exit + End If + Next + If found = False Then + Dim ici As Int = i+centerIndex + Do While True + If clv2.GetValue(ici)>-1 Then + found = True + diff = ici-(i+centerIndex) + Exit + End If + ici = ici-1 + Loop + End If + End If + End If + + clv2.ScrollToItem(i+diff) + +End Sub + +Private Sub ScrollChanged3 (Offset As Int) + ScrollChangedIndex3 = ScrollChangedIndex3 + 1 + Dim MyIndex As Int = ScrollChangedIndex3 + Sleep(InactiveDuration) + If ScrollChangedIndex3 = MyIndex Then + SnapCLV3(Offset) + End If +End Sub +Private Sub halfIndex3 As Int + Dim i As Int = clv3.FirstVisibleIndex + Dim item As CLVItem = clv3.GetRawListItem(i) + Return Floor((clv3.sv.Height/item.Size)/2) +End Sub +Private Sub SnapCLV3 (Offset As Int) + Dim i As Int = clv3.FirstVisibleIndex + Dim item As CLVItem = clv3.GetRawListItem(i) + Dim centerIndex As Int = Floor((clv3.sv.Height/item.Size)/2) + Dim visiblepart As Int = item.Offset + item.Size - Offset + If visiblepart / item.Size < 0.5 Then + i = i+1 + End If + Dim diff As Int = 0 + Dim found As Boolean = False + If i+centerIndex < clv3.Size-1 Then + If -1 = clv3.Getvalue(i+centerIndex) Then + For x=(i+centerIndex) To clv3.Size-1 + If clv3.GetValue(x)>-1 Then + found = True + diff = x-(i+centerIndex) + Exit + End If + Next + If found = False Then + Dim ici As Int = i+centerIndex + Do While True + If clv3.GetValue(ici)>-1 Then + found = True + diff = ici-(i+centerIndex) + Exit + End If + ici = ici-1 + Loop + End If + End If + End If + + clv3.ScrollToItem(i+diff) + +End Sub +#End Region + +Private Sub GetARGB(Color As Int) As Int() + Dim res(4) As Int + res(3) = Bit.UnsignedShiftRight(Bit.And(Color, 0xff000000), 24) + res(2) = Bit.UnsignedShiftRight(Bit.And(Color, 0xff0000), 16) + res(1) = Bit.UnsignedShiftRight(Bit.And(Color, 0xff00), 8) + res(0) = Bit.And(Color, 0xff) + Return res +End Sub + + + + diff --git a/Files/96761371-car-icon-white-icon-with-shadow-on-transparent-background.jpg b/Files/96761371-car-icon-white-icon-with-shadow-on-transparent-background.jpg new file mode 100644 index 0000000..1b2e533 Binary files /dev/null and b/Files/96761371-car-icon-white-icon-with-shadow-on-transparent-background.jpg differ diff --git a/Files/ballon280.png b/Files/ballon280.png new file mode 100644 index 0000000..ae3c252 Binary files /dev/null and b/Files/ballon280.png differ diff --git a/Files/ballon50.png b/Files/ballon50.png new file mode 100644 index 0000000..801701b Binary files /dev/null and b/Files/ballon50.png differ diff --git a/Files/balloon_overlay_close.png b/Files/balloon_overlay_close.png new file mode 100644 index 0000000..7a533cf Binary files /dev/null and b/Files/balloon_overlay_close.png differ diff --git a/Files/datetimelayout.bal b/Files/datetimelayout.bal new file mode 100644 index 0000000..cb7b5eb Binary files /dev/null and b/Files/datetimelayout.bal differ diff --git a/Files/icon-transit-small.png b/Files/icon-transit-small.png new file mode 100644 index 0000000..84afb1a Binary files /dev/null and b/Files/icon-transit-small.png differ diff --git a/Files/icon-transit.png b/Files/icon-transit.png new file mode 100644 index 0000000..ad1291c Binary files /dev/null and b/Files/icon-transit.png differ diff --git a/Files/infowindow.bal b/Files/infowindow.bal new file mode 100644 index 0000000..af0f94f Binary files /dev/null and b/Files/infowindow.bal differ diff --git a/Files/layout.bal b/Files/layout.bal new file mode 100644 index 0000000..583078f Binary files /dev/null and b/Files/layout.bal differ diff --git a/Files/marker-rojo-0.png b/Files/marker-rojo-0.png new file mode 100644 index 0000000..c2f508a Binary files /dev/null and b/Files/marker-rojo-0.png differ diff --git a/Files/marker-rojo-coche.png b/Files/marker-rojo-coche.png new file mode 100644 index 0000000..e9f9a38 Binary files /dev/null and b/Files/marker-rojo-coche.png differ diff --git a/Files/waze-moving-2.png b/Files/waze-moving-2.png new file mode 100644 index 0000000..8ab01c8 Binary files /dev/null and b/Files/waze-moving-2.png differ diff --git a/Files/waze-moving-small.png b/Files/waze-moving-small.png new file mode 100644 index 0000000..c63bdc2 Binary files /dev/null and b/Files/waze-moving-small.png differ diff --git a/Files/waze-moving.png b/Files/waze-moving.png new file mode 100644 index 0000000..73a1886 Binary files /dev/null and b/Files/waze-moving.png differ diff --git a/Files/waze-sleeping-small.png b/Files/waze-sleeping-small.png new file mode 100644 index 0000000..6ceefbf Binary files /dev/null and b/Files/waze-sleeping-small.png differ diff --git a/Files/waze-sleeping.png b/Files/waze-sleeping.png new file mode 100644 index 0000000..4b8594e Binary files /dev/null and b/Files/waze-sleeping.png differ diff --git a/Files/waze.png b/Files/waze.png new file mode 100644 index 0000000..c6d3996 Binary files /dev/null and b/Files/waze.png differ diff --git a/Files/zzz.png b/Files/zzz.png new file mode 100644 index 0000000..a5ecf17 Binary files /dev/null and b/Files/zzz.png differ diff --git a/FirebaseMessaging.bas b/FirebaseMessaging.bas new file mode 100644 index 0000000..931b3b5 --- /dev/null +++ b/FirebaseMessaging.bas @@ -0,0 +1,84 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Service +Version=10.5 +@EndOfDesignText@ +Sub Process_Globals + Private fm As FirebaseMessaging +End Sub + +Sub Service_Create + fm.Initialize("fm") +End Sub + +Public Sub SubscribeToTopics + fm.SubscribeToTopic("Trckr") 'Global (you can subscribe to more topics) + fm.SubscribeToTopic("Sprvsr") + fm.SubscribeToTopic("Sprv-ML") + fm.SubscribeToTopic("Sprv-This") + fm.SubscribeToTopic("Sprv-Cedex") + fm.SubscribeToTopic("Sprv-GunaReparto") + fm.SubscribeToTopic("Sprv-Durakelo") +' Log(fm.token) +End Sub + +Sub Service_Start (StartingIntent As Intent) + If StartingIntent.IsInitialized Then fm.HandleIntent(StartingIntent) + 'Sleep(0) + 'Service.StopAutomaticForeground 'remove if not using B4A v8+. +End Sub + +Sub fm_MessageArrived (Message As RemoteMessage) + Log("Mensaje recibido") + Log($"Message data: ${Message.GetData}"$) + + 'Si recibimos Pong, lo agregamos a la lista de dispositivos activos + If Message.GetData.ContainsKey("t") And Message.GetData.Get("t") = "pong" Then + Log("Recibimos pong "&Message.GetData.Get("d")) + If Main.dispositivos.ContainsKey(Message.GetData.Get("d")) Then + Dim dMap As Map = Main.dispositivos.Get(Message.GetData.Get("d")) + Dim dispData As Map = dMap + Else + Dim dispData As Map = CreateMap("coords": "0,0", "d": Message.GetData.Get("d"),"v": Message.GetData.Get("v"), "w": Message.GetData.Get("w")) + End If + Log("** "&dispData) + Main.dispositivos.Put(Message.GetData.Get("d"), dispData) + End If + + 'Si el mensaje es de ubicacion recibida + If Message.GetData.ContainsKey("t") And (Message.GetData.Get("t") = "u" Or Message.GetData.Get("t") = "au") Then + Log("Recibimos ubicacion") + Log("Llamamos UbicacionRecibida") + If Message.GetData.Get("t") = "au" Then ToastMessageShow("Ubicacion recibida:"&Message.GetData.Get("d"),False) + CallSub2(Main, "ubicacionRecibida", Message.GetData) + End If + + 'Si el mensaje es de ruta gps recibida + If Message.GetData.ContainsKey("t") And Message.GetData.Get("t") = "ruta" Then + Log("Recibimos Ruta GPS") + If Message.GetData.ContainsKey("r") Then + Log("Tenemos Ruta") + Main.base64=Message.GetData.Get("r") + descomprimeRuta +' ToastMessageShow("Ruta Recibida: "&Message.GetData.Get("d"),False) + Main.rRuta = Message.GetData.Get("d") + CallSub(Main, "muestraRuta") + End If + End If + CallSub(Main,"agregaAListview") +End Sub + +Sub Service_Destroy + +End Sub + +Sub descomprimeRuta + Dim su As StringUtils + Dim decompressedbytes() As Byte = su.DecodeBase64(Main.base64) + Log($"decompressedbytesLength: ${decompressedbytes.Length}"$) + Dim bc As ByteConverter + Main.rutaGPS = bc.StringFromBytes(decompressedbytes,"UTF8") + Log($"uncompressedLength: ${Main.rutaGPS.Length}"$) +' Log($"Decompressed String = ${Main.rutaGPS}"$) +End Sub \ No newline at end of file diff --git a/Mods.bas b/Mods.bas new file mode 100644 index 0000000..2803c8f --- /dev/null +++ b/Mods.bas @@ -0,0 +1,16 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=StaticCode +Version=11.2 +@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. +End Sub + +'Ver 2.01.14 +'Se agregó codigo en "Main.b_buscar_Click" para que el teclado se oculte al hacer clic en "b_buscar". +'Se acomodaron algunos botones para que se vean mejor. diff --git a/MyPopup.bas b/MyPopup.bas new file mode 100644 index 0000000..5f63655 --- /dev/null +++ b/MyPopup.bas @@ -0,0 +1,341 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=11 +@EndOfDesignText@ +' Popup menu class by Kevin Stainsby 2019. +' Works in b4a and b4i +' Needs JavaObject library for Android +' v1.1 + +Sub Class_Globals + Private Callback As Object + Private Event As String + Private btnList As List + Private anchorView As View + Private maxWidth, maxHeight As Int = 0 + Dim borderWidth As Int = 1 + Dim btnPadding As Int = 5dip + Dim btnSpacing As Int = 3dip + Dim btnBorderColour As Int = Colors.white + Private pnl As Panel + Private sv As ScrollView + Private maxX, maxY As Int + Private const ANCHOR_BOTTOMMIDDLE As Int = 1 + Private const ANCHOR_TOPLEFT As Int = 2 + Private showingMenu As Boolean + Dim btnTextColour As Int = Colors.black + Private btnHeight As Int = 45dip + Private btnRadius As Int = 5dip +#if b4i + Private myPanel As Panel + Dim btnColour As Int = Colors.white + Private const animTime As Int = 1000 + Private useThisFont As Font +#else if b4a + Dim myActivity As Activity + Dim btnBackgroundColour As Int = Colors.LightGray + Dim btnFontSize As Float = 18.0 + Private const animTime As Int = 300 + Dim useThisTypeFace As Typeface +#End If +End Sub + +'Initializes the popup. Pass a list of strings for the buttons text. +#if b4i +Public Sub Initialize( rootPnl As Panel, CallbackModule As Object, EventName As String, btnText As List, mX As Int, mY As Int, theFont As Font ) + useThisFont = theFont +#else if b4A +Public Sub Initialize( anActivity As Activity, CallbackModule As Object, EventName As String, btnText As List, mX As Int, my As Int, theTypeface As Typeface ) + useThisTypeFace = theTypeface +#End If + + maxX = mX + maxY = my + Callback = CallbackModule + Event = EventName + +#if b4i + myPanel = rootPnl +#else if b4A + myActivity = anActivity +#End If + + btnList.Initialize + pnl.Initialize("Pnl") + pnl.Color = Colors.Transparent + +#if b4i + sv.Initialize("sv", 1, 1) +#else if b4A + sv.Initialize(1) +#End If + + sv.Color = Colors.Transparent + + For Each s As String In btnText + Dim aBtn As Button +#if b4i + aBtn.Initialize("Btn",aBtn.STYLE_SYSTEM) + aBtn.CustomLabel.Font = useThisFont + aBtn.Text = s + aBtn.SetBorder( borderWidth, btnBorderColour, btnRadius ) + aBtn.SetShadow(Colors.black,3dip,3dip,0.7,False) + aBtn.SizeToFit + aBtn.Color = btnColour + SetButtonTextColor(aBtn, btnTextColour ) +#else if b4A + aBtn.Initialize("Btn") + setBorder(aBtn, borderWidth, btnRadius, btnBorderColour, btnBackgroundColour) + aBtn.TextSize = btnFontSize + aBtn.SingleLine = True + aBtn.Ellipsize = "END" + aBtn.Gravity = Gravity.CENTER_VERTICAL + aBtn.Padding = Array As Int (btnPadding, btnPadding, btnPadding, btnPadding) + aBtn.Typeface = theTypeface + SetButtonTextColor(aBtn, btnTextColour ) + aBtn.Text = s + sv.Panel.AddView( aBtn, 0,0,1,btnHeight) + setButtonWidth( aBtn ) +#End If + If aBtn.Width + (btnPadding*2) > maxWidth Then maxWidth = aBtn.Width + (btnPadding *2) + If aBtn.Height + (btnPadding*2) > maxHeight Then maxHeight = aBtn.Height + (btnPadding *2) + btnList.Add(aBtn) + Next + +#if b4i + For Each b As Button In btnList + sv.Panel.AddView( b, 0,0,1,btnHeight) + b.SizeToFit + Next +#End If + 'Resize to same width (max).. + For Each b As Button In btnList + If b.Width < maxWidth Then b.Width = maxWidth + If b.Height < maxHeight Then b.Height = maxHeight + Next + + Dim currY As Int = 0 + For Each b As Button In btnList + b.Left = btnSpacing + b.Width = maxWidth + + currY = currY + btnSpacing + b.Top = currY + b.Height = maxHeight + currY = currY + maxHeight + Next + currY = currY + btnSpacing + +#if b4i + sv.ContentHeight = currY + sv.ContentWidth = maxWidth + 2*btnSpacing +#else if b4a + sv.panel.Height = currY + sv.panel.Width = maxWidth + 2*btnSpacing +#End If + +End Sub + +'Call in page resize event, to reset the screen coordinates +public Sub Resize(screenX As Int, screenY As Int) + maxX = screenX + maxY = screenY + pnl.Width = maxX + pnl.Height = maxY +End Sub + +'Shows the popup menu, anchored to the parent view +'If already displaying, calling it show again will hide the menu. +public Sub Show(parent As View ) + showPopup(parent, ANCHOR_BOTTOMMIDDLE) +End Sub + +'Same as show, but popup anchored to top left corner of view instead. +'If already displaying, calling it show again will hide the menu. +Public Sub Show2(parent As View) + showPopup(parent, ANCHOR_TOPLEFT) +End Sub + +private Sub showPopup(parent As View, anchorPoint As Int) + If showingMenu Then + Hide + Return + End If + + anchorView = parent + Dim anchorViewTop, anchorViewLeft, anchorViewHeight, anchorViewWidth As Int + + anchorViewHeight = anchorView.Height 'Take a copy b4 abs coord call (problem in b4i) + anchorViewWidth = anchorView.Width + Dim leftTop() As Float = GetPageLeftAndTop( anchorView ) +#if b4i + Dim leftTop2() As Float = GetPageLeftAndTop( myPanel ) +#else + Dim leftTop2() As Float = GetPageLeftAndTop( myActivity ) +#End If + anchorViewLeft = leftTop(0) - leftTop2(0) + anchorViewTop = leftTop(1) - leftTop2(1) + + Dim left, top As Int + Select anchorPoint + Case ANCHOR_BOTTOMMIDDLE + left = anchorViewLeft + (anchorViewWidth / 2) + If left + maxWidth + 2*btnSpacing > maxX Then left = maxX - maxWidth - 2*btnSpacing + + If anchorViewTop > 0.5*maxY Then +#if b4i + top = anchorViewTop - sv.ContentHeight +#else if b4a + top = anchorViewTop - sv.panel.Height +#End If + If top < 0 Then top = 0 + Else + top = anchorViewTop + anchorViewHeight + If top + maxHeight > maxY Then top = Max(maxY - maxHeight, 0) + End If + Case ANCHOR_TOPLEFT + left = anchorViewLeft + If left + maxWidth > maxX Then left = maxX - maxWidth + + If anchorViewTop > 0.5*maxY Then +#if b4i + top = anchorViewTop - sv.ContentHeight +#else if b4a + top = anchorViewTop - sv.panel.Height +#End If + If top < 0 Then top = 0 + Else + top = anchorViewTop + anchorViewHeight + If top + maxHeight > maxY Then top = Max(maxY - maxHeight, 0) + End If + End Select +#if b4i + myPanel.AddView(pnl, 0, 0, maxX, maxY) +#else if b4A + pnl.RemoveView + myActivity.AddView(pnl, 0, 0, maxX, maxY) + pnl.Elevation = 99.0 'ignore +#End If + + pnl.BringToFront + pnl.Color = Colors.ARGB(80,255,255,255) + + 'Start of animation point in top left of anchorview.. + pnl.AddView(sv, anchorViewLeft, anchorViewTop, 1, 1) + pnl.Visible = True + sv.Visible = True + sv.Color = Colors.ARGB(10,255,255,255) + +#if b4i + If top + sv.ContentHeight <= maxY Then + sv.SetLayoutAnimated(animTime, 0.5, left, top, sv.ContentWidth, sv.ContentHeight ) + Else + sv.SetLayoutAnimated(animTime, 0.5, left, top, sv.ContentWidth, maxY - top ) + End If +#else if b4a + If top + sv.panel.Height <= maxY Then + sv.SetLayoutAnimated(animTime, left, top, sv.panel.Width, sv.panel.Height ) + Else + sv.SetLayoutAnimated(animTime, left, top, sv.panel.Width, maxY - top ) + End If + sv.BringToFront +#End If + showingMenu = True +End Sub + +' Hides the popup menu +public Sub Hide + pnl.SendToBack + pnl.RemoveAllViews +#if b4A + pnl.RemoveView +#End If + showingMenu = False +End Sub + +Private Sub Btn_Click + Dim b As Button = Sender + Dim txt As String = b.Text +#if b4i + If SubExists(Callback, Event & "_BtnClick", 1) Then + CallSub2(Callback, Event & "_BtnClick", txt ) + End If +#else if b4a + If SubExists(Callback, Event & "_BtnClick") Then + CallSub2(Callback, Event & "_BtnClick", txt ) + End If +#End If + Hide +End Sub + +private Sub Pnl_Click + Hide +End Sub + +private Sub SetButtonTextColor(btn As Button, clr As Int) +#if b4i + Dim no As NativeObject = btn + no.RunMethod("setTitleColor:forState:", Array(no.ColorToUIColor(clr), 1)) +#else if b4a + btn.TextColor = clr +#End If +End Sub + +#if b4i +#else if b4A +'Sets the button to be wide enough to fit its text. +private Sub setButtonWidth(btn As Button) + Dim w As Int + Dim wMargin As Int = Max( btn.Width * 0.1, 10 ) 'say + Dim bmpTest As Bitmap + bmpTest.InitializeMutable(1, 1) 'ignore + Dim cvsTest As Canvas + cvsTest.Initialize2(bmpTest) + w = cvsTest.MeasureStringWidth(btn.Text, useThisTypeFace, btn.TextSize) + btn.Width = w + 2* wMargin +End Sub +#End If + +Sub GetPageLeftAndTop(v As View) As Float() +#if b4i + Dim tl(2) As Float + Do While GetType(v) <> "B4IMainView" + '' Log("View type = " & GetType(v)) + '' Dim no As NativeObject = v + tl(0) = tl(0) + v.Left + If v Is ScrollView Then + Dim s As ScrollView = v + tl(1) = tl(1) + v.Top - s.ScrollOffsetY + Else + tl(1) = tl(1) + v.Top + End If + '' v = no.GetField("superview") + ''v = v.Parent + If v.Parent.IsInitialized Then + v = v.Parent + Else + Exit + End If + Loop + Return tl +#else if b4A + Dim leftTop(2) As Int + Dim JO As JavaObject = v + JO.RunMethod("getLocationOnScreen", Array As Object(leftTop)) + Dim ret(2) As Float + ret(0) = leftTop(0) + ret(1) = leftTop(1) + Return ret +#End If +End Sub + +#if b4A +Sub setBorder(v As View, width As Int, cornerRadius As Int, borderColor As Int, backgroundColor As Int) + Dim c As ColorDrawable + c.Initialize2(backgroundColor,cornerRadius,width,borderColor) + v.Background = c +End Sub +#End If + diff --git a/Starter.bas b/Starter.bas new file mode 100644 index 0000000..8517406 --- /dev/null +++ b/Starter.bas @@ -0,0 +1,31 @@ +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 + Public rp As RuntimePermissions + Public FLP As FusedLocationProvider +End Sub + +Sub Service_Create + CallSubDelayed(FirebaseMessaging, "SubscribeToTopics") +End Sub + +Sub Service_Start (StartingIntent As Intent) + +End Sub + +Sub Application_Error (Error As Exception, StackTrace As String) As Boolean + Return True +End Sub + +Sub Service_Destroy + +End Sub diff --git a/Tracker.bas b/Tracker.bas new file mode 100644 index 0000000..2e3301c --- /dev/null +++ b/Tracker.bas @@ -0,0 +1,168 @@ +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") +' AddPermission(android.permission.ACCESS_FINE_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, 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 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(50) '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(5) '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&","&Location1.Time + +' Dim mm As Map = CreateMap("Body": coords, "d": Main.devModel) +' CallSub2(Main,"ubicacionRecibida",mm) + + '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) +End Sub + + +Sub Service_Destroy + If Tracking Then + StopFLP + End If + Tracking = False + lock.ReleasePartialLock +End Sub diff --git a/TrackerXXX.bas b/TrackerXXX.bas new file mode 100644 index 0000000..1a17ac3 --- /dev/null +++ b/TrackerXXX.bas @@ -0,0 +1,168 @@ +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") +' AddPermission(android.permission.ACCESS_FINE_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, 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 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(50) '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(5) '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&","&Location1.Time + +' Dim mm As Map = CreateMap("Body": coords, "d": Main.devModel) +' CallSub2(Main,"ubicacionRecibida",mm) + + '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) +End Sub + + +Sub Service_Destroy + If Tracking Then + StopFLP + End If + Tracking = False + lock.ReleasePartialLock +End Sub diff --git a/TrsLogClass.bas b/TrsLogClass.bas new file mode 100644 index 0000000..20a2580 --- /dev/null +++ b/TrsLogClass.bas @@ -0,0 +1,121 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=6.5 +@EndOfDesignText@ +' TrsLogClass Class module +' Version 1.0 20FEB17 +'--------------------------------------------------------------------------------- +Sub Class_Globals + Private faultLogEntry As Int = 0 + Private warningLogEntry As Int = 1 + Public informationLogEntry As Int = 2 + Private testResultLogEntry As Int = 3 +' + Dim typeStrings() As String = Array As String ("F","W","I","T") + + Dim Const textExtension As String = ".txt" + Private logFileToUse As String + Private fileRootIs As String + + Private logTimer As Timer + + Type logEntryStruct (logType As Int, timeAndDate As Long, source As String, message As String) + Public faultReportingList As List + Private myLogTestResults As Boolean + +End Sub +'--------------------------------------------------------------------------------- +'--------------------------------------------------------------------------------- +' delete tomorrow file if it exists +' is not designed to run over midnight +Public Sub Initialize(pathName As String, logFileName As String) +Dim fileToDelete As String + + logFileToUse = logFileName&DateTime.GetDayOfMonth(DateTime.Now)&textExtension + fileRootIs = pathName + Dim tomorrowDay As Int = DateTime.GetDayOfMonth(DateTime.Now)+1 + If tomorrowDay > 31 Then tomorrowDay = 1 + fileToDelete = logFileName&tomorrowDay&textExtension + If File.Exists(fileRootIs,fileToDelete) Then + File.Delete(fileRootIs,fileToDelete) + End If + + faultReportingList.Initialize + myLogTestResults = False + logTimer.Initialize("LogTimer",250) + logTimer.Enabled = True + DateTime.TimeFormat = "HH:mm:ss:SSS" + + LogInformation("TrsLogClass", "Log file is "&logFileToUse) +End Sub +'--------------------------------------------------------------------------------- +Public Sub Flush + LogTimer_Tick +End Sub +'--------------------------------------------------------------------------------- +'--------------------------------------------------------------------------------- +'write to the log file - could include a midnight check if required +Sub LogTimer_Tick() + If faultReportingList.Size = 0 Then Return ' nothing to do +Dim TextWriter1 As TextWriter + TextWriter1.Initialize(File.OpenOutput(fileRootIs, logFileToUse, True)) + Do While faultReportingList.Size > 0 + Dim entry As logEntryStruct = faultReportingList.Get(0) + faultReportingList.RemoveAt(0) + Dim strToLog As String = DateTime.Time(entry.timeAndDate) &"::" & typeStrings(entry.logType)&":"&entry.source&":"&entry.message + TextWriter1.WriteLine(strToLog) + Log("*"&strToLog) + Loop + TextWriter1.Close +End Sub +'--------------------------------------------------------------------------------- +'--------------------------------------------------------------------------------- +Public Sub LogInformation(sendingRoutine As String, theInformationMessage As String) +Dim entry As logEntryStruct + entry.Initialize + entry.logType = informationLogEntry + entry.timeAndDate = DateTime.Now + entry.source = sendingRoutine + entry.message = theInformationMessage + faultReportingList.Add(entry) +End Sub +'--------------------------------------------------------------------------------- +Public Sub LogFault(sendingRoutine As String, theFaultMessage As String) +Dim entry As logEntryStruct + entry.Initialize + entry.logType = faultLogEntry + entry.timeAndDate = DateTime.Now + entry.source = sendingRoutine + entry.message = theFaultMessage + faultReportingList.Add(entry) +End Sub +'--------------------------------------------------------------------------------- +Public Sub LogWarning(sendingRoutine As String, theWarningMessage As String) +Dim entry As logEntryStruct + entry.Initialize + entry.logType = warningLogEntry + entry.timeAndDate = DateTime.Now + entry.source = sendingRoutine + entry.message = theWarningMessage + faultReportingList.Add(entry) +End Sub +'--------------------------------------------------------------------------------- +' can be turned off to suppress test results +Public Sub LogTest(sendingRoutine As String, theTestMessage As String) + If myLogTestResults = False Then Return +Dim entry As logEntryStruct + entry.Initialize + entry.logType = testResultLogEntry + entry.timeAndDate = DateTime.Now + entry.source = sendingRoutine + entry.message = theTestMessage + faultReportingList.Add(entry) +End Sub +'--------------------------------------------------------------------------------- +Public Sub LogTestResults(nv As Boolean) + myLogTestResults = nv +End Sub +'--------------------------------------------------------------------------------- +'--------------------------------------------------------------------------------- diff --git a/google-services.json b/google-services.json new file mode 100644 index 0000000..72093d6 --- /dev/null +++ b/google-services.json @@ -0,0 +1,213 @@ +{ + "project_info": { + "project_number": "821860097209", + "project_id": "pusher-4c091", + "storage_bucket": "pusher-4c091.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:328e84bfb7adb112f24f68", + "android_client_info": { + "package_name": "dreparto.keymon.com.mx" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:7bdc730c1cad5927f24f68", + "android_client_info": { + "package_name": "durakelo.keymon.com.mx" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:4a9c1af4c93ba100f24f68", + "android_client_info": { + "package_name": "flp2.chv.com" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:7b6620b2a870f23cf24f68", + "android_client_info": { + "package_name": "gunav2.keymon.com.mx" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:f0e04307b3842e25f24f68", + "android_client_info": { + "package_name": "prof_rep.keymon.com.mx" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:7780f81ae43bf0f3f24f68", + "android_client_info": { + "package_name": "pusher.chv.com" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:7c55bc95da6d952df24f68", + "android_client_info": { + "package_name": "ths.keymon.com.mx" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/google-services_old.json b/google-services_old.json new file mode 100644 index 0000000..b21b6d3 --- /dev/null +++ b/google-services_old.json @@ -0,0 +1,155 @@ +{ + "project_info": { + "project_number": "821860097209", + "project_id": "pusher-4c091", + "storage_bucket": "pusher-4c091.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:7bdc730c1cad5927f24f68", + "android_client_info": { + "package_name": "durakelo.keymon.com.mx" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:4a9c1af4c93ba100f24f68", + "android_client_info": { + "package_name": "flp2.chv.com" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android:7b6620b2a870f23cf24f68", + "android_client_info": { + "package_name": "gunav2.keymon.com.mx" + } + }, + "oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDS-_5lpLX5IiKYrG-0Et-KCKx1bwlY7R0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "821860097209-ef17t5620111ghub7l0tple62otbb56v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:821860097209:android: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 diff --git a/pusher.chv.com.b4a b/pusher.chv.com.b4a new file mode 100644 index 0000000..da6c53e --- /dev/null +++ b/pusher.chv.com.b4a @@ -0,0 +1,765 @@ +Build1=Default,pusher.chv.com +File1=96761371-car-icon-white-icon-with-shadow-on-transparent-background.jpg +File10=marker-rojo-0.png +File11=marker-rojo-coche.png +File12=waze.png +File13=waze-moving.png +File14=waze-moving-2.png +File15=waze-moving-small.png +File16=waze-sleeping.png +File17=waze-sleeping-small.png +File18=zzz.png +File2=ballon280.png +File3=ballon50.png +File4=balloon_overlay_close.png +File5=datetimelayout.bal +File6=icon-transit.png +File7=icon-transit-small.png +File8=infowindow.bal +File9=Layout.bal +FileGroup1=Default Group +FileGroup10=Default Group +FileGroup11=Default Group +FileGroup12=Default Group +FileGroup13=Default Group +FileGroup14=Default Group +FileGroup15=Default Group +FileGroup16=Default Group +FileGroup17=Default Group +FileGroup18=Default Group +FileGroup2=Default Group +FileGroup3=Default Group +FileGroup4=Default Group +FileGroup5=Default Group +FileGroup6=Default Group +FileGroup7=Default Group +FileGroup8=Default Group +FileGroup9=Default Group +Group=Default Group +Library1=administrator +Library10=googlemapsextras +Library11=gps +Library12=ime +Library13=javaobject +Library14=json +Library15=okhttputils2 +Library16=phone +Library17=randomaccessfile +Library18=runtimepermissions +Library19=xcustomlistview +Library2=byteconverter +Library20=xui +Library21=reflection +Library3=compressstrings +Library4=core +Library5=dateutils +Library6=firebaseanalytics +Library7=firebasenotifications +Library8=fusedlocationprovider +Library9=googlemaps +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~CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)~\n~CreateResourceFromFile(Macro, FirebaseAnalytics.Firebase)~\n~CreateResourceFromFile(Macro, FirebaseNotifications.FirebaseNotifications)~\n~AddPermission(android.permission.ACCESS_FINE_LOCATION)~\n~AddPermission(android.permission.WRITE_EXTERNAL_STORAGE) ' Allows an application to write to external storage.~\n~'Lo siguiente es para la api de google maps, para mostrar un mapa en la app~\n~AddApplicationText(~\n~~\n~~\n~) 'Obtener la llave del API en https://console.cloud.google.com/~\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~~\n~SetActivityAttribute(main, android:windowSoftInputMode, adjustPan|stateHidden)~\n~'SetActivityAttribute(main, android:windowSoftInputMode, adjustResize|stateHidden) 'Para que suba al abrir el teclado junto con la libreria IME +Module1=DBRequestManager +Module2=FirebaseMessaging +Module3=Mods +Module4=MyPopup +Module5=Starter +Module6=Subs +NumberOfFiles=18 +NumberOfLibraries=21 +NumberOfModules=6 +Version=12.5 +@EndOfDesignText@ +#Region Project Attributes + #ApplicationLabel: Pusher-ML + #VersionCode: 1 + #VersionName: 3.09.18 + 'Ver. 3.09.18 - Se agregó la posibilidad de mostrar puntos internedios en la ruta y muestra icono diferente si esta en movimiento o parado. + 'SupportedOrientations possible values: unspecified, landscape or portrait. + #SupportedOrientations: portrait + #CanInstallToExternalStorage: False + #BridgeLogger: True + '########################################################################################################### + '###################### PULL ############################################################# + 'Ctrl + click ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=git&Args=pull + '########################################################################################################### + '###################### PUSH ############################################################# + 'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=github&Args=..\..\ + '########################################################################################################### +#End Region +#AdditionalJar: com.android.support:support-v4 +#AdditionalJar: com.google.android.gms:play-services-location + +#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. + 'Api + Private const API_KEY As String = "AAAAv1qt3Lk:APA91bECIR-pHn6ul53eYyoVlpPuOo85RO-0zcAgEXwE7vqw8DFSbBtCaCINiqWQAkBBZXxHtQMdpU6B-jHIqgFKVL196UgwHv0Gw6_IgmipfV_NiItjzlH9d2QNpGLp9y_JUKVjUEhP" + Private rp As RuntimePermissions + Dim phn As Phone + Dim devModel As String + Dim dUbicados As Int 'Dispositivos con ubicacion + Dim dispositivos As Map + Public GZip As GZipStrings + Dim base64 As String + Dim rutaGPS, rRuta, fechaInicioRutaGPS, fechaFinRutaGPS As String + Dim rutasGPS As Map +' Dim topics As List + Dim clientes As List + Dim dispLVClic As Map + Dim rutaClic, rutaAnt As String 'ignore + Dim colorAnt As Int = 1 + Dim line, lineAnt As Polyline 'ignore + Dim tracker As String = "Trckr" + Dim wifi, montoTotal As String + Dim reqManager As DBRequestManager + Dim mapaDestino As Int = 1 + Private hInicio, hFinal As String + Private distanciaRecorrida As String = "0" + Private usuario As String +End Sub + +Sub Globals + 'These global variables will be redeclared each time the activity is created. + Private gmap As GoogleMap + Dim MapFragment1 As MapFragment + Dim latmarker As String + Dim longmarker As String + Dim timemarker As Long + Dim batt As Int + Dim ListView1 As ListView + Private MapPanel As Panel + Dim InfoWindowPanel As Panel + Private TitleLabel As Label + Private SnippetLabel As Label + Private ThumbImage As ImageView + Private cuantos As Label + Private ubicados As Label + Private L_RutaInfo As Label + Private et_buscador As EditText + Private b_buscar As Button + '/////// Popup + Dim const popupItemSettings As String = Chr(0xF05B) & " Borrar Ruta" + Dim const popupItemContactUs As String = Chr(0xF1D9) & " Limpiar Mapa" + Dim const popupItemBorraTodosGPS As String = Chr(0xF059) & " Borrar GPS Todos" + + Dim popExample As MyPopup + Private b_dameRuta As Button + Dim IME As IME + Private p_buscador As Panel + Dim topInicialBuscador As Int + Private L_RutaInfo As Label + Private s_tracker As Spinner + Dim aBuscar As String + Private p_principal As Panel + Private p_ruta As Panel + Private b_regresar As Button + Private b_getRuta As Button + Private MapFragment2 As MapFragment +' Private lv_hora As ListView +' Private s_hora As Spinner + Private b_limpiaMapa, b_inicioMenos, b_inicioMas, b_finalMenos, b_finalMas As Button + Private l_periodo As Label + Private et_inicio, et_final As EditText + Private p_periodoInfo As Panel + Private p_mapa2 As Panel + Private l_periodoTitulo As Label + Private l_distanciaRecorrida As Label + Private s_rutas As Spinner + Private l_rutas As Label 'ignore + Private rutaSeleccionada As String = "" + Private p_contenedor1 As Panel + Private cb_puntosIntermedios As CheckBox +End Sub + +Sub Activity_Create(FirstTime As Boolean) + Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE) +' Wait For Activity_PermissionResult (Permission As String, Result As Boolean) + Dim p As String + If File.ExternalWritable Then + p = File.DirRootExternal + Else + p = File.DirInternal + End If + Log("rootExternal="&p) + Log("File.DirInternal="&File.DirInternal) + Log("File.DirRootExternal="&File.DirRootExternal) + + Activity.LoadLayout("Layout") + clientes.Initialize + clientes.AddAll(Array As String("Trckr","Trckr-ML","Trckr-This","Trckr-Cedex","Trckr-GunaReparto","Trckr-Durakelo")) + IME.Initialize("IME") + dispLVClic.Initialize + Wait For MapFragment1_Ready + gmap.IsInitialized + gmap = MapFragment1.GetMap + rp.CheckAndRequest(rp.PERMISSION_ACCESS_FINE_LOCATION) + Wait For Activity_PermissionResult (Permission As String, Result As Boolean) + If Result Then + gmap.MyLocationEnabled = True + Else + Log("Sin permisos de ubicacion") + End If + ' For android_id + devModel = phn.Model + dispositivos.Initialize + rutaClic = "" + rutasGPS = CreateMap("r" : rRuta) + popExample.Initialize( Activity, Me, "popExample", Array As String( popupItemSettings, popupItemContactUs, popupItemBorraTodosGPS ), 100%x, 100%y, Typeface.FONTAWESOME ) + IME.AddHeightChangedEvent +' Log(" BT="&b_buscar.Top) + topInicialBuscador = p_buscador.top + s_tracker.AddAll(clientes) + cb_puntosIntermedios.Checked = True +' reqManager.Initialize(Me, "http://10.0.0.205:1782") +' s_hora.AddAll(Array As String("00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23")) +End Sub + +Sub Activity_Resume + Subs.panelVisible(p_principal, 0, 0) + p_principal.Width = Activity.Width + p_principal.Height = Activity.Height + Subs.centraPanel(p_contenedor1, p_principal.Width) + devModel = phn.Model + reqManager.Initialize(Me, "http://keymon.lat:1782") + 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("Sin permisos de ubicacion", True) +' End If +' Dim p As Period +' p.Hours = -2 +' p.Minutes = -30 +' Dim x As String = DateUtils.AddPeriod(DateTime.Now, p) +'' x = DateUtils.SetDateAndTime(2022, 2, 24, 20, 20, 20) +' Log(Subs.fechaKMT(x)) + + Dim cmd As DBCommand + cmd.Initialize + cmd.Name = "seleccionaRutasGPS" + reqManager.ExecuteQuery(cmd , 0, "seleccionaRutasGPS", 0) + calculaPeriodo +End Sub + +Sub Activity_Pause (UserClosed As Boolean) + 'Starter.StopFLP +' CallSub(Tracker, "StopFLP") +End Sub + +Sub Button1_Click + Log("Peticion enviada") + Dim tipos As String + tipos="pu,ping" + ToastMessageShow("Solicitud Enviada : "&tipos,True) + Mensaje(tracker, "Peticion","DameUbicacion", tipos) +' Message("Trckr", "Ping","ping", "ping") +' gmap.Clear 'Limpiamos mapa + ListView1.Clear ' Limpiamos Listview + dispositivos.Initialize +End Sub + +'Mandamos mensaje +Sub Mensaje(Topic As String, Title As String, Body As String, Tipos As String) + LogColor("Mandamos mensaje", Colors.Magenta) + 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, "t": Tipos) + 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) + Log(m) +End Sub + +Sub JobDone(Job As HttpJob) + If Job.Success = False Then + ToastMessageShow("Error: " & Job.ErrorMessage, True) + Else + If Job.JobName = "DBRequest" Then + LogColor("JobDone: '" & reqManager.HandleJob(Job).tag & "' - Registros: " & reqManager.HandleJob(Job).Rows.Size, Colors.Green) 'Mod por CHV - 211027 + Dim result As DBResult = reqManager.HandleJob(Job) + If result.Tag = "seleccionaRutaGPS2" Then 'query tag + rutaGPS = "" + Private estasCoords, coordsAnt As Location + estasCoords.Initialize + coordsAnt.Initialize + Private cont As Int = 0 + Subs.SetDateFormat("es", "MX", "MMM d") + distanciaRecorrida = 0 + cont = 0 + For Each records() As Object In result.Rows + If cont = 0 Then + usuario = records(result.Columns.Get("RUTA")) + fechaInicioRutaGPS = Subs.fechaKMT2Ticks(records(result.Columns.Get("FECHA"))) + DateTime.timeformat = "HH:mm" + fechaInicioRutaGPS = DateTime.Date(fechaInicioRutaGPS) & ", " & DateTime.Time(fechaInicioRutaGPS) + End If + Private d As String = records(result.Columns.Get("DATOS")) & "," & records(result.Columns.Get("FECHA")) + Private l As List = Regex.Split(",", d) + estasCoords.Initialize + estasCoords.Latitude = l.Get(0) + estasCoords.Longitude = l.Get(1) + Private acc0 As List = Regex.Split(":", l.Get(2)) +' Log(acc0) + Private acc As String + If acc0.Size = 1 Then acc = acc0.Get(0) Else acc = acc0.Get(1) + If acc < 20 Then + rutaGPS = rutaGPS & d & CRLF + If cont > 0 Then + distanciaRecorrida = distanciaRecorrida + coordsAnt.DistanceTo(estasCoords) +' Log($"Distancia: $1.0{coordsAnt.DistanceTo(estasCoords)} mts, Total: $1.0{distanciaRecorrida} mts"$) + End If + End If + cont = cont + 1 + coordsAnt.Latitude = estasCoords.Latitude + coordsAnt.Longitude = estasCoords.Longitude + fechaFinRutaGPS = Subs.fechaKMT2Ticks(records(result.Columns.Get("FECHA"))) + DateTime.timeformat = "HH:mm" + fechaFinRutaGPS = DateTime.Date(fechaFinRutaGPS) & ", " & DateTime.Time(fechaFinRutaGPS) + Next + ToastMessageShow("Recibimos ruta con " & reqManager.HandleJob(Job).Rows.Size & " puntos.", False) +' Log(rutaGPS) + LogColor($"Distancia recorrida: $1.1{distanciaRecorrida/1000} kms."$, Colors.Magenta) + l_distanciaRecorrida.Text = $"Dist. recorrida: $1.1{distanciaRecorrida/1000} kms."$ + muestraRuta + End If + End If + If Job.JobName = "DBRequest" Then + If result.Tag = "seleccionaRutasGPS" Then 'query tag + s_rutas.Clear + s_rutas.Add("Selecciona") + For Each records() As Object In result.Rows + For Each k As String In result.Columns.Keys + Log(result.Tag & ": " & k & ": " & records(result.Columns.Get(k))) + s_rutas.Add(records(result.Columns.Get(k))) + Next + Next + End If + End If + End If + Job.Release +End Sub + +public Sub ubicacionRecibida(message As Map) + 'Aqui mostramos la ubicacion recibida en el mapa + Dim coords As List = Regex.Split(",",message.Get("body")) + latmarker=coords.Get(0) + longmarker=coords.Get(1) + devModel=message.Get("d") + wifi=message.Get("w") + montoTotal =message.Get("mt") + batt=message.Get("b") + Dim v As String = message.Get("v") + Log("Ubicacion recibida : "&message.Get("d")&","&message.Get("t")&","&message.Get("body")) + If message.Get("t") = "au" Then 'Si es actualizacion +' For i=0 To message.Size-1 +' Log(message.GetKeyAt(i)&"="&message.GetValueAt(i)) +' Next + L_RutaInfo.Text = "Ruta: "&rutaClic&CRLF&"Bateria: "&message.Get("b")&"%"&CRLF& _ + "Monto Total: $"&message.Get("mt")&CRLF&"Wifi: "&wifi&CRLF& _ + "Version: "&message.Get("v")&CRLF + Subs.mueveCamaraMapa(MapFragment1, latmarker, longmarker) + End If + If coords.Size > 2 And IsNumber(coords.Get(2)) Then 'Si hay fecha en coordenadas ... + Dim timemarker As Long=coords.Get(2) + Else + Dim timemarker As Long=0 + End If + Dim dispData As Map = CreateMap("coords" : coords.Get(0)&","&coords.Get(1), "tm" : timemarker, "d" : message.Get("d"), "b" : batt, "w" : wifi, "mt" : montoTotal, "v" : v) + dispositivos.Put(message.Get("d"), dispData) +' Log("dispositvos="&dispositivos) + Log(DateTime.Time(timemarker)) + MapFragment1_Ready + Log("Dispositivos : "&dispositivos.Size) +End Sub + +Sub agregaAListview + ListView1.Clear ' Limpiamos Listview + ListView1.SingleLineLayout.Label.TextSize = 13 + ListView1.SingleLineLayout.ItemHeight = 30dip + ListView1.SingleLineLayout.Label.textColor=Colors.Black + dUbicados=0 + For i = 0 To dispositivos.Size - 1 + Dim vals As Map = dispositivos.GetValueAt(i) + Dim thisRuta As String = dispositivos.GetKeyAt(i) + thisRuta = thisRuta.ToUpperCase + aBuscar = et_buscador.Text + aBuscar = aBuscar.ToUpperCase +' Log(vals) + If vals.ContainsKey("tm") And vals.Get("tm") <>"" Then + Dim located As String = " *" 'Si ya tenemos ubicacion, agregamos un asterisco + dUbicados=dUbicados+1 + Else + Dim located As String = "" + End If + If aBuscar <> "" Then + If thisRuta.IndexOf(aBuscar) > -1 Then + ListView1.AddSingleLine2(dispositivos.GetKeyAt(i)&located, dispositivos.GetValueAt(i)) + End If + Else + ListView1.AddSingleLine2(dispositivos.GetKeyAt(i)&located, dispositivos.GetValueAt(i)) + End If + Next + cuantos.Text = "Rutas"&CRLF&ListView1.Size + ubicados.Text = "Ubicados"&CRLF&dUbicados + Log("dUbicados="&dUbicados) +End Sub + +Sub IME_HeightChanged(NewHeight As Int, OldHeight As Int) + If NewHeight < (topInicialBuscador + p_buscador.Height) Then ' Si el teclado tapa al buscador + If OldHeight > NewHeight Then 'Si se redujo la pantalla + p_buscador.Top = NewHeight - b_buscar.Height + Else ' Si se amplio la pantalla + p_buscador.Top = topInicialBuscador + End If + Else + p_buscador.Top = topInicialBuscador + End If +' ToastMessageShow("Height changed", False) +End Sub + +Sub b_buscar_Click + agregaAListview + IME.HideKeyboard +End Sub + +Sub ListView1_ItemClick (Position As Int, Value As Object) + dispLVClic = Value + rutaClic = dispLVClic.Get("d") +' Log("RutaClic="&dispLVClic.Get("d")) + Dim w As String = dispLVClic.Get("w") + Log("******************"&w&" - "&w.Length) + If w <> "" And w <> Null And w <> "null" Then + w = "Wifi: "&w&CRLF + Else + w = "" + End If +' L_RutaInfo.Text = "Ruta: "&rutaClic&CRLF +' For i=0 To dispLVClic.Size-1 +' Log(dispLVClic.GetKeyAt(i)&"="&dispLVClic.GetValueAt(i)) + '' If dispLVClic.GetKeyAt(i)="d" Then L_RutaInfo.Text = "Ruta: "&dispLVClic.GetValueAt(i)&CRLF +' If dispLVClic.GetKeyAt(i)="b" And dispLVClic.GetValueAt(i) <> "null" Then L_RutaInfo.Text = L_RutaInfo.Text&"Bateria: "&dispLVClic.GetValueAt(i)&"%"&CRLF +' If dispLVClic.GetKeyAt(i)="mt" And dispLVClic.GetValueAt(i) <> "null" Then L_RutaInfo.Text = L_RutaInfo.Text&"Monto Total: $"&dispLVClic.GetValueAt(i)&CRLF +' If dispLVClic.GetKeyAt(i)="w" And dispLVClic.GetValueAt(i) <> "null" Then L_RutaInfo.Text = L_RutaInfo.Text&"Wifi: "&dispLVClic.GetValueAt(i)&CRLF +' If dispLVClic.GetKeyAt(i)="v" And dispLVClic.GetValueAt(i) <> "null" Then L_RutaInfo.Text = L_RutaInfo.Text&"Version: "&dispLVClic.GetValueAt(i)&CRLF +' Next + L_RutaInfo.Text = "Ruta: "&rutaClic&CRLF&"Bateria: "&dispLVClic.Get("b")&"%"&CRLF& _ + "Monto Total: $"&dispLVClic.Get("mt")&CRLF&w&"Version: "&dispLVClic.Get("v")&CRLF + + Dim thisVals As Map = Value + Log(thisVals) + Dim coords As List = Regex.Split(",", thisVals.Get("coords")) + + 'Mueve el mapa a la posicion solicitada + Subs.mueveCamaraMapa(MapFragment1, coords.Get(0), coords.Get(1)) +End Sub + +Sub b_actUbic_click + Mensaje(dispLVClic.Get("d"), "Peticion","DameUbicacion", "pu,au") + ToastMessageShow("Solicitamos Ubicacion: "&rutaClic, True) +End Sub + +Sub b_dameRuta_click + Mensaje(dispLVClic.Get("d"), "Peticion","DameRuta", "dr") + ToastMessageShow("Solicitamos Ruta: "&rutaClic, True) +End Sub + +Sub b_dameRuta_LongClick + popExample.Show(b_dameRuta) 'Show the menu, anchored to the button. +End Sub + +Sub MapFragment1_Ready + gmap = MapFragment1.GetMap + '/////////////////////////////////////////// + Dim GoogleMapsExtras1 As GoogleMapsExtras + Dim InfoWindowAdapter1 As InfoWindowAdapter + + InfoWindowAdapter1.Initialize("InfoWindowAdapter1") + GoogleMapsExtras1.SetInfoWindowAdapter(gmap, InfoWindowAdapter1) + InfoWindowPanel.Initialize("") + InfoWindowPanel.LoadLayout("InfoWindow") + ' a hack(ish) way to set InfoWindowPanel width and height! + MapPanel.AddView(InfoWindowPanel, 0, 0, 240dip, 90dip) + InfoWindowPanel.RemoveView + '///////////////////////////////////////////// + Dim horaFecha As String = timemarker + Dim hms As String = horaFecha.SubString(6) 'Tomamos solo la parte de la hora +' Log("hms="&hms) + Dim horasMinsSegs As String = hms.SubString2(0,2)&":"&hms.SubString2(2,4)&":"&hms.SubString(4) +' Log(horasMinsSegs) + If wifi <> "" And wifi <> Null Then + wifi = $"Wifi: ${wifi&CRLF}"$ + Else + wifi = "" + End If + + If aBuscar <> "" Then + If devModel.IndexOf(aBuscar) > -1 Then + Dim Marker1 As Marker + Marker1 = gmap.AddMarker(latmarker, longmarker, devModel) + Marker1.Title = devModel + Marker1.Snippet = "Last Loc: "&horasMinsSegs&CRLF&"Monto Total: "&montoTotal&CRLF&"Bateria: "&batt&"%" + End If + Else + Dim Marker1 As Marker + Marker1 = gmap.AddMarker(latmarker, longmarker, devModel) + Marker1.Title = devModel + Marker1.Snippet = "Last Loc: "&horasMinsSegs&CRLF&"Monto Total: "&montoTotal&CRLF&"Bateria: "&batt&"%" + End If + +' Subs.mueveCamaraMapa(MapFragment1, latmarker, longmarker) +End Sub + +Sub InfoWindowAdapter1_GetInfoContents(Marker1 As Marker) As View + ' the default InfoContent will be used if this event Sub is not defined or if it returns Null +' Log("InfoWindowAdapter1_GetInfoContents") + TitleLabel.Text=Marker1.Title + SnippetLabel.Text=Marker1.Snippet + ' ThumbImage.Bitmap=? how will you store the file path/file name of the image to display? + ' it's a shame that the Marker object has no Tag property which could be used to store such info + Return InfoWindowPanel +End Sub + +Sub muestraRuta +' Log("iniciamos MuestraRuta") + Private estasCoords, coordsAnt As Location + coordsAnt.Initialize + estasCoords.Initialize +' If lineAnt.IsInitialized Then lineAnt.Visible = False 'Ocultamos ruta anterior + If mapaDestino = 1 Then + gmap = MapFragment1.GetMap + Else + gmap = MapFragment2.GetMap + End If + Dim points As List + Dim point As LatLng + Dim lat1, lon1, latIn, lonIn, latOut, lonOut As Double + line=gmap.AddPolyline + line.Width=10 +' Log("Color ruta") + 'Cambiamos el color de la ruta cada vez que se solicite una nueva + If colorAnt = 1 Then line.color=Colors.RGB(255, 54, 54) ' Rojo + If colorAnt = 2 Then line.color=Colors.RGB(78, 85, 255) ' Azul + If colorAnt = 3 Then line.color=Colors.RGB(50, 205, 37) ' Verde + If colorAnt = 4 Then line.color=Colors.RGB(200, 46, 176) ' Purpura + If colorAnt = 5 Then line.color=Colors.RGB(193, 208, 0) ' Amarillo oscuro + If colorAnt = 6 Then line.color=Colors.RGB(247, 113, 252) ' Rosa oscuro + If colorAnt = 7 Then line.color=Colors.RGB(255, 190, 62) ' Naranja + If colorAnt = 8 Then line.color=Colors.RGB(62, 255, 196) ' Cyan + If colorAnt = 9 Then line.color=Colors.RGB(0, 167, 255) ' Azul claro + If colorAnt = 10 Then line.color=Colors.RGB(255, 0, 8) ' Rojo-rosa + colorAnt = colorAnt + 1 + If colorAnt = 11 Then colorAnt = 1 + points.Initialize + Dim point As LatLng + Dim listtemp As List +' Log(rutaGPS) + If rutaGPS.Length > 10 Then + listtemp = Regex.Split(CRLF, rutaGPS) +' Log(listtemp.Size) + For i = 1 To listtemp.Size-1 + Dim coords() As String = Regex.Split(",",listtemp.Get(i)) + If i = 1 Then + latIn = coords(0) + lonIn = coords(1) + End If + latOut = coords(0) + lonOut = coords(1) + estasCoords.Latitude = latOut + estasCoords.Longitude = lonOut +' Log(coordsAnt) +' Log(estasCoords) + Private estaDist As String = coordsAnt.DistanceTo(estasCoords) +' Log(estaDist) + Dim speedOut As String = coords(4) + Dim Marker0 As Marker + If (i Mod 2 = 0) And estaDist > 300 And cb_puntosIntermedios.Checked Then 'Solo ponemos la mitad de los puntos y si la distancia entre puntos es mayor de 300 mts. + Private hora As String = Subs.fechaKMT2Ticks(coords(6)) + DateTime.timeformat = "HH:mm" + hora = DateTime.Time(hora) + If speedOut > 0.5 Then + Marker0 = gmap.AddMarker3(latOut, lonOut, "Fin " & usuario, LoadBitmap(File.DirAssets, "waze-moving-small.png")) + Else + Marker0 = gmap.AddMarker3(latOut, lonOut, "Fin " & usuario, LoadBitmap(File.DirAssets, "waze-sleeping-small.png")) + End If + Marker0.Snippet = "Hora: " & hora & ", Vel.: " & NumberFormat2((speedOut * 3.6), 1, 2, 2, True) & " km/h" + End If + lat1 = coords(0) + lon1 = coords(1) + point.Initialize(lat1,lon1) + points.Add(point) + coordsAnt.Latitude = latOut + coordsAnt.Longitude = lonOut + Next + line.Points = points ' Mapeamos la ruta en el mapa + lineAnt = line + Dim data As Map = CreateMap("ruta" : line) + rutasGPS.Put(rRuta, data) +' Log(rutasGPS) + Log("Puntos : "&listtemp.Size) +' ToastMessageShow("Recibimos ruta con "&listtemp.Size&" puntos", True) + rutaAnt = rRuta ' Ponemos en rutaAnt la ruta actual + 'Mueve el mapa a las ultmas coordenadas de la ruta + If mapaDestino = 1 Then + Subs.mueveCamaraMapa(MapFragment1, latIn, lonIn) + Else 'Los puntos de la ruta de la base de datos se traen en orden ascendente (los mas viejos primero) + Subs.mueveCamaraMapa(MapFragment2, latOut, lonOut) + Dim Marker1 As Marker +' Marker1 = gmap.AddMarker(latOut, lonOut, "Fin " & usuario) + If speedOut > 1 Then + Marker1 = gmap.AddMarker3(latOut, lonOut, "Fin " & usuario, LoadBitmap(File.DirAssets, "waze-moving.png")) + Else + Marker1 = gmap.AddMarker3(latOut, lonOut, "Fin " & usuario, LoadBitmap(File.DirAssets, "waze-sleeping.png")) + End If +' Marker1.Title = "Fin " & usuario + Marker1.Snippet = "Fecha: " & fechaFinRutaGPS & ", Vel.: " & NumberFormat2((speedOut * 3.6), 1, 2, 2, True) & " km/h" + + Dim Marker0 As Marker + Marker0 = gmap.AddMarker2(latIn, lonIn, "Inicio " & usuario, gmap.HUE_GREEN) +' Marker0.Title = "Inicio " & usuario + Marker0.Snippet = $"Fecha: ${fechaInicioRutaGPS}"$ + End If + End If +End Sub + +Sub popExample_BtnClick( btnText As String ) +' ToastMessageShow(btnText & " selected", False) + If btnText.IndexOf("Borrar Ruta") <> -1 Then + Mensaje(rutaClic, "Peticion","borraRuta", "bgps2") + ToastMessageShow("Borramos Ruta:"&rutaClic, True) + End If + If btnText.IndexOf("Limpiar Mapa") <> -1 Then + gmap.Clear 'Limpiamos mapa + ToastMessageShow("Limpiamos mapa", True) + End If + If btnText.IndexOf("Borrar GPS Todos") <> -1 Then + For c = 0 To clientes.Size-1 + Log(clientes.Get(c)) + Mensaje(clientes.Get(c), "Peticion","borraRuta", "bgps2") + Next + ToastMessageShow("Borrar GPS Todos", True) + End If +End Sub + +Sub s_tracker_ItemClick (Position As Int, Value As Object) + tracker = Value +End Sub + +Sub b_buscar_longClick + mapaDestino = 2 + Subs.panelVisible(p_ruta, 0, 0) + p_mapa2.Width = Activity.Width + p_mapa2.Height = Activity.Height - p_periodoInfo.Height - l_periodo.Height - l_periodoTitulo.Height + p_mapa2.GetView(0).SetLayout(10, 10, p_ruta.Width, p_mapa2.Height) 'ignore + p_ruta.Width = Activity.Width + p_ruta.Height = Activity.Height + p_periodoInfo.Top = Activity.Height - p_periodoInfo.Height - 5 + b_regresar.Top = Activity.Height - b_regresar.Height - 5 + l_periodoTitulo.Top = Activity.Height - (Activity.Height - p_mapa2.Height) + l_periodo.Top = Activity.Height - (Activity.Height - p_mapa2.Height) + 10 + s_rutas.Top = l_periodoTitulo.Top + l_periodoTitulo.Height + l_rutas.Top = s_rutas.top + l_distanciaRecorrida.Top = l_periodo.Top + l_periodo.Height +End Sub + +Sub traeRutaGPS + Log("traemos ruta del servidor") + Dim hi, hf As Period + hi.Hours = et_inicio.text + hf.Hours = et_final.text +' hi.Minutes = -30 +' hInicio = DateUtils.AddPeriod(DateTime.Now, hi) +' hFinal = DateUtils.AddPeriod(DateTime.Now, hf) + Dim cmd As DBCommand + cmd.Initialize + cmd.Name = "seleccionaRutaGPS2" + cmd.Parameters = Array As Object(Subs.fechaKMT(hInicio), Subs.fechaKMT(hFinal), rutaSeleccionada) +' Log($"Inicio: ${Subs.fechaKMT(hInicio)}, Fin: ${Subs.fechaKMT(hFinal)}, ${rutaSeleccionada}"$) + reqManager.ExecuteQuery(cmd , 0, "seleccionaRutaGPS2", 0) + ToastMessageShow("Solicitamos ruta", False) +End Sub + +Private Sub b_getRuta_Click + traeRutaGPS +End Sub + +Private Sub b_regresar_Click + p_principal.Visible = True + p_ruta.Visible = False + mapaDestino = 1 +End Sub + +Private Sub b_limpiaMapa_Click + Private gmap2 As GoogleMap + gmap2.IsInitialized + gmap2 = MapFragment2.GetMap + gmap2.Clear 'Limpiamos mapa +End Sub + +Private Sub b_inicioMenos_Click + If et_inicio.text = "" Then et_inicio.Text = "0" + et_inicio.text = Regex.Replace("[ ]", et_inicio.text, "") 'Quitamos espacios + et_inicio.text = $"$1.1{et_inicio.text - 0.5}"$ + calculaPeriodo +End Sub + +Private Sub b_inicioMas_Click + If et_inicio.text = "" Then et_inicio.Text = "0" + et_inicio.text = Regex.Replace("[ ]", et_inicio.text, "") 'Quitamos espacios + Log(et_inicio.text) + et_inicio.text = $"$1.1{et_inicio.text + 0.5}"$ + calculaPeriodo +End Sub + +Private Sub b_finalMenos_Click + If et_final.text = "" Then et_final.Text = "0" + et_final.text = Regex.Replace("[ ]", et_final.text, "") 'Quitamos espacios + et_final.text =$"$1.1{ et_final.text - 0.5}"$ + calculaPeriodo +End Sub + +Private Sub b_finalMas_Click + If et_final.text = "" Then et_final.Text = "0" + et_final.text = Regex.Replace("[ ]", et_final.text, "") 'Quitamos espacios + et_final.text =$"$1.1{ et_final.text + 0.5}"$ + calculaPeriodo +End Sub + +Sub calculaPeriodo + Dim hi, hf As Period + Private minsInicio() As String + Private minsFinal() As String + minsInicio = Array As String("0","0") + minsFinal = Array As String("0","0") + hi.Hours = et_inicio.text + minsInicio = Regex.Split("\.", et_inicio.text) + If Regex.Split("\.", et_inicio.text).Length > 0 Then minsInicio = Regex.Split("\.", et_inicio.text) + If minsInicio.Length > 1 Then + hi.Minutes = minsInicio(1)*6 + If et_inicio.Text < 0 Then hi.Minutes = minsInicio(1)*6*-1 'Si es negativo lo multiplicamos por -1 par restar los minutos + End If + hf.Hours = et_final.text + minsFinal = Regex.Split("\.", et_final.text) + If Regex.Split("\.", et_final.text).Length > 0 Then minsFinal = Regex.Split("\.", et_final.text) + If minsFinal.Length > 1 Then + hf.Minutes = minsFinal(1)*6 + If et_final.Text < 0 Then hf.Minutes = minsFinal(1)*6*-1 'Si es negativo lo multiplicamos por -1 par restar los minutos + End If + hInicio = DateUtils.AddPeriod(DateTime.Now, hi) + hFinal = DateUtils.AddPeriod(DateTime.Now, hf) + l_periodo.Text = $"Del: ${Subs.diaSemanaString(DateTime.GetDayOfWeek(hInicio))} ${DateTime.Time(hInicio)}${CRLF}Al : ${Subs.diaSemanaString(DateTime.GetDayOfWeek(hFinal))} ${DateTime.Time(hFinal)}"$ +End Sub + +Private Sub s_rutas_ItemClick (Position As Int, Value As Object) + rutaSeleccionada = Value +End Sub \ No newline at end of file diff --git a/subs.bas b/subs.bas new file mode 100644 index 0000000..71c876f --- /dev/null +++ b/subs.bas @@ -0,0 +1,139 @@ +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. + +End Sub + +Sub mueveCamaraMapa(mapFragment As MapFragment, lat As String, lon As String) + 'Mueve el mapa a la posicion solicitada + Private gmap As GoogleMap + gmap = mapFragment.GetMap + Dim aa As CameraPosition + aa.Initialize(lat,lon,15) + gmap.AnimateCamera(aa) +End Sub + +Sub CreateNotification (Body As String) As Notification 'ignore + Dim notification As Notification + notification.Initialize2(notification.IMPORTANCE_LOW) + notification.Icon = "icon" + notification.SetInfo("Tracking location", Body, Main) + Return notification +End Sub + +Sub removeFomList(myList As List, theItem As String) 'ignore + Dim x As Int = 0 + Dim myObject As List + Do While x < myList.Size + myObject = myList.get(x) + If myObject.Get(x) = theItem Then + myList.removeAt(x) + Else + x = x + 1 + End If + Loop +End Sub + +Sub creaMarcador(mapFragment As MapFragment, lat As String, lon As String, devModel As String, timemarker As Double) 'ignore +' Private gmap As GoogleMap +' gmap = mapFragment.GetMap +' Dim Marker1 As Marker +' Marker1 = gmap.AddMarker(lat, lon, title) +' Marker1.Title = devModel +' +' Dim horaFecha As String = timemarker +' Dim hms As String = horaFecha.SubString(6) 'Tomamos solo la parte de la hora +'' Log("hms="&hms) +' Dim horasMinsSegs As String = hms.SubString2(0,2)&":"&hms.SubString2(2,4)&":"&hms.SubString(4) +'' Log(horasMinsSegs) +' If Main.wifi <> "" And Main.wifi <> Null Then +' Main.wifi = $"Wifi: ${Main.wifi&CRLF}"$ +' Else +' Main.wifi = "" +' End If +' Marker1.Snippet = "Last Loc: "&horasMinsSegs&CRLF&"Monto Total: "&montoTotal&CRLF&"Bateria: "&batt&"%" +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 + +'Hace visible y trae al frente el panel con los parametros "Top" y "Left" dados +Sub panelVisible(panel As Panel, top As Int, left As Int) 'ignore + panel.BringToFront + panel.Visible = True + panel.Top = top + panel.Left = left +End Sub + +Sub diaSemanaString(diaSemana As Int) As String 'ignore + If diaSemana = 2 Then Return "Lun" + If diaSemana = 3 Then Return "Mar" + If diaSemana = 4 Then Return "Mie" + If diaSemana = 5 Then Return "Jue" + If diaSemana = 6 Then Return "Vie" + If diaSemana = 7 Then Return "Sab" + If diaSemana = 1 Then Return "Dom" + Return "" +End Sub + +'Convierte una fecha en formato YYMMDDHHMMSS a Ticks +Sub fechaKMT2Ticks(fKMT As String) As Long 'ignore + Try + If fKMT.Length = 12 Then + Private parteFecha As String = fKMT.SubString2(0,6) + Private parteHora As String = fKMT.SubString(6) + Private OrigFormat As String = DateTime.DateFormat 'save original date format + DateTime.DateFormat="yyMMdd" + DateTime.TimeFormat="HHmmss" + Private ticks As Long = DateTime.DateTimeParse(parteFecha,parteHora) +' Log(" +++ +++ pFecha:"&parteFecha&" | pHora:"&parteHora) + DateTime.DateFormat=OrigFormat 'return to original date format + Return ticks + Else + Log("Formato de fecha incorrecto, debe de ser 'yyMMddHHmmss', no '"&fKMT&"' largo="&fKMT.Length) + Return 0 + End If + Catch + Log(LastException) + LogColor($"Fecha dada: ${fKMT}, Parte Fecha: ${parteFecha}, Parte Hora: ${parteHora}"$, Colors.Red) + Return 0 + End Try +End Sub + +Sub SetDateFormat(Language As String, Country As String, format As String) + #if B4A or B4J + Dim locale As JavaObject + locale.InitializeNewInstance("java.util.Locale", Array(Language, Country)) + Dim DateFormat As JavaObject + DateFormat.InitializeNewInstance("java.text.SimpleDateFormat", Array(format, locale)) + Dim r As Reflector + r.Target = r.RunStaticMethod("anywheresoftware.b4a.keywords.DateTime", "getInst", Null, Null) + r.SetField2("dateFormat", DateFormat) + #else if B4i + Dim locale As NativeObject + locale = locale.Initialize("NSLocale").RunMethod("alloc", Null).RunMethod("initWithLocaleIdentifier:", Array(Language & "_" & Country)) + DateTime.As(NativeObject).GetField("dateFormat").SetField("locale", locale) + DateTime.DateFormat = format + #End if +End Sub + +'Centra un panel dentro de un elemento superior +Sub centraPanel(elemento As Panel, anchoElementoSuperior As Int) 'ignore + elemento.Left = Round(anchoElementoSuperior/2)-(elemento.Width/2) +End Sub \ No newline at end of file