Android onLocationChanged location.getTime() returns wrong time
Asked Answered
B

1

8

I have a Samsung Galaxy Tab A. I have implemented android.location.LocationListener and onLocationChanged(Location location) gets called and it gives me kinda right longitude and latitude but,

The problem is: location.getTime() gives me wrong time, it returns a time near 300000 mil or so. It should be something like 1471243684497.

I don't know what to do.

GPSTracker class:

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class GPSTracker extends Service implements LocationListener
{
    //flag for GPS Status
    boolean isGPSEnabled = false;
    
    //flag for network status
    //boolean isNetworkEnabled = false;
    
    boolean canGetLocation = false;
    
    Location location;
    double latitude;
    double longitude;
    
    //The minimum distance to change updates in metters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; //10 metters
    
    //The minimum time beetwen updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 10; // 1 minute
    
    //Declaring a Location Manager
    protected LocationManager locationManager;
    
    /*public GPSTracker(Context context) 
    {
        this.mContext = context;
        getLocation();
    }*/
    
    public Location getLocation(Context ctx)
    {
        try
        {
            locationManager = (LocationManager) ctx.getSystemService(LOCATION_SERVICE);
    
            //getting GPS status
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    
            //getting network status
            //isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    
            if (!isGPSEnabled /*&& !isNetworkEnabled*/)
            {
                // no network provider is enabled
            }
            else
            {
                this.canGetLocation = true;
    
                //First get location from Network Provider
               /* if (isNetworkEnabled)
                {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
    
                    Log.d("Network", "Network");
    
                    if (locationManager != null)
                    {
                        location = 
                                locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        updateGPSCoordinates();
                    }
                }*/
    
                //if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled)
                {
                    if (location == null)
                    {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
    
                        Log.d("GPS Enabled", "GPS Enabled");
    
                        if (locationManager != null)
                        {
                            location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            updateGPSCoordinates();
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            //e.printStackTrace();
            Log.e("Error : Location", "Impossible to connect to LocationManager", e);
        }
    
        return location;
    }
    
    public void updateGPSCoordinates()
    {
        if (location != null)
        {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
        }
    }
    
    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app
     */
    
    public void stopUsingGPS()
    {
        if (locationManager != null)
        {
            locationManager.removeUpdates(GPSTracker.this);
        }
    }
    
    /**
     * Function to get latitude
     */
    public double getLatitude()
    {
        if (location != null)
        {
            latitude = location.getLatitude();
        }
    
        return latitude;
    }
    
    /**
     * Function to get longitude
     */
    public double getLongitude()
    {
        if (location != null)
        {
            longitude = location.getLongitude();
        }
    
        return longitude;
    }
    
    /**
     * Function to check GPS/wifi enabled
     */
    public boolean canGetLocation()
    {
        if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)/*&&
                !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)*/){
            this.canGetLocation = false;
        } else {
            this.canGetLocation = true;
        }
        return this.canGetLocation;
    }
    
    /**
     * Get list of address by latitude and longitude
     * @return null or List<Address>
     */
    public List<Address> getGeocoderAddress(Context context)
    {
        if (location != null)
        {
            Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
            try 
            {
                List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
                return addresses;
            } 
            catch (IOException e) 
            {
                //e.printStackTrace();
                Log.e("Error : Geocoder", "Impossible to connect to Geocoder", e);
            }
        }
    
        return null;
    }
    
    /**
     * Try to get AddressLine
     * @return null or addressLine
     */
    public String getAddressLine(Context context)
    {
        List<Address> addresses = getGeocoderAddress(context);
        if (addresses != null && addresses.size() > 0)
        {
            Address address = addresses.get(0);
            String addressLine = address.getAddressLine(0);
    
            return addressLine;
        }
        else
        {
            return null;
        }
    }
    
    /**
     * Try to get Locality
     * @return null or locality
     */
    public String getLocality(Context context)
    {
        List<Address> addresses = getGeocoderAddress(context);
        if (addresses != null && addresses.size() > 0)
        {
            Address address = addresses.get(0);
            String locality = address.getLocality();
    
            return locality;
        }
        else
        {
            return null;
        }
    }
    
    /**
     * Try to get Postal Code
     * @return null or postalCode
     */
    public String getPostalCode(Context context)
    {
        List<Address> addresses = getGeocoderAddress(context);
        if (addresses != null && addresses.size() > 0)
        {
            Address address = addresses.get(0);
            String postalCode = address.getPostalCode();
    
            return postalCode;
        }
        else
        {
            return null;
        }
    }
    
    /**
     * Try to get CountryName
     * @return null or postalCode
     */
    public String getCountryName(Context context)
    {
        List<Address> addresses = getGeocoderAddress(context);
        if (addresses != null && addresses.size() > 0)
        {
            Address address = addresses.get(0);
            String countryName = address.getCountryName();
    
            return countryName;
        }
        else
        {
            return null;
        }
    }
    
    @Override
    public void onLocationChanged(Location location) 
    {   
    }
    
    @Override
    public void onProviderDisabled(String provider) 
    {   
    }
    
    @Override
    public void onProviderEnabled(String provider) 
    {   
    }
    

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

And my own class which extends GPSTracker class:

public class NewMainService extends GPSTracker {
    

    @Override
    public void onLocationChanged(Location location) {
        long time = location.getTime();
        Log.i("TAG", "onLocationChanged time: "+time); //prints wrong timestamp
        super.onLocationChanged(location);
    }
}

EDIT:

everything works fine on other devices.

I googled it and it's a bug in some devices. location listeners stop receiving changes after some time.

the time it gives me is like device's uptime, it's some hours, it's not a date.

EDIT 2: Now I'm using com.google.android.gms.location.FusedLocationProviderClient instead and android.location.LocationManager doesn't even give me any location updates anymore on Android 10+

Backache answered 15/8, 2016 at 7:29 Comment(5)
Had the same issue (LocationManager returns a location with device's uptime instead of time since epoch) - if possible, can you please give the links regarding the bug? Could not find anything except this SO question. Many thanks!Antefix
@AlephAleph, I ended up implementing my own simple location listener and not "Fused Location". and mixed it with wake lock of type PARTIAL_WAKE_LOCK, I registered Locationmanager to listen for both network provider and gps provider. and now it's working fine.Backache
I have a similar problem on some Asus devices. I am using Fused Location Provider. The getTime() method sometimes returns the time with one hour mistake. I do not change the time and the time zone of the device. Did you find any solution?Emyle
On startup of location requests onLocationChanged seems to give an old location from some buffer. I always set the time of the last fix and only take time if time is bigger than last fix (and not take time from first fix but only set last_location_time with it). I suggest to also check the provider and only take the time if provider.equals(LocationManager.GPS_PROVIDER); I dont think you could rely on timestamp of wifi if there is any. I still wonder if this is really fail proof or if I should quit using gps time alltogether and switch completly to SNTPOrphrey
@Orphrey Use com.google.android.gms.location.FusedLocationProviderClient insteadBackache
B
-1

You can use NMEA location listener and only get the time from that. it's always true and is in UTC time even if you change your device's timezone or date and time, this will always give you the current real date and time.

Limitaions:

-if GPS or Location is off, you won't get NMEA. (you can check if Location is turned on or not)

-if Location is turned on but user has changed its accuracy to network only through the Settings, you won't get NMEA. (you can check if locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) )

Backache answered 14/6, 2017 at 14:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.