G-Track für Android Mobiltelefone

Eigene oder Gemeinschaftsprojekte, Klassen, Module, Codeschnipsel, HowTos, ...
Antworten
Benutzeravatar
gambi
Moderator
Beiträge: 175
Registriert: Mi 8. Mai 2013, 21:46
Kontaktdaten:

G-Track für Android Mobiltelefone

Beitrag von gambi » So 14. Mai 2017, 17:45

Hallo zusammen,
die Urlaubszeit beginnt bald und manche zeichnen ihre Touren mit diversen GPS-Trackern über ihr Smartphone auf.
Gambas bietet mit der Komponente gb.map die Möglichkeit, z.B. Karten von OpenStreetMap anzuzeigen und darin auch Wegepunkte einzutragen.
Im Gambas Buch gibt es unter http://gambas-buch.de/dw/doku.php?id=k24:k24.8:start einige schöne Beispiele dazu.

Dadurch inspiriert kam mir die Idee zu G-Track. Einem Programm, mit dem die GPS-Daten eines Android-Mobiltelefons aufgezeichnet und anschließend mit Gambas angezeigt werden können. Die folgende Grafik soll das Prinzip verdeutlichen.
G-Track_Bsp.png
G-Track_Bsp.png (537.13 KiB) 176 mal betrachtet
Die grundlegenden Rahmenbedingen/Einschränkungen sind dabei:
  • Die Funktion ist nur für Android-Mobiltelefone möglich
  • Es soll keine Google-API zum Einsatz kommen
  • Satt dessen wird der Android-Gerätemanager verwendet (https://www.google.com/android/devicemanager), der es ermöglicht, sein Mobiltelefon zu lokalisieren, sofern die Funktion auf dem Mobilteil aktiviert ist
  • Es soll eine Auswahl des Mobiltelefons möglich sein, sofern mehrere Geräte mit dem entsprechenden Google-Account verknüpft sind
  • Die Karten kommen von OpenStreetMap
  • Anmeldung am Google-Account, Abfrage der Geo-Koordinaten, Anzeige der Wegepunkte usw. erfolgt mit 'Gambas-Bord-Mitteln'
Ich will das Projekt hier Schritt für Schritt entwickeln und freue mich deshalb auf Kritik, Anregungen und Verbesserungsvorschläge :wink:

Legen wir also los mit Step 1: - Anmeldung über den Devicemanager.

Wir benötigen:
  • eine Form - FMain
  • ein WebView - WebGGM
  • einen Button - btnStart
gambas code
Private $sEmail As String = "E-MAIL"
Private $sPW As String = "PASSWORT"

Public Sub btnStart_Click()
   connect()
End

Private Function connect() As Integer
' ACHTUNG: nur die Adresse, die im href steht verwenden. Das gambas-code Plugin macht hier zu viel des Guten!
Dim sURL As String = "https://www.google.com/android/devicemanager?hl=de"
Dim shtest As String
  
  webGGM.Url = sURL
  While webGGM.Progress < 1                                                          ' Warten, bis Seite geladen ist
    Wait 
  Wend

  shtest = webGGM.Eval("document.getElementById('Email').value='" & $sEmail & "'")    ' Eingabe von E-Mail
  Wait 
  webGGM.Eval("document.forms[0].submit()")                                           ' Abschicken
  
  While webGGM.FindText("Anmelden")                                                   ' Warten bis der Text erscheint
    Wait 0.01
  Wend
 
  shtest = webGGM.Eval("document.getElementById('Passwd').value='" & $sPW & "'")      ' Eingabe PW
  Wait 
  webGGM.Eval("document.forms[0].submit()")                                           ' Abschicken
  
End
Nach der erfolgreichen Anmeldung, sollten wir das von uns gewünschte Gerät auswählen können.
Dies kommt dann im 2. Schritt.

Bis dahin
gg

Benutzeravatar
gambi
Moderator
Beiträge: 175
Registriert: Mi 8. Mai 2013, 21:46
Kontaktdaten:

Re: G-Track für Android Mobiltelefone

Beitrag von gambi » Sa 20. Mai 2017, 20:18

Bevor es im zweiten Teil um die Identifikation und Auswahl des zu trackenden Gerätes geht, muss zunächst die Anmeldung angepasst werden. Die ID für die E-Mail-Adresse wurde nämlich von 'Email“ auf 'identifierId' geändert. gambas code
 shtest = webGGM.Eval("document.getElementById('identifierId').value='" & $sEmail & "'") 
Nun aber zur Auswahl:
Wenn mit dem gewählten Google-Account mehrere Geräte verknüpft sind wollen wir eine Auswahl treffen können. Bei nur einem verknüpften Gerät liefert die angedachte Funktion genau dieses Gerät zurück.
Für die Auswahl eines Gerätes soll eine Form dynamisch erstellt werden.
Geräteauswahl.png
Geräteauswahl.png (6.97 KiB) 147 mal betrachtet
Was wir aus dem HTML-Dokument benötigen ist der Klassenname "device-name". In ihm stehen alle mit dem Account verknüpften Geräte. Diese Auflistung wird in ein Stringarray übergeben. Daneben nutzen wir die Klassenauflistung "device-details", woraus wir die Geräte-ID gewinnen.
Für das Auswahlformular sowie den Gerätenamen und die ID führen wir neue Variablen ein: gambas code
Private $FDevices As Form
Private $DeviceName As String
Private $DeciveID As String
Am Ende der connect()-Funktion wird dann die Auswahl durch Aufruf von thisDevice() gestartet. gambas code
Private Function thisDevice() As String                     ' Tracke das gewählte Device
Dim dDoc As New HtmlDocument                                ' Die zu untersuchende HTML-Seite
Dim aDevices As New String[]                                ' Enthält die Geräte
Dim xDevices As XmlElement                                  ' xml-Element für die Gräte
Dim sDeviceName, sErrorTxt As String
Dim hRButton As RadioButton                                 ' RadioButton
Dim xOff As Integer                                         ' Offset für die Höhe der Form

  
  Try dDoc.FromString(webGGM.HTML)                          ' Übernehmem der Webseite in dDoc
  Error.Clear                                               ' Lösche einen möglichen Fehler 
   
  For Each xDevices In dDoc.getElementsByClassName("device-name")
    If Not aDevices.Exist(xDevices.Value) Then
      aDevices.Add(xDevices.Value)                     ' Enthält alle verfügbaren Devices mit ihrem Namen
    Endif
  Next
  
  If aDevices.Count = 0 Then                     ' Falls kein Gerät mit dem Account verknüpft ist, wird das Programm beendet
    sErrorTxt = "Es ist noch kein Gerät mit <b><font color='red'>" 
    sErrorTxt &= $sEmail & "</font></b> verknüpft!" & gb.NewLine
  ' ACHTUNG: HIER WIEDER NUR DEN href-TEIL VERWENDEN!
    sErrorTxt &= "Hilfe: https://support.google.com/accounts/?p= ... ce_manager"
    Message.Error(sErrorTxt, "&Beenden")
    Quit
  Endif
  
  $FDevices = New Form As "FDevices"                 ' Erzeugen einer neuen Form
  $FDevices.Width = 400
  $FDevices.Title = "Wähle ein Gerät"
  $FDevices.Height = 50 + aDevices.Length * 30       ' Die Höhe wird variabel festgelegt
  
  For Each sDeviceName In aDevices                  ' Erzeugen der richtigen Anzahl von RadioButtons
    hRButton = New RadioButton($FDevices)
    hRButton.x = 20
    hRButton.Y = 20 + xOff
    hRButton.H = 30
    hRButton.w = 300
    hRButton.Visible = True
    hRButton.Caption = sDeviceName
    xOff += 30
    Wait
  Next
  
  hRButton = $FDevices.Children[0] '  Das erste gefundene Gerät wird vorausgewählt
  hRButton.Value = True  
  $FDevices.Show()
     
  While $FDevices <> Null            ' Schleife solange die Geräteauswahl angezeigt wird
    Wait 0.1
  Wend
     
End
Beim Schließen der Form wird der ausgewählte Gerätenamen der entsprechenden Variablen übergeben und in der Funktion findDeviceID() die Geräte-ID ermittelt.
gambas code
Public Sub FDevices_Close()         ' Schließen der Geräteauswahl
Dim rb As RadioButton
   
  For Each rb In $FDevices.Children                ' Durchsuche alle RadioButtons
    If rb.Value = True Then                       ' Wenn ein Wert 'TRUE' ist
      $DeviceName = rb.Caption                    ' übernehme den Namen des Geräts in $DeviceName 
      $DeciveID = findDeviceID()                  ' Ermittelt die Device-ID des Gerätes
    Endif
  Next
  $FDevices = Null                                 ' Setze das Objekt zurück 
  
End

Private Function findDeviceID() As String       ' Ermitteln der Geräte-ID
Dim dDoc As New HtmlDocument
Dim DeviceNode As XmlNode

  Try dDoc.HtmlFromString(webGGM.HTML)
  Error.Clear
  
  For Each DeviceNode In dDoc.GetElementsByClassName("device-details")    ' Die Details aller Geräte
    If InStr(DeviceNode.Value, $DeviceName) Then                          ' Wurde der Gerätename gefunden...
      If Devicenode.ChildNodes.count = 2 Then                             ' ... prüfe, ob 2 Nodes vorhanden
        If Devicenode.ChildNodes[0].Attributes.count = 3 Then             ' ... prüfe, ob 3 Attribute vorhanden
          Return Devicenode.ChildNodes[0].Attributes["data-id"]           ' Gebe die Geräte-ID aus dem Attribut zurück
        Endif                                                             ' Ende (3 Attribute)
      Endif                                                               ' Ende (2 Nodes)
    Endif                                                                 ' Ende Geräte-Details
  Next

End
Der nächste Teil wird sich dann damit beschäftigen, wie die Geo-Koordinaten aus dem HTML-Code ermittelt werden können.
gg

Benutzeravatar
gambi
Moderator
Beiträge: 175
Registriert: Mi 8. Mai 2013, 21:46
Kontaktdaten:

Re: G-Track für Android Mobiltelefone

Beitrag von gambi » Sa 27. Mai 2017, 17:32

Die spannende Frage lautet: Wie kommen wir an die Geo-Koordinaten.

Die HTML-Seite muss geparst werden, denn die Koordinaten stehen in einem src-Attribut eines script-Tags. Hier ein Beispiel mit den rot markierten Koordinaten.
src="https://maps.googleapis.com/maps/api/js ... 5m2&amp;1d52.530644&amp;2d13.383068&amp;7sUS&amp;9sde&amp;client=google-nova&amp;callback=_xdc_._lown2f&amp;token=41324"
Wenn man übrigens dem Link folgt, erhält man eine Art JSON-Datei mit interessanten Details (funktioniert natürlich nur mit aktuellem Token!)

Hier also der Quelltext. Zuerst übergeben wir die HTML-Seite einem HTMLDocument-Objekt und parsen dann in der Funktion 'findCoordinates(dHTML As HtmlDocument) As String[] ' das Dokument, indem die 'script-Tags' in eine Auflistung übergeben werden.
Das Ergebnis wird dann als String[] zurück gegeben.
gambas code
Private Function ReadGeoData() As Integer
Dim dDoc As New HtmlDocument
Dim sLat, sLon As String
Dim pts As String[]
Dim tCount As Integer

  Try dDoc.HTMLFromString(webGGM.HTML)
  Error.Clear  
  
  While Not pts
    pts = findCoordinates(dDoc)
    Wait 0.5
    Inc tCount
    If tCount = 20 Then 
    Print "Gerät nicht erreichbar!"
    Return
    Endif
  Wend
  
  Try sLat = pts[0]
  Try sLon = pts[1]
  
  Print Time()
  Print sLat
  Print sLon  
  Print "----------------------------------------------------------------------"
 
End
gambas code
Private Function findCoordinates(dHTML As HtmlDocument) As String[] 
Dim xEle As XmlElement
Dim sCoord As String
Dim aCoord As String[]

  For Each xEle In dHTML.GetElementsByTagName("script")           ' Jedes xmlElement in der Auflistung von 'script' durchsuchen 
    If InStr(xEle.GetAttribute("src"), "GeocodeService") Then      ' Wenn der String 'GeocodeService' im Attribut 'src' vorkommt ...
      If InStr(xEle.GetAttribute("src"), ";1d") Then                ' ... wenn zusätzlich der String '1d' im src-Attribut vorkommt ...
        sCoord = Replace(xEle.GetAttribute("src"), "amp;", "")      ' ... dann ersetze 'amp;' durch Leerstring
        Try aCoord = Split(sCoord, "&")                             ' Splitte den String nach '&'
        Return [Right(aCoord[1], -2), Right(aCoord[2], -2)]         ' Extrahiere aus dem Split Latitude und Longtitude und gib als String[] zurück
      Endif                                                         ' Ende '1d' im src-Attribut
    Endif                                                          ' Ende 'GeocodeService'im src-Attribut
  Next                                                            ' Ende Auflistung

End
Damit sind jetzt die Voraussetzungen geschaffen, ein Android-Mobiltelefon oder Tablet über den Gerätemanager zu tracken. Fehlt lediglich ein Timer, der in bestimmten Abständen die Seite aktualisiert und noch etwas Logik, um immer das richtige Gerät zu erwischen sowie die Neuanmeldung , die nach einer Stunde notwendig wird, abzufangen.

Im letzten Teil will ich dann noch zeigen, wie die aufgezeichneten Daten in einer Map dargestellt werden können.

gg

Benutzeravatar
gambi
Moderator
Beiträge: 175
Registriert: Mi 8. Mai 2013, 21:46
Kontaktdaten:

Re: G-Track für Android Mobiltelefone

Beitrag von gambi » Sa 10. Jun 2017, 19:21

Im letzten Teil will ich nun zeigen, wie die gesammelten Daten in einer Map angezeigt werden können.
Dazu wurden die Daten in der Funktion getGeoData() als Textdatei im Format „sLat; sLong; sDate“ abgespeichert. Natürlich kann auch ein x-beliebig anderes Format gewählt werden. Sollen die Daten z.B. mit Geodaten-Viewern (Google-Earth oder anderen) anzuschauen sein, so empfehlt es sich, die Daten im kml- oder gpx-Format abzulegen.

Für die Darstellung der Strecke in einer Karte wird die Komponente gb.map benötigt. Prima, dass sich in gb.map eigentlich die Methode „AddPolyLine“ befindet. Eigentlich deshalb, weil mit AddPolyLine leider keine offene Linie sondern ein Polygon gezeichnet wird. D.h., dass der letzte eingegebene Punkt sich wieder mit dem ersten Punkt verbindet und damit die Begrenzungslinie eines Polygons entsteht. Nach Rücksprache mit Fabien Bodard hat er dafür bereits einen Fix zur Verfügung gestellt [1].
In der hier gezeigten Variante nutze ich aber noch den „Workaround“ mit Paint().

Insgesamt ist die Dokumentation zur Komponente recht lückenhaft. So werden leider u.a. die Methoden zur Darstellung von Start-/Stop-Punkten und deren Handhabung nicht beschrieben. Durch Probieren und eine Menge Versuche und Irrtümer ist es mir aber gelungen, eine ganz passable Darstellung einer Wegstrecke zu erreichen.
Die beiden wesentlichen Punkte sind:
  • Schrittweise Anzeige der Wegstrecke mit einem Slider
  • Darstellung des Start- und Stop-Punktes mit einem selbst definierten Symbol
  • Anpassung der Linenfarbe und der Linienstärke (direkt im Code)
G-Track-Map.png
G-Track-Map.png (505.58 KiB) 59 mal betrachtet
Auf eine Anzeige des Codes wird hier verzichtet. Ladet das Projekt mit der Beispielwegstrecke herunter und probiert es einfach aus. Über den Menü-Punkt „Tracks“ kann die Beispiel-Wegstrecke „Berlin.txt“ geladen werden. Danach über den Slider den Weg einfach „abgehen“.
Viel Spaß beim Ausprobieren.

gg

[1]http://gambas.8142.n7.nabble.com/How-to ... 57682.html
Dateianhänge
G-Track-Map-0.0.1.tar.gz
(14.98 KiB) 2-mal heruntergeladen

Benutzeravatar
4tionov
Site Admin
Beiträge: 154
Registriert: So 18. Mai 2014, 22:40
Kontaktdaten:

Re: G-Track für Android Mobiltelefone

Beitrag von 4tionov » Sa 10. Jun 2017, 21:52

Wow! Hammer, was mit Gambas alles möglich ist! Danke für das schöne Beispiel. Bin schwer beeindruckt. :-)
Alles Gute,

4tionov

Benutzeravatar
gambi
Moderator
Beiträge: 175
Registriert: Mi 8. Mai 2013, 21:46
Kontaktdaten:

Re: G-Track für Android Mobiltelefone

Beitrag von gambi » Sa 17. Jun 2017, 18:21

Hallo 4tionov,
danke. Ja, mit Gambas lassen sich tolle Sachen umsetzen.
Ich würde mich über weiter Beispiele freuen :wink:

gg

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast