GPSTracker, falsches Datum

  • Antworten:16
Wicki11
  • Forum-Beiträge: 103

07.01.2020, 15:40:19 via Website

Problem:
Ich programmiere einen GPSTracker um mir daraus einen Weg anzeigen zu lassen.
Der Weg wird richtig dargestellt, d.h. longitude und latitude sind richtig
aber die Timestamp-Daten (Tag Monat Jahr) kommen bei mir falsch an und ich
weiß nicht warum.
In der MainActivity wird die Klasse WegAufzeichnungsService gestartet, die
die GPS-Daten speichert.
Auf Buttondruck wird GPSTracker gestartet, der diese GPS-Daten in einer
xml-Datei speichert, die u.a. zur Aufzeichnung des Weges dient und die
Daten Streckenlänge, Zeitpunkt von Start und Ende enthält.
Bitte um Hilfe !

/* Ausschnitt Klasse GPSTracker */
...
private List<Location> positions;
private void writePositions(String sz) {
    positions=WegAufzeichnungsService.weg;
    ....
    for(Location loc : positions) {
        storeLocation(loc, writer);
    }
    ....

}
private void storeLocation1(Location loc, BufferedWriter writer) throws IOException {
  SimpleDateFormat gpxTimeFormat;
    String s1;
    writer.write(s1="<wpt lat=\"" + loc.getLatitude() + "\" lon=\"" + loc.getLongitude() + "\">");
    writer.newLine();
String zeit0 = gpxTimeFormat.format(new Date(loc.getTime()));
    //Datum völlig falsch, Uhrzeit Differenz 1 Std.
    //am 06.01.20 Bsp. für Time: 22.05.00 16:04

//Anfang Testbereich

    //nur zum Test
    SimpleDateFormat simple = new SimpleDateFormat("dd MMM yyyy HH:mm:ss");
    Date result = new Date(loc.getTime());
    String zeit2 = simple.format(result);
    Log.d("GPSTracker", zeit0+" | "+zeit2);

//Ende Testbereich

    SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yy");
    String zeit1 = sdf.format(new Date()); //nur Tag.Monat.Jahr, Ersatz für falsches Datum
    String zeit = zeit1 + zeit0.substring(8); //+ Uhrzeit aus loc.getTime()
    writer.write(s1="<time>" + zeit + "</time>");
    writer.newLine();
    writer.write("</wpt>");
    writer.newLine();
}

/* Klasse WegAufzeichnungsService */
package example.com.mymapquestapp;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class WegAufzeichnungsService extends Service implements LocationListener {
    private static final String LOGTAG = "WegAufzeichnungsService";
    private LocationManager locationManager;
    public static List<Location> weg = new ArrayList<Location>();

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(LOGTAG, "create");
        locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
//    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
    //minTime:5sec
//      if (checkPermission("android.permission.ACCESS_FINE_LOCATION",5000,0)==PERMISSION_GRANTED )
        try {
            //Par. 2 minTime: long: minimum time interval between location updates, in milliseconds
            //Par. 3 minDistance:   float: minimum distance between location updates, in meters
            //These two parameters work in AND relation, so in order to receive location update,
            //      both of their conditions need to be achieved
            //Par. 4 LocationListener: onLocationChanged
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 2, this);
//          locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 0, this);
        } catch (SecurityException e) {
            Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();
        } catch (IllegalArgumentException e) {
            Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();
        } catch (RuntimeException e) {
            Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();
        }
        Toast.makeText(getApplicationContext(), "create service", Toast.LENGTH_SHORT).show();
//    weg.clear();
    }
    @Override
    public void onDestroy() {
        Log.d(LOGTAG, "destroy");
//      if (checkPermission("android.permission.ACCESS_FINE_LOCATION",5000,0)==PERMISSION_GRANTED )
        try {
            locationManager.removeUpdates(this);
        } catch (SecurityException e) {
            Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();
        }
        Toast.makeText(getApplicationContext(), "destroy service", Toast.LENGTH_SHORT).show();
        super.onDestroy();      
    }
    @Override
    public void onLocationChanged(Location location) {
        weg.add(location);
    String s="Aktuelle Weglänge: " + weg.size() + " Punkte";
        Log.d(LOGTAG, s);
    Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onProviderDisabled(String p) {
        Log.d(LOGTAG, p);
        Toast.makeText(getApplicationContext(), "onProviderDisabled", Toast.LENGTH_LONG).show();
    }
    @Override
    public void onProviderEnabled(String p) {
        Log.d(LOGTAG, p);
        Toast.makeText(getApplicationContext(), "onProviderEnabled", Toast.LENGTH_LONG).show();
    }
    @Override
    public void onStatusChanged(String s, int status, Bundle b) {
        if (status == LocationProvider.OUT_OF_SERVICE || status == LocationProvider.TEMPORARILY_UNAVAILABLE)
          Toast.makeText(getApplicationContext(), "onStatusChanged:"+status, Toast.LENGTH_LONG).show();
    }
}

— geändert am 07.01.2020, 16:21:06 durch Moderator

Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

07.01.2020, 23:20:17 via App

Welche Long wird denn als Time zurückgegeben?
Stimmt das denn?

Ansonsten mal die Zeit anders aus der long extrahieren.
https://stackoverflow.com/a/20243382

Ach ja und dein SimpleDateFormat ist nicht gesetzt..Ist das Absicht?

— geändert am 07.01.2020, 23:21:51

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

08.01.2020, 11:38:32 via Website

Welche Long wird denn als Time zurückgegeben?

private void storeLocation(Location loc, BufferedWriter writer) throws IOException {
  SimpleDateFormat gpxTimeFormat;
    String s1;
    writer.write(s1="<wpt lat=\"" + loc.getLatitude() + "\" lon=\"" + loc.getLongitude() + "\">");
    writer.newLine();
String zeit0 = gpxTimeFormat.format(new Date(loc.getTime()));
    //Datum völlig falsch, Uhrzeit Differenz 1 Std.
    //am 06.01.20 Bsp. für Time: 22.05.00 16:04

die zurückgegebene Long ist: loc.getTime() und führt zu den angegebenen Werten
am Anfang der GPSTracker-Klasse habe ich u.a. folgende Anweisung:
gpxTimeFormat=new SimpleDateFormat();

Ich habe Deinen Hinweis-Link probiert, das Datum ist nun immer noch falsch, die Zeit richtig.
Hier der Code:

  void test2(Location loc,BufferedWriter writer) {
    SimpleDateFormat simple = new SimpleDateFormat("dd MM yy HH:mm:ss");
    long currentTime = loc.getTime();
    TimeZone tz = TimeZone.getDefault();
    Calendar cal = GregorianCalendar.getInstance(tz);
    int offsetInMillis = tz.getOffset(cal.getTimeInMillis());

    currentTime -= offsetInMillis;
    Date date = new Date(currentTime);
    String zeit0 = simple.format(date);//gpxTimeFormat.format(date);
    try {
        writer.write("<time>" + zeit0 + "</time>");
        writer.newLine();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.d("GPSTrackerTest",zeit0);
}

Ergebnis: 24 05 00 11:33:23

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

08.01.2020, 20:17:33 via Website

Ok, bei mir funktioniert es (ohne Service), aber das sollte keine rolle spielen.

Du hast mir aber immer noch nicht deine Log Time genannt:

 D/TIME: 1578510930273
 D/TIME: 08 Jan. 2020 20:15:30

  Log.d("TIME",String.valueOf(location.getTime()));
        SimpleDateFormat simple = new SimpleDateFormat("dd MMM yyyy HH:mm:ss");
        Date result = new Date(location.getTime());
        String zeit2 = simple.format(result);
        Log.d("TIME",zeit2)

Was passiert wenn du die Zeit direkt on der onLocationChanged ausgiebst?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

08.01.2020, 22:41:27 via Website

Da erhalte ich folgende Daten:

959202788000
24 Mai 2000 23:13:08

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

08.01.2020, 22:59:52 via App

Deine Systemzeit stimmt aber?
Was liefert System.currentTimeMilis()?

Ansonsten keine Ahnung an was es liegen könnte.
Welche API Version nutzt du und welche Android Version?
Du kannst mir die App zukommen lassen, dann kann ich schauen ob es auf meinem Gerät genauso ist.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

09.01.2020, 05:44:19 via Website

Hallo es könnte immer noch am simpeldateformat liegen. Du erstellst zwar nun eines aber das Jahr nur mit yy und nicht wie es eigentlich sein solte yyyy so wie es auch pascal in seinen Code macht.

— geändert am 09.01.2020, 05:53:45

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

09.01.2020, 06:18:31 via Website

Auch erschließt sich mir nicht der Grund warum du den Umweg über die long Variablen curenttime machst.
Dann ziehst du von der Variablen auch noch etwas an veränderst somit auch den timestamp. Und willst es dann mit einem etwas falschen simpeldate formatieren.

Das die Zeit am Anfang - 1 Stunde angezeigt hat ligt mit Sicherheit an der falschen Zeit zohne.

Im timestamp long wird eigentlich immer zohne null gespeichert London.
Bei der Ausgabe must du es erst formatieren.
Du musst deinem Date Objekt schon sagen in welcher zohne es sich befindet. Oder auch deinem Kalender.

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

09.01.2020, 10:57:37 via Website

Dank für die Beiträge !
Ich habe Android 3.4.1 und API 16
Ich weiß zwar immer noch nicht wie es zum falschen Datum kommt, habe aber einen Weg gefunden wie ich zu den gewünschten Werten kommen kann:
- in WegAufzeichnungsService -> onLocationChanged habe ich eingefügt:
location.setTime(System.currentTimeMillis());
- in GPSTracker steht dann:
String zeit0 = gpxTimeFormat.format(new Date(loc.getTime()));
writer.write("" + zeit0 + "");
writer.newLine();

Ich würde natürlich gern wissen, wie es zu dem falschen Datum kommt.

Gruß Wicki11

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

09.01.2020, 12:10:33 via Website

Puh, das ist natürlich uralt...
Allein schon das kann viele Fehlerquellen mitbringen....

Aber dann liegt es am GPS Rollover, und dein GPS Chip + Android Software ist zu alt das zu berücksichtigen.
https://stackoverflow.com/a/56357981/4975457
Hab das mal mit deiner Time gerechnet, dann kommt das ungefähr hin.
Hier musst du aber aufpassen, wenn du das überall einbaust, kommt auf neuen Geräten ein FEhler. Daher musst du eigentlich feststellen ob die Berechnung notwendig ist oder nicht. Anderenfalls werden keine neueren Geräte unterstützt.

Allerdings würde ich nie auf solch alten Devices arbeiten. Um alte und neue Devices zu unterstützten brauchst du sehr viel Aufwand und du kannst neue Features nicht nutzen etc., davon abgesehen dürfte ein Android 3.x total langsam und veraltet sein was die Sicherheit angeht.

Edit: das bringt dir aber nichts, da überschreibst du einfach die Zeit die dein GPS reingeschrieben hat.
Dann kannst du auch unabhängig der Location die aktuelle Zeit anzeigen lassen.
Dabei geht aber in jedem Fall der Zeitliche verlauf verloren... -- Edit 2: Quatsch :O

— geändert am 09.01.2020, 12:26:49

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Jokel
Kommentieren
Wicki11
  • Forum-Beiträge: 103

09.01.2020, 21:28:35 via Website

Ich will mit meiner App einen Fußmarsch oder Fahrrad-Weg protokollieren, d.h. aufzeichnen in einer Karte mittels Location, die Weglänge und Start- und Endzeit ermitteln. Da nützt mir die UTC-Zeit offensichtlich wenig und

Puh, das ist natürlich uralt...

aber zielführend.
Was mein Android 3.4.1 angeht so werde ich wahrscheinlich auf 3.5.3 updaten in der Hoffnung, dass da meine Apps noch laufen und ich nicht noch weitere Komponenten (bspw. Gradle) installieren muß.

Ich bedanke mich nochmal bei Dir Pascal für Deine Beiträge zu meinem Problem !

Gruß Wicki11

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

10.01.2020, 05:23:18 via Website

Hallo Wicki11

Android 3.4.1 war doch nicht für Handys gedacht nur für tablet's.

— geändert am 10.01.2020, 08:07:59

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

10.01.2020, 06:23:29 via Website

Habe es mir noch mal angesehen

mal eine Frage zu dem hier

void test2(Location loc,BufferedWriter writer) {
SimpleDateFormat simple = new SimpleDateFormat("dd MM yy HH:mm:ss");
long currentTime = loc.getTime();
TimeZone tz = TimeZone.getDefault();
Calendar cal = GregorianCalendar.getInstance(tz);
int offsetInMillis = tz.getOffset(cal.getTimeInMillis());
currentTime -= offsetInMillis;

was steht in der Variablen currentTime vor dem abziehen des offset ?
welchen Wert hat der offsetInMillis ?

ist 959202788000 mit oder ohne offset?

wen du den Link von pascal beachtest und auch so machst kommst du auf.

0959202788000
0619315200000 +
1578517988000 =

das entspricht
08.01.2020 21:13:00 UTC
08.01.2020 22:13:00 Local Zeit

— geändert am 10.01.2020, 08:13:13

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

10.01.2020, 15:57:24 via Website

  • Punkt1
    habe diesen von Dir erwähnten Test nochmal gemacht, folgende Werte kamen dabei heraus:
    currentTime ohne: 959348683000
    offsetInMillis: 3600000
    Frage: woher stammt Dein Wert 0619315200000 ?

  • Punkt2
    Android 3.4.1 läuft bei mir auf einem Laptop,
    als Gerät habe ich ein Smartphone Samsung GT-I8190 mit API16

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

10.01.2020, 17:23:39 via Website

Der Wert kommt aus dem Link von @Pascal.

https://stackoverflow.com/a/56357981/4975457

Kann man sich aber auch selber errechnen.

Der offset ist genau eine Stunde.
Also utc Zeit +1 Stunde unsere Zeit

https://www.cisa.gov/gps-week-number-roll-over

Dein gps Empfänger arbeitet bestimmt noch mit 10 bit wochen Zähler.
Neu neuere Empfänger arbeiten mit 13 bit

— geändert am 10.01.2020, 17:54:16

Hilfreich?
Wicki11
Kommentieren
Wicki11
  • Forum-Beiträge: 103

10.01.2020, 19:12:53 via Website

Dank an Jokel weil ich jetzt den "GPS Week Number Rollover" verstanden habe, offensichtlich die Ursache für mein Ausgangsproblem.
Ich bleibe aber bei meiner Lösung in der ich in "onLocationChanged"
mit "location.setTime(System.currentTimeMillis());" die UTC-Zeit jedesmal überschreibe.
Das ist für meine Zwecke die eleganteste Lösung.

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

10.01.2020, 20:02:53 via Website

Nachtrag: neue Lösung mit Anwendung von Pascals Link:

        public void onLocationChanged(Location location) {

// location.setTime(System.currentTimeMillis()); //aktuelle Systemzeit setzen
long gpsTime=location.getTime();
if ((gpsTime > 0) && (gpsTime < 1546300800000L))
gpsTime += 619315200000L; //add 24 weeks
location.setTime(gpsTime);
...
...

Damit funktioniert meine App auch mit der korrigierten UTC-Zeit.

Hilfreich?
Kommentieren