Achuthan M
Achuthan M

Reputation: 349

onlocationchanged called too late and not according to my requirement

I am trying to get the current latitude and longitude using an example i found on the following link: http://gabesechansoftware.com/location-tracking/

There are two classes :The first class:

package com.example.marinamapseg;

import android.content.Context;
import android.location.Location;
import android.location.LocationManager;

public class FallbackLocationTracker  implements LocationTracker, LocationTracker.LocationUpdateListener {


    private boolean isRunning;

    private ProviderLocationTracker gps;
    private ProviderLocationTracker net;

    private LocationUpdateListener listener;

    Location lastLoc;
    long lastTime;

    public FallbackLocationTracker(Context context) {
        gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
        net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //Start both
        gps.start(this);
        net.start(this);
        isRunning = true;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;
    }


    public void stop(){
        if(isRunning){
            gps.stop();
            net.stop();
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        //If either has a location, use it
        return gps.hasLocation() || net.hasLocation();
    }

    public boolean hasPossiblyStaleLocation(){
        //If either has a location, use it
        return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
    }

    public Location getLocation(){
        Location ret = gps.getLocation();
        if(ret == null){
            ret = net.getLocation();
        }
        return ret;
    }

    public Location getPossiblyStaleLocation(){
        Location ret = gps.getPossiblyStaleLocation();
        if(ret == null){
            ret = net.getPossiblyStaleLocation();
        }
        return ret;
    }

    public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
        boolean update = false;

        //We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
        if(lastLoc == null){
            update = true;
        }
        else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
            update = true;
        }
        else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
            update = true;
        }
        else if (newTime - lastTime > 5 * 60 * 1000){
            update = true;
        }

        if(update){
            lastLoc = newLoc;
            lastTime = newTime;
            if(listener != null){
                listener.onUpdate(lastLoc, lastTime, newLoc, newTime);                  
            }
        }
    }
}

The second class:

package com.example.marinamapseg;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class ProviderLocationTracker implements LocationListener, LocationTracker {

    // The minimum distance to change Updates in meters
    private static final long MIN_UPDATE_DISTANCE =  0; 

    // The minimum time between updates in milliseconds
    private static final long MIN_UPDATE_TIME = 0; 

    private LocationManager lm;

    public enum ProviderType{
        NETWORK,
        GPS
    };    
    private String provider;

    private Location lastLocation;
    private long lastTime;

    private boolean isRunning;

    private LocationUpdateListener listener;

    public ProviderLocationTracker(Context context, ProviderType type) {
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        if(type == ProviderType.NETWORK){
            provider = LocationManager.NETWORK_PROVIDER;
        }
        else{
            provider = LocationManager.GPS_PROVIDER;
        }
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //The provider is on, so start getting updates.  Update current location
        isRunning = true;
        lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE,this);
        lastLocation = null;
        lastTime = 0;
        //lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE,this);
        //return;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;

    }


    public void stop(){
        if(isRunning){
            lm.removeUpdates(this);
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        if(lastLocation == null){
            return false;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return false; //stale
        }
        return true;
    }

    public boolean hasPossiblyStaleLocation(){
        if(lastLocation != null){
            return true;
        }
        return lm.getLastKnownLocation(provider)!= null;
    }

    public Location getLocation(){
        if(lastLocation == null){
            return null;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return null; //stale
        }
        return lastLocation;
    }

    public Location getPossiblyStaleLocation(){
        if(lastLocation != null){
            return lastLocation;
        }
        return lm.getLastKnownLocation(provider);
    }

    public void onLocationChanged(Location newLoc) {
        long now = System.currentTimeMillis();
        if(listener != null){
            listener.onUpdate(lastLocation, lastTime, newLoc, now);
        }
        lastLocation = newLoc;
        lastTime = now;
    }

    public void onProviderDisabled(String arg0) {

    }

    public void onProviderEnabled(String arg0) {

    }

    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
    }
}

What i tried doing was to create an object of the first class and check whether the location can be found as follows:

fobj=new FallbackLocationTracker(MainActivity.this);
    fobj.start();
    if(fobj.hasLocation())
    {
        Location locobj=fobj.getLocation();
        current_latitude=locobj.getLatitude();
        current_longitude=locobj.getLongitude();
        Toast.makeText(getApplicationContext(),current_latitude+" "+current_longitude,Toast.LENGTH_LONG).show();
        placemarkersonmap();
    }

The issue is as follows:

The haslocation() method will return false as the lastlocation object is null.But the lastlocation object gets a value only in the onlocationchanged method.So how do i ensure that the onlocationchanged method runs before i call my haslocation method?

Upvotes: 1

Views: 705

Answers (1)

CommonsWare
CommonsWare

Reputation: 1006614

So how do i ensure that the onlocationchanged method runs before i call my haslocation method?

onLocationChanged() may never be called. Just because you want a location does not mean that the user has to allow you to get one (e.g., user has both providers disabled). And, just because you want a location does not mean that it is physically possible to get one (e.g., user has GPS disabled and has airplane mode enabled). And, just because you want a location does not mean one will be ready yet.

Hence, your application already needs to deal with not having a location, so add that logic to your app.

You are certainly welcome to also do something more event-driven, starting up some application logic from onLocationChanged(), once you have demonstrated you are at least temporarily able to get location fixes.

Upvotes: 3

Related Questions