In my current application, the location data that is returned is outdated. I use a method that gets updates based on min time/distance between updates. However, lets say i turn my phone off, drive to another city, and then turn the phone back on. In this case my GPS reading will be off. How do i force the app to get the current location NOT getLastKnownLocation().
I have heard of a locationListener but everything i have read is very vague on how to use it.
Here is the code I have just in case this clarifies whats going on:
public class GPSHandling extends Service implements LocationListener{
private final Context myContext;
//flag for gps status
public boolean isGPSEnabled = false;
//flag for network status
public boolean isNetworkEnabled = false;
// used to determine if i can get a location either by network or GPS
public boolean canGetLocation = false;
Location myloc;
public double latitude;
public double longitude;
public int MIN_TIME_BTWN_UPDATE = 500*10; // in miliseconds, so 10sec
public int MIN_DISTANCE_BTWN_UPDATE = 10; // in meters
protected LocationManager locManager;
public GPSHandling(Context context){
this.myContext= context;
getLocation();
}
public Location getLocation(){
try{
locManager =(LocationManager) myContext.getSystemService(LOCATION_SERVICE);
// now get gps status
isGPSEnabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
//now the same for network
isNetworkEnabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled){
// do nothing since neither provider are enabled (this.cangetlocation = false but its already set to that by default)
}
else{
this.canGetLocation=true;
//first get values for locManager from the network provider. send parameters telling when to update
if(isNetworkEnabled){
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BTWN_UPDATE, MIN_DISTANCE_BTWN_UPDATE, this);
Log.d("provider", "network");
//if we are successful, then check to see if the location manager isnt null. attempt to get the current location from the manager
if (locManager != null){
myloc =locManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// after getting the current location, attempt to get the latitude and longitude values
if (myloc != null){
latitude = myloc.getLatitude();
longitude = myloc.getLongitude();
}
}
}
//now get values for locManager from the GPS provider. send parameters telling when to update
if(isGPSEnabled){
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BTWN_UPDATE, MIN_DISTANCE_BTWN_UPDATE, this);
Log.d("provider", "GPS");
}
//if we are successful, then check to see if the location manager isnt null. attempt to get the current location from the manager
if(locManager!= null){
myloc = locManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
// after getting the current location, attempt to get the latitude and longitude values
if(myloc != null){
latitude = myloc.getLatitude();
longitude = myloc.getLongitude();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return myloc;
}
// get an update of the current latitude by using this class method
public double getMyLatitude(){
if (myloc!= null){
latitude = myloc.getLatitude();
}
return latitude;
}
//get an update of the current longitude by using this class method
public double getMyLongitude(){
if (myloc != null ){
longitude = myloc.getLongitude();
}
return longitude;
}
// use this method to find if app can get the current location
public boolean canGetMyLocation(){
return this.canGetLocation;
}
public void showGPSDialog(){
AlertDialog.Builder alert = new AlertDialog.Builder(myContext);
// Setting Dialog Title
alert.setTitle("Location Setting");
// Setting Dialog Message
alert.setMessage("GPS is not enabled, do you want to enable this now in the settins menue?");
// setting icon to dialog
//alert.setIcon(R.drawable.)
// on pressing settings button
alert.setPositiveButton("Settins", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
myContext.startActivity(intent);
}
});
//on pressing cancel button
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// showing the alert dialog
alert.show();
}
public void stopUsingGPS(){
if(locManager !=null){
locManager.removeUpdates(GPSHandling.this);
}
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
You are already half using LocationListener in your code. You just didn't fully implement the code.
This method bellow is empty in your code:
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
This is the method that is called everytime GPS produces an location update.
You should complete it doing something like:
#Override
public void onLocationChanged(Location location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
Regards.
Did you read the corresponding docs?
Look at Location API and LocationListener for the start.
LocationListener is actually pretty straight-forward to use and the only (clean) way to reliably retrieve the device's location.
Location data usually take up to 30 seconds to fully warm up. As you asked for the getLastKnownLocation() you, indeed, could have a outdated location returned.
Read more about it at Location strategies by Google itself.
Related
Here, GPS takes half an hour or more (time) to get the current location coordinates.
How can I use GPS from GPS_SATELLITES and GPS _NETWORK_PROVIDERS
simultaneously in the same context and get the value of the recent
GPS?
public class ImageFile extends Activity{
LocationListener listner;
Location location;
LocationManager locationManager ;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
private static final long MIN_TIME_BW_UPDATES = 1000 * 10 * 1; // 1 minute
#Override
protected void onCreate(final Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.branchreport_layout);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listner = new MyLocationListner();
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(isGPSEnabled==false&&isNetworkEnabled==false)
{
showSettingsAlert();
}
if (isGPSEnabled)
{
progress = ProgressDialog.show(this, "GPS",
"Fetching latitude and longitude...", true);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES,listner);
}
else if (isNetworkEnabled)
{
progress = ProgressDialog.show(this, "GPS",
"Fetching latitude and longitude...", true);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES,listner);
}
public class MyLocationListner implements LocationListener {
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
x = location.getLatitude();
y = location.getLongitude();
if((x!=0) && (y!=0))
{
progress.dismiss();
locationManager.removeUpdates(listner);
Geocoder gCoder = new Geocoder(ImageFile.this);
try {
addresses = gCoder.getFromLocation(x, y, 1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (addresses != null && addresses.size() > 0) {
Log.d("TestTag", "Locality: " + addresses.get(0).getLocality()+"getAddressLine"+addresses.get(0).getAddressLine(0)+",getAdminArea"+addresses.get(0).getAdminArea()+",getSubLocality"+addresses.get(0).getSubLocality());
}
}
}
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
}
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
}
GPS is always slow, so i'll suggest to use Android Location API using Google Play Services.
Steps
First check for availability of Google Play Services by calling in onResume() of the Activity
Once play services are available on the device, build the GoogleApiClient.
Connect to google api client by calling mGoogleApiClient.connect() in onStart() method. By calling this, onConnectionFailed(), onConnected() and onConnectionSuspended() (GooglePlayServiceListeners) will be triggered depending upon the connection status.
Once google api is successfully connected, displayLocation() should be called in onConnected() method to get the current location.
This is how we build the GoogleApiClient
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
displayLocation()
private void displayLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
lblLocation.setText(latitude + ", " + longitude);
} else {
lblLocation
.setText("(Couldn't get the location. Make sure location is enabled on the device)");
}
}
A perfect explanation of the above methods and steps can be found here .also check the official documentation
in my application i have a button that start counting the time how long the user has been in the same location. and i want the app stop the timer counting if the user goes out from the area he started so i made a class that give me the current location (LAT,LONG,PLACE NAME) and i don't know how to use the "onLocationChanged" and Should I use it? or something else for what i need?
public class MapCurrentPlace extends Service implements LocationListener {
private final Context mContext;
public static final String MY_TEMP = "sharedFile";
SharedPreferences setting;
SharedPreferences.Editor editor;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
Location location; // location
double latitude; // latitude
double longitude; // longitude
String placeName = "";
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 500; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public MapCurrentPlace(Context context) {
this.mContext = context;
getLocation();
}
public String getPlaceName(){
Geocoder gc = new Geocoder(mContext);
try {
List<Address> list = gc.getFromLocation(latitude, longitude, 1);
if(list.size()>0){
String city = list.get(0).getLocality();
String street = list.get(0).getAddressLine(0);
placeName = city+", "+street+"";
}
} catch (IOException e) {
placeName = "";
e.printStackTrace();
}
return placeName;
}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(Context.LOCATION_SERVICE);
// getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isGPSEnabled) {
// no network provider is enabled
this.canGetLocation = false;
return null;
} else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES,0, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MIN_TIME_BW_UPDATES,0, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
/**
* Stop using GPS listener
* Calling this function will stop using GPS in your app
* */
public void stopUsingGPS(){
if(locationManager != null){
locationManager.removeUpdates(MapCurrentPlace.this);
}
}
/**
* Function to get latitude
* */
public double getLatitude(){
if(location != null){
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
* #return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}
public boolean getIsNetworkEnabled() {
return this.isNetworkEnabled;
}
/**
* Function to show settings alert dialog
* On pressing Settings button will lauch Settings Options
* */
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS OFF");
// Setting Dialog Message
alertDialog.setMessage("Allow GPS");
// On pressing Settings button
alertDialog.setPositiveButton("SETTING", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
#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 intent) {
// TODO Auto-generated method stub
return null;
}
}
locationManager.getLastKnownLocation
this one returns last know location fix. This might be kind of old if no apps requested location for a while.
Location updates will be fired each time device location was changed.
So it's up to you what to use. If you want to get up-to date location, use location updates. But bear in mind that location updated drain battery.
Also you might want to look into Geofences: http://developer.android.com/training/location/geofencing.html
The onLocationChanged method will be called when the current location is changed. This is a default method called because you have implemented the LocationListener.
I do not know how you are implementing the timer (perhaps an AsyncTask so your app can do other stuff as well - http://developer.android.com/reference/android/os/AsyncTask.html), but then in the OnLocationChanged method add some call to your timer variable to stop.
OnLocationChanged will trigger whenever the device travels the minDistance parameter of requestLocationUpdates, from the last relevant location of your device (i.e. since the event last triggered).
Of course, the trigger rate also takes into account the minTime parameter, which should be used to prevent saturation of the calls, and thus saving battery/data usage (e.g. car travelling too fast for your minDistance).
As you have it now (you supplied an inline 0 to the call), you need to manually check if the most recent OnLocationChanged data is a relevant change to your scenario.
It's much more transparent to just use that parameter as the system tries to make it hardware-independent and battery-efficient. You already have a MIN_DISTANCE_CHANGE_FOR_UPDATES in your boilerplate code, just add it as a parameter instead of '0' as you have, and set it to the number of meters you need:
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 30; //30 meters
//...
//at some point while your service/activity is running
locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES,
this);
//...
#Override
public void onLocationChanged(Location currentLocation) {
//triggered when System asserts a 30 meter variation from last relevant location
doMyStuff();
}
Side note: remember most GPS hardware has issues with very fine locations, especially at sub-10m.
You can also keep the value at 0, receive updates at the granularity the hardware updates itself, and do the checks manually - just use the Location parameter supplied with the event and do your own checks to decide, which is pretty much a geo-fencing check:
Location lastRelevantLocation;
#Override
public void onLocationChanged(Location currentLocation) {
// called when the listener is notified with a location update from the GPS
// hardware update rate might call this more than your CPU should handle
if(checkOutsidePerimeter(location)){
lastRelevantLocation = currentLocation;
doMyStuff();
}
}
Remember minTime if you want to keep tabs on granularity.
All I wanted to do is to get the current location using GPS before I move to next activity. So I disabled the buttons that takes me to next activities. The buttons are enabled only after getting a location using the GPS. The following code runs perfectly. But I found one bug..
Last time I used the app it was quite right. Then I moved to my University. There I launched the app and then moved to next activity as location was retrieved by then. I got the location of my home which is about 10 kilometers away. Then after closing the application, I launched it once again and this time it retrieved the correct location.
Well, this is happening because of the line below:
location = locationManagerAsync.getLastKnownLocation(providerAsync);
My app is retrieving the last location and enabling the buttons. But it is able to keep the current location to use for the next time I launch the app. As a result, on the second attempt, the location is retrieved perfectly.
I used a code from a question on stackoverflow.com which is given below.
private class MyLocationTracker extends AsyncTask<Void, Void, Void> implements LocationListener {
private Context ContextAsync;
public MyLocationTracker (Context context){
this.ContextAsync = context;
}
Dialog progress;
private String providerAsync;
private LocationManager locationManagerAsync;
double latAsync=0.0;
double lonAsync=0.0;
Location location;
#Override
protected void onPreExecute() {
super.onPreExecute();
progress = ProgressDialog.show(ContextAsync, "Loading location", "Please wait...");
}
#Override
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
locationManagerAsync = (LocationManager) ContextAsync.getSystemService(ContextAsync.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
providerAsync = locationManagerAsync.getBestProvider(criteria, false);
if (locationManagerAsync.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
providerAsync = LocationManager.GPS_PROVIDER;
} else if (locationManagerAsync.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
providerAsync = LocationManager.NETWORK_PROVIDER;
} else if (locationManagerAsync.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)) {
providerAsync = LocationManager.PASSIVE_PROVIDER;
//Toast.makeText(ContextAsync, "Switch On Data Connection!!!!", Toast.LENGTH_LONG).show();
}
location = locationManagerAsync.getLastKnownLocation(providerAsync);
// Initialize the location fields
if (location != null) {
// System.out.println("Provider " + provider + " has been selected.");
latAsync = location.getLatitude();
lonAsync = location.getLongitude();
} else {
//Toast.makeText(ContextAsync, " Location not available", Toast.LENGTH_SHORT).show();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
progress.dismiss();
onLocationChanged(location);
Log.v("latAsync_lonAsync",latAsync+"_"+lonAsync);
myCurrentLatitude = latAsync;
myCurrentLongitude = lonAsync;
// the buttons that were disabled in the onCreate() method
police.setEnabled(true);
medical.setEnabled(true);
fireService.setEnabled(true);
cityCorporation.setEnabled(true);
telePhnCall.setEnabled(true);
getRoute.setEnabled(true);
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
locationManagerAsync.requestLocationUpdates(providerAsync, 0, 0, this);
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
And this is the line that I am using to call the AsyncTask from the Oncreate() method..
new MyLocationTracker(TypeOfEmergency.this).execute();
Now the problem is, I do not want the last location to be retrieved and stored in the variables. I tried the code after removing the line
location = locationManagerAsync.getLastKnownLocation(providerAsync);
But the app crashes in that case. Need a quick fix.
Here is the error log :: (Please have a look to the comments before having a look to the error log)
With the code something is basically wrong: the single line of code in onLocationChanged
locationManagerAsync.requestLocationUpdates(providerAsync, 0, 0, this);
needs to be called at the end of doInBackground (which does not need to be done in background). This line of code requests location updates from the provider (e.g. the GPS provider). When a new location is avaiable the onLocationChanged of your location listener is called (which is MyLocationTracker in your example due to the this in the line above. in onLocationChanged you need to react to a new location by enabling or disabling the functionality, you mentioned in your question.
The call to getLastKnownLocation does exectly what the name suggests: It returns the last known position, which may be quite old.
I am doing application, we are in inside the room or not. I have to stored 4 corner values means doing polygon. But i cant get exactly value in the same position, it gets different values in the same position. How it get solution this problem??
Code:
MainActivity.java
public class MainActivity extends Activity {
Button btnShowLocation;
TextView tvLat;
TextView tvLang;
TextView tvInsideRoom;
dbHandler myDbHelper;
// GPSTracker class
GPSTracker gps;
Handler mHandler1;
tvInsideRoom = (TextView)findViewById(R.id.insideRoom);
btnShow = (Button) findViewById(R.id.btnShow);
// show location button click event
btnShow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
mHandler1 = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(100);
mHandler1.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// creating GPS Class object
GPSTracker gps = new GPSTracker (MainActivity.this);
// check if GPS location have some values
if (gps.canGetLocation()) {
double currentlat = gps.getLatitude();
double currentlong = gps.getLongitude();
tvLat = (TextView)findViewById(R.id.lat);
tvLang = (TextView)findViewById(R.id.lang);
tvLat.setText(""+currentlat);
tvLang.setText(""+currentlong);
boolean boolFlag = myDbHelper.isInsideRoom(currentlat,currentlong);
tvInsideRoom.setText("");
if(boolFlag)
tvInsideRoom.setText("You are in inside Room");
else
tvInsideRoom.setText(""+boolFlag);
} else {
// no current location
gps.showSettingsAlert();
}
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
}
}); }
GPSTracker.java
public class GPSTracker extends Service implements LocationListener {
private final Context mContext;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
Location location; // location
double latitude; // latitude
double longitude; // longitude
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public GPSTracker(Context context) {
this.mContext = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext.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);
if (location != null) {
Log.d("Accuracy1 := ", ""+location.getAccuracy());
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// 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);
if (location != null) {
Log.d("Accuracy2 := ", ""+location.getAccuracy());
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
/**
* 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
return latitude;
}
/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
* #return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog
* On pressing Settings button will lauch Settings Options
* */
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
#Override
public void onLocationChanged(Location location) {
this.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;
}}
The accuracy of location tracking can vary vastly. What you are trying to achieve will never work because of an insufficient accuracy. Especially inside a room, but even with GPS.
Depending on where you are, network cell-towers, wifi or GPS will be used to determine the current location, and all with a different accuracy. Even outside, it usually takes a few seconds until you get a GPS fix.
Use getAccuracy() to check if your location is somewhat useful with the current fix.
When my map activity is called I make a call in the onCreate to addUserMapPoint. This function contains two instances where I try to get the location information using myOverlay.getMyLocation. On the initial load of this activity the result of the first attempt returns a null GeoPoint and after the main UI thread completes the second attempt located in the listener thread of myOverlay.runOnFirstFix(new Runnable()… is call after a second and does contain a GeoPoint that does contain a lat and lon. The call inside this listener function does appear to put the dot on the map and the line mapController.animateTo(gp) does move the map to my location. My app has a refresh button that when clicked fires off this activity again. I need the lat and lon in order to fetch location data from another service. After the refresh, the second time through the map activity code I was expecting the first call to myOverlay.getMyLocation() would now be able to get the GeoPoint, but it is still null.
If I’m not able to get the GeoPoint by this first call to myOverlay.getMyLocation then how can I pass the lat and lon value from the second call found in the myOverlay.runOnFirstFix(new Runnable()… thread. You will notice that I have been trying to add the lat and lon to MyApp which is helper bean class but the lat and lon in this class is null even after the refresh. If I manually set a lat and lon manually in the addUserMapPoint function the first time the activity is accessed these values are retained. I’m guessing that this is because it is being set on the main UI thread.
public class MapActivity extends com.google.android.maps.MapActivity {
private MapView mapView = null;
private MapController mapController = null;
private MyLocationOverlay myOverlay = null;
public static MyApp app;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
app = (MyApp) getApplicationContext();
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapController = mapView.getController();
List<Overlay> mapOverlays = mapView.getOverlays();
mapOverlays.clear();
addUserMapPoint(mapView);
if (!app.isLocServOff()) {
//map other points – service call to get items from our service near lat and lon
addOtherMapPoints(mapOverlays);
} else {
Toast.makeText(app.getApplicationContext(),"Current location could not be found.",Toast.LENGTH_LONG).show();
}
}
private void addUserMapPoint(MapView mapView){
myOverlay = new MyLocationOverlay(app.getApplicationContext(), mapView);
myOverlay.disableCompass();
myOverlay.enableMyLocation();
if(app.getMyLat()==null||app.getMyLon()==null){
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
}else{
app.setLocServOff(true);
}
}
myOverlay.runOnFirstFix(new Runnable() {
public void run() {
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
mapController.animateTo(gp);
}else{
app.setLocServOff(true);
}
}
});
mapView.getOverlays().add(myOverlay);
}
}
Your help is being requested for the following question.
How can I get a GeoPoint that contains a lat and lon in the main UI thread or how can I pass these values from GeoPoint I am able to get from the myOverlay.runOnFirstFix(new Runnable()… thread?
If you are going to suggest that I use Handler or runOnUiThread please provide code example that passes the lat and lon back to something that can be used by the main UI thread/map view. I have tried things like the following code that did not produce the desired outcome. I was able to get the toast message to show up, but was not able to get the lat and lon passed in a way I could use.
final Handler handler = new Handler();
myOverlay.runOnFirstFix(new Runnable() {
#Override public void run() {
handler.post(new Runnable() {
#Override public void run() {
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
mapController.animateTo(gp);
}else{
app.setLocServOff(true);
}
//Toast.makeText(getApplicationContext(),"wowoowowowoowoowowow",Toast.LENGTH_LONG).show();
}
});
}
});
I've also used code like the following to get the lat and lon and it works, but because the current location would sometimes be a different lat and lon than whas was being returned becuase for example I could not get a gps signal but yet an old value was returned. I added checks to see if the lat/lon data was older than 2 minutes, but I still could not match up the most recent lat and lon with that that is returned by myOverlay.getMyLocation.
LocationManager locMgr = (LocationManager)appcontext.getSystemService(Context.LOCATION_SERVICE);
MyLocationListener locLstnr = new MyLocationListener();
//fetch current location for current location
locMgr.requestSingleUpdate(LocationManager.GPS_PROVIDER, locLstnr, appcontext.getMainLooper());
Bellow you can find some examples on how to get the current location in the UI thread, but first of all, some background information.
GPS may take some time (15 seconds to 1 minute) to get the first fix after the request for new location is made. This is the reason you your first attempt to get it from myOverlay fails, and only after the first fix you can get the value.
During this blackout period you can use getLastKnownLocation() to get the last good known GPS location if you are in a hurry. If not availble it returns null
The code:
Last Known Location
LocationManager locMgr=(LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
Location loc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(loc != null){
//we have a valid location. Check location date
}
Requesting a Single Location Update
LocationManager locMgr=(LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
locMgr.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListener, appcontext.getMainLooper);
Requesting a Continuous Location Update
LocationManager locMgr = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
//use 0 for minDistance and minDistance between updates if you need the maximum update frequency.
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, minDistance, minTime, locationListener);
Location Listener for Single and Continuous position update
This is the last piece of code, and is the place where you get the new fresh locations requested above.
When a new location that match your request critirea defined above is retrieved by GPS, this listener is immediately called, unless you device is busy doing something else that can't be interrupted (i.e. callback is on a paused thread or that hit a lock).
From within the onLocationChanged() you can set any class level filed as appropriate. If you registered the listener from the UI thread, then this will be running running on the UI.
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location fix) {
fix.setTime(fix.getTime() + timeZoneOffset); //Add Timezone offset if needed
//here you have a fresh new location in fix...
//You can set the value of any class level field from here
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
Regards.
handler.post(new Runnable() {
#Override public void run() {
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
// HERE WE HAVE VALID gp VALUE AND WE NEED TO SHARE IT
mapController.animateTo(gp);
}else{
app.setLocServOff(true);
}
}
});
I think that your app.set/get|MyLat/Lon not working because you call them from different threads. To fix it synchronize set and get methods for MyLat/Long. (create Object for synchronization and sync on it)
Or if you like your way with handler this should work:
final Handler handler = new Handler(); // BE SURE TO RUN THIS LINE ON UI THREAD
...
myOverlay.runOnFirstFix(new Runnable() {
#Override public void run() {
// THIS PART WORKS AS BEFORE
final GeoPoint gp = myOverlay.getMyLocation();
mapController.animateTo(gp);
...
// AND THIS RUNNABLE TO UPDATE MyLat/MyLong FROM UI THREAD
handler.post(new Runnable() {
#Override public void run() {
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
});
}
});
Some of the most important points you must take into account while seeking Device's location are:
Satellite GPS fix is not guaranteed to be received in adequate amount of time. E.g. the device is inside a building / not under open sky.
Make sure the satellite GPS listeners are not kept active for long. Keeping the listener ON will imply keeping the GPS radio on all the time making it the biggest battery drain reason.
In the below code example, the poll method in LinkedBlockingQueue doesn't return until either a specified time interval is over or a Location is queued in.
Use something like the below to get the current Location:
Location getCurrentLocation() {
long startmillis = 0;
LinkedBlockingQueue<Location> mQueue = new LinkedBlockingQueue<Location>();
try{
long millisSinceLastCollection = System.currentTimeMillis() - startmillis;
startmillis = System.currentTimeMillis();
mQueue.clear();
// Register for Satellite GPS listener as well as Network GPS listener.
registerGPSListeners();
// Wait for a maximum of one minutes for a fix
Location firstfix = mQueue.poll(1, TimeUnit.MINUTES);
if(firstfix != null && firstfix.getProvider().equals(LocationManager.GPS_PROVIDER)) {
return firstfix;
}
long elapsedmillis = System.currentTimeMillis() - startmillis;
long remainingmillis = ONE_MINUTE_IN_MS - elapsedmillis;
if (remainingmillis <= 0){
return firstfix;
}
Location secondfix = mQueue.poll(remainingmillis, TimeUnit.MILLISECONDS);
if(secondfix != null && secondfix.getProvider().equals(LocationManager.GPS_PROVIDER)) {
return secondfix;
}
/*
* In case we receive fix only from Network provider, return it.
*/
if(firstfix != null && firstfix.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
return firstfix;
}
} catch(Exception e){
Logger.e("GPS: Exception while listening for the current location", e);
} finally {
Logger.i("GPS: Unsubscribing from any existing GPS listeners");
unregisterGPSListeners();
}
}
// GPS issue fix edit.
private void registerGPSListeners() {
LocationManager locationManager = (LocationManager)AirWatchApp.getAppContext().getSystemService(Context.LOCATION_SERVICE);
if(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 30000, 100, oneShotNetworkGPSLocationListener, MyAppApp.getAppContext().getMainLooper());
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 100, oneShotSatelliteGPSLocationListener, AirWatchApp.getAppContext().getMainLooper());
}
}
private void unregisterGPSListeners(){
final LocationManager locationManager = (LocationManager)MyApp.getAppContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(oneShotSatelliteGPSLocationListener);
locationManager.removeUpdates(oneShotNetworkGPSLocationListener);
}
//One shot location listener
protected LocationListener oneShotSatelliteGPSLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
try {
mQueue.put(location);
} catch (InterruptedException e) {
Logger.e("Exception in putting new Location to the queue", e);
}
Logger.d("GPS: Location received from Satellite GPS Provider");
unregisterGPSListeners();
}
public void onProviderDisabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
};
//One shot location listener
protected LocationListener oneShotNetworkGPSLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
try {
mQueue.put(location);
} catch (InterruptedException e) {
Logger.e("Exception in putting new Location to the queue", e);
}
Logger.d("GPS: Location received from Network GPS Provider");
// Stop Listener for one-shot location fix from Network GPS provider.
final LocationManager locationManager = (LocationManager)AirWatchApp.getAppContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(oneShotNetworkGPSLocationListener);
Logger.d("GPS: Unsubscribed the network location listener.");
}
public void onProviderDisabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
};
Android modifies the user interface and handles input events from one single user interface thread(main thread).
If the programmer does not use any concurrency constructs, all code of an Android application runs in this thread.
GPS is the best way to determine a user's location, but pinging a global positioning satellite too much will quickly drain a mobile device's battery, take long time to get user location and this method doesn't always work indoors. You are not getting your location in first attempt that's why you are getting null over there.
Android's Network Location Provider figures out a user's location based on cell tower and Wi-Fi signals. It not only uses less battery power than GPS, but it's also faster and it works whether the user is outside or inside.
I am giving my Working Code below that show progress dialog, listen for user's location & after getting location show user's location overlay on Google-map
I assume that you have give below permissions in your Menifest file
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
My main class
public class MyLocationOnMap extends MapActivity {
private MapView mapView;
private MyLocationOverlay itemizedoverlay;
private LocationManager locationManager;
private String provider;
private MyLocationListener locationListener;
MyBroadCastreceiver myBroadCastreceiver;
/**
* My current Location <i>longitude</i>.
*/
static int longitude;
/**
* My current Location <i>latitude</i>.
*/
static int latitude;
/**
*My progress indicator.
*/
ProgressDialog loadingDialog;
public static final String INTENT_FILTER_TAG="my location broadcast receiver";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_location_on_map);
loadingDialog = new ProgressDialog(this);
loadingDialog.setTitle("Hot Spots!");
loadingDialog.setMessage("Please wait ...");
loadingDialog.setIndeterminate(true);
loadingDialog.setCancelable(false);
loadingDialog.show();
// Configure the Map
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapView.setStreetView(true);
/**
* Get your location manager and Location Listener...
*/
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener=new MyLocationListener();
myBroadCastreceiver = new MyBroadCastreceiver();
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.i("GPS_Enabled", "GPS enable! listening for gps location.");
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, locationListener);
registerReceiver(myBroadCastreceiver, new IntentFilter(INTENT_FILTER_TAG));
} else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.i("Network_Enabled", "Network enable! listening for Network location.");
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, locationListener);
registerReceiver(myBroadCastreceiver, new IntentFilter(INTENT_FILTER_TAG));
} else {
loadingDialog.dismiss();
Toast.makeText(this, "No Provider enable!", Toast.LENGTH_LONG).show();
}
}//End of onCreate......
/**
* My BroadCast Receiver, that is called when i get the location of user.
* #author Rupesh Yadav.
*
*/
class MyBroadCastreceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//Remove location update when you get user`s location very first time.
locationManager.removeUpdates(locationListener);
//Remove the broadcast listener that update my location on map.
unregisterReceiver(myBroadCastreceiver);
GeoPoint point = new GeoPoint(latitude, longitude);
mapView.getController().animateTo(point);
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = MyLocationOnMap.this.getResources().getDrawable(R.drawable.hs_mapoverlay);
itemizedoverlay = new MyLocationOverlay(drawable, MyLocationOnMap.this);
OverlayItem overlayitem = new OverlayItem(point, "Hello!", "My Current Location :)");
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
loadingDialog.dismiss();
}
}
/**
* My Location listener...
*/
class MyLocationListener implements LocationListener{
#Override
public void onLocationChanged(Location location) {
latitude=(int) ((location.getLatitude())*1E6);
longitude=(int) ((location.getLongitude())*1E6);
//Send broadcast to update my location.
Intent sendLocationIntent=new Intent(INTENT_FILTER_TAG);
sendBroadcast(sendLocationIntent);
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
MyLocationOverlay class
public class MyLocationOverlay extends ItemizedOverlay<OverlayItem> {
Context mContext;
private ArrayList<OverlayItem> hsOverlays = new ArrayList<OverlayItem>();
public MyLocationOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
// TODO Auto-generated constructor stub
}
public MyLocationOverlay(Drawable defaultMarker, Context context) {
super(boundCenterBottom(defaultMarker));
mContext = context;
}
#Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return hsOverlays.get(i);
}
#Override
public int size() {
// TODO Auto-generated method stub
return hsOverlays.size();
}
/**
* add new OverlayItem objects to map OverlayItem ArrayList.
*
* #param overlay
*/
public void addOverlay(OverlayItem overlay) {
hsOverlays.add(overlay);
populate();
}
/**
* Called when user clicks on map overlay.
*/
#Override
protected boolean onTap(int index) {
// TODO Auto-generated method stub
// return super.onTap(index);
OverlayItem item = hsOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
You can modify the Location Listener & Broadcasr Receiver according to your need.
I hope this will solve your problem.
Best regards!
I have used this class for detecting my lat & lon:
Hope this is useful for you too.
Example how to use:
GPSUtility.getInstance(Context).getLatitude();
GPSUtility.getInstance(CamPhotoModeAct.this).getLongitude()
public class GPSUtility {
public static final String TAG = "GPSUtility";
private Context ctx;
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled=false;
boolean network_enabled=false;
private double latitude;
private double longitude;
private static SharedPreferences SHARED_PREF;
private static SharedPreferences.Editor EDITOR_SHARED_PREF;
private static GPSUtility this_instance;
public GPSUtility(Context ctx){
this.ctx = ctx;
SHARED_PREF = ctx.getSharedPreferences(ConstantsG.SHARED_PREF_FILE, Context.MODE_PRIVATE);
EDITOR_SHARED_PREF = SHARED_PREF.edit();
this.getLocation(innerLocationResult);
}
public static GPSUtility getInstance(Context ctx){
if(this_instance == null)
this_instance = new GPSUtility(ctx);
return this_instance;
}
public static void updateLocation(Context ctx){
GPSUtility.getInstance(ctx);//this writes the latitude and longitude in sharable preference file
}
public double getLatitude(){
String latitudeStr = SHARED_PREF.getString(ConstantsG.KEY_LATITUDE,null);
if(latitudeStr == null){
latitude = 0.0;
}
else{
latitude = Double.parseDouble(latitudeStr);
}
return latitude;
}
public double getLongitude(){
String longitudeStr = SHARED_PREF.getString(ConstantsG.KEY_LONGITUDE,null);
if(longitudeStr == null){
longitude = 0.0;
}
else{
longitude = Double.parseDouble(longitudeStr);
}
return longitude;
}
private void updateWithNewLocation(Location location) {
if (location != null) {
latitude = location.getLatitude();
EDITOR_SHARED_PREF.putString(ConstantsG.KEY_LATITUDE, String.valueOf(latitude) );
longitude = location.getLongitude();
EDITOR_SHARED_PREF.putString(ConstantsG.KEY_LONGITUDE, String.valueOf(longitude));
EDITOR_SHARED_PREF.commit();
}
}
public boolean getLocation(LocationResult result)
{
//I use LocationResult callback class to pass location value from GPSUtility to user code.
locationResult=result;
if(lm==null)
lm = (LocationManager) this.ctx.getSystemService(Context.LOCATION_SERVICE);
//exceptions will be thrown if provider is not permitted.
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
Log.e(TAG, "Exception error: " + ex.getLocalizedMessage(), ex);
}
try {
network_enabled = lm
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
Log.e(TAG, "Exception error: " + ex.getLocalizedMessage(), ex);
}
//Toast.makeText(context, gps_enabled+" "+network_enabled, Toast.LENGTH_LONG).show();
//don't start listeners if no provider is enabled
if(!gps_enabled && !network_enabled){
Toast.makeText(this.ctx, "You should enable gps or be connected to network.", Toast.LENGTH_LONG).show();
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(), 10000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
#Override
public void run() {
//Context context = getClass().getgetApplicationContext();
Location net_loc=null, gps_loc=null;
if(gps_enabled)
gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(network_enabled)
net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//if there are both values use the latest one
if(gps_loc!=null && net_loc!=null){
if(gps_loc.getTime()>net_loc.getTime())
locationResult.gotLocation(gps_loc);
else
locationResult.gotLocation(net_loc);
return;
}
if(gps_loc!=null){
locationResult.gotLocation(gps_loc);
return;
}
if(net_loc!=null){
locationResult.gotLocation(net_loc);
return;
}
locationResult.gotLocation(null);
}
}
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
LocationResult innerLocationResult = new LocationResult() {
#Override
public void gotLocation(Location location) {
updateWithNewLocation(location);
}
};
}