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