Question

I would like to expose the following question.

I have an Android App that makes use of both UserLocation (I developped my own class in order to get when the app atars as I explain below) and Google Maps Api v2.

Let´s say the app has two buttons Button one--> When the user clicks the app shows a map with a lot of markers, I use the google maps api V2 fragment. And I mahe use of the following line to show the users location.

mMap.setMyLocationEnabled(true);

Button two--> Starts a AsyncTask to get the users position and calculate the closets places, and show then on a Map and on a ListView. Below I provide all my code to do this:

private class findPosicionTask extends AsyncTask<Void,Integer,Location>
        {           
            private final ProgressDialog dialog = new ProgressDialog(MainActivity.this);
            private int error = 0;          
            private Activity actividad;     
            private int procesoTerminado=0;

            public findPosicionTask(Activity actividad)
            {           
                this.actividad = actividad;
            }

            @Override
            protected void onPreExecute() 
            {                                                       
                if (!LocationSettingsManager.isLocationServiceAvaliable(getApplicationContext()))
                {                                                   
                    cancel(true);
                }           
                else
                {
                    this.dialog.setMessage(getString(R.string.obteniendoPoisicion));
                    this.dialog.show();
                }

            }

            @Override
            protected Location doInBackground(Void... params)
            {                                   
                if (this.error==0)
                {                           
                    try 
                    {
                        Looper.prepare();
                        MyLocationManager.LocationResult locationResult = new MyLocationManager.LocationResult(){

                            @Override
                            public void gotLocation(Location location) {                                

                                if (location!=null)
                                {   
                                    LocationSingleton posicionSingleton = (LocationSingleton)getApplication();
                                    posicionSingleton.setMiPoscion(location);
                                    posicionSingleton.setFecha(new Date());
                                    procesoTerminado=1;
                                    onPostExecute(location);                                    
                                }
                                else
                                {
                                    procesoTerminado=1;
                                    onPostExecute(location);
                                }                           
                            }           
                        };

                        MyLocationManager myLocation = new MyLocationManager();
                        if (!myLocation.getLocation(getApplicationContext(), locationResult))
                        {                       
                        }                                                 

                    }
                    catch (Exception e) 
                    {                   
                        error=2;
                        cancel(true);
                        return null;
                    }
                }

                return null;                
            }            

            @Override
            protected void onPostExecute(Location posicion) 
            {                                               
                if (procesoTerminado==1)
                {                                       
                    if (this.dialog.isShowing())
                    {
                        this.dialog.dismiss();
                    }

                    if (error==0)
                    {               
                        if (posicion==null)
                        {                       
                            MessageManager.muestraMensaje(this.actividad, R.string.noSeObtuvoLocalizacion);
                        }
                        else
                        {
                            ArrayList centros = DBFacade.findCentros(getBaseContext());

                            ArrayList<Centro> centrosMasCercanos = DistanciasManager.getCentrosMasCercanos(posicion, centros);

                            Intent i = new Intent(getBaseContext(), CentrosCercanosActivity.class);                                                                         
                            i.putExtra("centrosMasCercanos", centrosMasCercanos);
                            i.putExtra("posicion", posicion);
                            startActivity(i);                                                                                                               
                        }           
                    }
                    else
                    {
                        if (error==2)
                        {   
                            MessageManager.muestraMensaje(this.actividad, R.string.noSeObtuvoLocalizacion);                                                                                                                                                             
                        }
                    }           
                }                           
            }

            @Override
            protected void onCancelled() {
                super.onCancelled();

                if (this.dialog.isShowing())
                {
                    this.dialog.dismiss();
                }

                MessageManager.muestraMensaje(this.actividad, R.string.servicioLocalizacionDesactivado);                                                       
            }                   

        }

And here is my own MyLocationManager Class

public class MyLocationManager {

    Timer timer1;
    LocationManager lm;
    LocationResult locationResult;
    boolean gps_enabled=false;
    boolean network_enabled=false;

    public boolean getLocation(Context context, LocationResult result)
    {
        //I use LocationResult callback class to pass location value from MyLocation to user code.
        locationResult=result;
        if(lm==null)
            lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        //exceptions will be thrown if provider is not permitted.
        try 
        {
            gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }
        catch(Exception ex)
        {           
        }

        try
        {
            network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        }
        catch(Exception ex)
        {
        }

        //don't start listeners if no provider is enabled
        if(!gps_enabled && !network_enabled)
            return false;

        if (gps_enabled)
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
        if (network_enabled)
            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);

        timer1=new Timer();        
        timer1.schedule(new GetLastLocation(), 5000);
        return true;                              
    }

    LocationListener locationListenerGps = new LocationListener() 
    {
        @Override
        public void onLocationChanged(Location location) {

            Location gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);                           

            long diffInMs = (new Date().getTime()/60000) - (gps_loc.getTime()/60000);

            if (diffInMs<1)
            {
                if (((int)gps_loc.getAccuracy())<=3000)
                {
                    lm.removeUpdates(this);
                    lm.removeUpdates(locationListenerNetwork);
                    timer1.cancel();                
                    locationResult.gotLocation(gps_loc);
                    Looper.loop();
                    return;
                }
            }

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

    LocationListener locationListenerNetwork = new LocationListener() 
    {
        @Override
        public void onLocationChanged(Location location) {                                   

            Location net_loc = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);                   

            long diffInMs = (new Date().getTime()/60000) - (net_loc.getTime()/60000);

            if (diffInMs<1)
            {
                if (((int)net_loc.getAccuracy())<=3000)
                {
                    lm.removeUpdates(this);
                    lm.removeUpdates(locationListenerGps);
                    timer1.cancel();                
                    locationResult.gotLocation(net_loc);
                    Looper.loop();
                    return;
                }
            }

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

    class GetLastLocation extends TimerTask 
    {
        @Override
        public void run() 
        {
            Looper.prepare();           

             lm.removeUpdates(locationListenerGps);
             lm.removeUpdates(locationListenerNetwork);

             Location net_loc=null;
             Location gps_loc=null;
             Location finalLocation=null;

             if(gps_enabled)
                 gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
             if(network_enabled)
                 net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);                                                                      

             long diffInMs;

             if (gps_loc!=null)
             {
                diffInMs = (new Date().getTime()/60000) - (gps_loc.getTime()/60000);

                 if (diffInMs>1)
                    gps_loc=null;               
             }

             if (net_loc!=null)
             {
                 diffInMs = (new Date().getTime()/60000) - (net_loc.getTime()/60000);

                 if (diffInMs>1)
                    net_loc=null;
             }             

             if (gps_loc!=null || net_loc!=null)
             {                               
                int gpsAccuracy = 1000000;
                int netAccuracy = 1000000;

                if (gps_loc!=null)
                    gpsAccuracy = (int)gps_loc.getAccuracy();

                if (net_loc!=null)
                    netAccuracy = (int)net_loc.getAccuracy();

                if (netAccuracy<gpsAccuracy)
                    finalLocation=net_loc;
                else
                    finalLocation=gps_loc;

                if (((int)finalLocation.getAccuracy())<=3000)
                {                
                    locationResult.gotLocation(finalLocation);
                    Looper.loop();
                    return;
                }
                else
                {
                    locationResult.gotLocation(null);
                    Looper.loop();
                    return;
                }

             }
             else
             {
                 locationResult.gotLocation(null);
                 Looper.loop();
                 return;                 
             }

        }//fin del run

    }//fin de la clase GetLastLocation

    public static abstract class LocationResult{
        public abstract void gotLocation(Location location);      
    }

}

As you can see on the OnPreExecute method of the AsyncTask y check if location providers are enabled or not like that:

public static boolean isLocationServiceAvaliable(Context mContext) 
    {
        String locationProviders = Settings.Secure.getString(mContext.getContentResolver(),Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

        if (locationProviders.trim().equals(""))
            return false;
        else
            return true;

    }

Well, most of the times the app works perfectly but some cases (Wich are turning me mad), the method "isLocationServiceAvaliable" returns false so the app says that the location providers are not enabled.

this happens even when the location providers are enabled on the device settings and what is more extrange is that If the users clicks on Button One the app show the google maps with the users Location propertly.

So how Google Maps Api V2 gets device location even when providers are not enabled at the moment?? Is there any way to use the same method as it seems that is much more efficient that the one I use on MyLocationManager class.

Thak u very much for reading my post

Was it helpful?

Solution

Google is using the location provider from googleplayservices. It's super efficient and super easy to code. The first location (last known location) comes in really fast.

There's none of the complex checking for providers it just works with what is turned on. Meaning if the user somehow turns on the gps. The googleplayservices provider will start using it.

These are the steps.

  1. create
  2. connect
  3. request for locations
  4. wait for the onlocation to fire

github MapMover the complete.java code here

locationClient = new LocationClient(activity, this, this);
locationClient.connect();

public void onConnected(Bundle dataBundle) {
    // Create a new global location parameters object
    locationRequest = LocationRequest.create();
    // Set the update interval 70% of the interval
    // this is to make sure we have an updated location
    // when the animation completes
    locationInterval = (long) (interval * .70);
    locationRequest.setInterval(locationInterval);
    locationRequest.setFastestInterval(locationInterval);
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationClient.requestLocationUpdates(locationRequest, this);
}

@Override
public void onLocationChanged(Location location) {
            // here you have a location to do with what you will
}

github MapMover the complete.java code here

OTHER TIPS

I have implemented the same thing in my application, I first try to do it using Google maps by :

  1. mGoogleMap.setMyLocationEnabled(true);

  2. mGoogleMap.getMyLocation();

But the problem is it mostly return zero as we don't know that after how long the Google maps get the location after loading the map.

Then I use Google play services but it also return zero sometimes. Finally I tried to use Google Play services and Location Poller Class which works for me better, I must not say perfectly but better than only using Google play services here is the link hope it helps.

Also here is a very simple example for LocationManager class if you are looking for that here is the link

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top