I use the following code to get Current Location from a Network provider in my application:
LocationManager mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean network_enabled = mgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(network_enabled){
Location location = mgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
But it gives a location approximately 300-700 meters away from my actual location.
This is expected from a Network provider. But the problem is:
with only this Network provider enabled, and no GPS, I openned Foursquare
application where it shows my current location exactly where I am. Now
when I come back to my application, it shows the accurate current
location or say the same location which Foursquare showed.
Same thing happens with Google apps like Navigator, Maps etc..,
How can this be done? How are other apps able to get the exact location, based on just the Network provider?
Complete Code:
public class MyLocationActivity extends Activity implements LocationListener {
private LocationManager mgr;
private String best;
Location location;
public static double myLocationLatitude;
public static double myLocationLongitude;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
best = mgr.getBestProvider(criteria, true);
location = mgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
dumpLocation(location);
}
public void onLocationChanged(Location location) {
dumpLocation(location);
}
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
protected void onPause() {
super.onPause();
mgr.removeUpdates(this);
}
#Override
protected void onResume() {
super.onResume();
mgr.requestLocationUpdates(best, 15000, 10, this);
}
private void dumpLocation(Location l) {
if (l != null){
myLocationLatitude = l.getLatitude();
myLocationLongitude = l.getLongitude();
}
}
}
Thank You
You are getting just the last known location. You should request location updates from the LocationManager. Use LocationManager.getLocationUpdates.
On your LocationListener on the onLocationChanged(Location location) method, you can check on the Location object, how accurate this location is, like this :
float accuracy=location.getAccuracy();
then, if this Location is accurate enough for you, you can stop receiving location updates from the LocationManager using removeUpdates() , and use the received Location. If the Location is not accurate enough, you can wait for a more precise Location, and stop the updates latter on.
Related
I've been getting current location with GoogleApiClient up until now but I've just noticed that it's much simpler to do it with LocationManager using LocationListener since it can even detect when GPS service was turned on or off by the user.
But I have a problem when getting user's first location after the LocationManager was initialized.
LocationManager has 4 listeners but none of them give you your first location. It does have a onLocationChanged listener but it only activates when you move.
This is how I'm using it:
// Init LocationManager (needed to track if GPS is turned on or not
locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
end of oncreate......
/*
LocationListener (Listening if GPS service is turned on/off)
*/
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderDisabled(String provider) {
}
I've written my custom location manager to check for an update in the user's location every 30 seconds. The code is working fine i.e. I'm receiving updates in user's location. But the problem is that the GPS icon is always visible on the status bar on top. I'm guessing that it should be visible only once in 30 seconds. Is this normal or I'm doing something wrong?
public volatile Double mLatitude = 0.0;
public volatile Double mLongitude = 0.0;
int minTime = 30000;
float minDistance = 0;
MyLocationListener myLocListener = new MyLocationListener();
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setSpeedRequired(false);
String bestProvider = locationManager.getBestProvider(criteria, false);
locationManager.requestSingleUpdate(criteria, myLocListener, null);
locationManager.requestLocationUpdates(bestProvider, minTime, minDistance, myLocListener);
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc)
{
if (loc != null) {
//Do something knowing the location changed by the distance you requested
mLatitude = loc.getLatitude();
mLongitude = loc.getLongitude();
Toast.makeText(mContext, "Location Changed! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
}
#Override
public void onProviderDisabled(String arg0)
{
//Do something here if you would like to know when the provider is disabled by the user
Toast.makeText(mContext, "Provider Disabled! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
#Override
public void onProviderEnabled(String arg0)
{
//Do something here if you would like to know when the provider is enabled by the user
Toast.makeText(mContext, "Provider Enabled! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2)
{
//Do something here if you would like to know when the provider status changes
Toast.makeText(mContext, "Provider Status Changed! "+Double.toString(mLatitude)+" "+Double.toString(mLongitude), Toast.LENGTH_LONG).show();
}
}
As long as 1 or more apps have called requestLocationUpdates for the GPS provider, GPS will stay on. It doesn't turn off between requests. It can't- doing so would cause it to lose satellite lock, which would cause it to have to re-establish. That takes a lot more than 30 seconds sometimes. So GPS will stay on until you unregister for GPS events.
The question is old but still, it would be great to give a better answer.
You need to use a Handler which runs continuously on 5 minutes interval so, you get the location update only once and you release the GPS device, this way your app won't listen to the GPS updates but your handler know when it should be called again to listen the updates.
public static void getLocation(Context context) {
Handler locationHandler = new Handler();
locationHandler.post(new Runnable() {
#Override
public void run() {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// Handle the location update
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}, null);
locationHandler.postDelayed(this, 1000 * 60 * 5);
}
});
}
when used GPS_PROVIDER the application work fine, but when used NETWORK_PROVIDER the application was stopped by force. Why? are my permissions not complete?? please help me by making my code working, thanx
public class My_location extends Activity implements LocationListener {
EditText ET1,ET2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_location);
// Log.i("onCreate_My_location", "begin");
ET1=(EditText)this.findViewById(R.id.editText1);
ET2=(EditText)this.findViewById(R.id.editText2);
ET1.setText("1.0000");
ET2.setText("1.0000");
LocationManager LM1=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
LM1.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,1,this);
//Log.i("onCreate_my_location", "End");
}
#Override
public void onLocationChanged(Location L1) {
// TODO Auto-generated method stub
//Log.i("onLocationChanged",String.valueOf(L1.getLongitude()));
//Log.i("onLocationChanged",String.valueOf(L1.getLatitude()));
//Log.i("onLocationChanged",String.valueOf(L1.getAltitude()));
ET1.setText("C.0000");
ET2.setText("C.0000");
ET1.setText(String.valueOf(L1.getLongitude()));
ET2.setText(String.valueOf(L1.getLatitude()));
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
instead of using specific provider use best provider, which will give you more accuracy in your location
use code given below which will give you location by choosing best provider automatically :
LocationManager LM1=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider=LM1.getBestProvider(criteria, true);
LM1.requestLocationUpdates(provider,0,1,this);
Edit:
for Your Code you Can Check network State before requestLocationUpdates
i think this can avoid the crash :
if(LM1.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
{
LM1.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,1,this);
}
Check whether the network location provider is enabled or not.
try {
network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {
ex.printStackTrace();
}
If the provider is enabled then only you can use that. Also, for location updates using a network provider, I think giving the minDistance value as 1 is meaningless as coarse location is anyway not very accurate. You might want to change that value to 50 or 100 meters.
I have tried to get this code sorted couple of times. Here’s the scenario I have tried so far…
Scenario:
Once the activity is started I want to get the coordinates (long & lat) based on network/gps provider. This should run in background and it should keep checking until long & lat is not null or “0.0”. Thus, I have tried the following code with AsyncTask and thereby using LocationListener in doInBackground method.
Source Code:
public class GetLocation extends AsyncTask<String, String, String>
{
private myTest test;
boolean running =true;
private Context cont;
String addressString;
public GetLocation(myTest fr, Context contxt)
{
test = fr;
cont = contxt;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result)
{
test.GetContent();
}
#Override
protected String doInBackground(String... params) {
Looper.myLooper().prepare();
LocationManager locationManager;
locationManager = (LocationManager) cont
.getSystemService(Context.LOCATION_SERVICE);
Criteria crta = new Criteria();
crta.setAccuracy(Criteria.ACCURACY_FINE);
crta.setAltitudeRequired(false);
crta.setBearingRequired(false);
crta.setCostAllowed(true);
crta.setPowerRequirement(Criteria.POWER_LOW);
String provider = locationManager.getBestProvider(crta, true);
Location location = locationManager.getLastKnownLocation(provider);
updateWithNewLocation(location);
LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
updateWithNewLocation(null);
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
};
locationManager.requestLocationUpdates(provider, 0, 0,
locationListener);
Looper.loop();
return addressString;
}
private void updateWithNewLocation(Location location) {
Constants.lat = Double.toString(location.getLatitude());
Constants.long = Double.toString(location.getLongitude());
}
}
Problem:
However, I also know that Looper’s can help to keep the thread active. I want to be able to get valid coordinates and this should loop until its received. How do i call to get the locations over and over again until valid one's are received? (I could put conditions within the loops i have provided but im not aware as to how and what methods i should call to achieve this). Please provide a code snippet if possible.
Cheers!
You have implemented this wrong. There is no need to create the AsyncTask. The LocationManager will asynchronously fetch locations for you and deliver them on your LocationListener.onLocationChanged. Once you get a proper Location you can call LocationManager.removeUpdates() and this will stop for further delivery of Locations.
Do not use AsyncTask for this. You just registered the LocationManager that is listen by LocationListener and use progressbar for that. Once call LocationListner.onLocationChanged try to get Lat and Long and dismiss the progress bar. OnLocationChanged will be call at you move your device for a short distance.
I am using the routine requestSingleUpdate() reoutine of the android LocationManager library with a LocationListener. The functionality I am trying to implement is that the user can press a button and the app will get their current location and perform reverse geocoding to get the approximate address.
My problem is that depending on the network situation of the device, getting a location fix may take a long time. How can I implement a timeout that will cause my 'requestSingleUpdate()' to give up and tell the user to find out their own bloody address?
my code:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
locationManager.requestSingleUpdate(criteria, new LocationListener(){
#Override
public void onLocationChanged(Location location) {
// reverse geo-code location
}
#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
}
}, null);
LocationManager doesn't seem to have a timeout mechanism. But LocationManager does have a method named removeUpdates(LocationListener listener) which you can use to cancel any callbacks on the specified LocationListener.
So, you could implement your own timeout with something like the following pseudo-code:
final LocationManager locationManager
= (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// ...
final LocationListener myListener = new LocationListener() {
//... your LocationListener's methods, as above
}
Looper myLooper = Looper.myLooper();
locationManager.requestSingleUpdate(criteria, myListener, myLooper);
final Handler myHandler = new Handler(myLooper);
myHandler.postDelayed(new Runnable() {
public void run() {
locationManager.removeUpdates(myListener);
}
}, MY_TIMEOUT_IN_MS);
I'm not certain what happens if you call locationManager.removeUpdates(myListener) after you get the Location. You might want to check for that before you call removeUpdates. Or, you could add something like this to the onLocationChanged method in your callback (and possibly to the other methods as well) :
myHandler.removeCallbacks(myRunnable); // where myRunnable == the above Runnable