finding current location in android through GPS - android

Is there possible to get accurate latitude and longitude of a user through "GPS" after changing its location of very shorter distance like 3-4 feet.
Actually I have made an application in android which gives me latitude and longitude of a user but, it changes its value on a same point or location of a user.
Kindly help me out of this problem.
thanks in advance.

My Experience says It depends on Phone/Device you are using, if your device support AGPS then getting GPS coordinates will be easier and fast (No related to your coding skill as you will be using android SDK). Normal GPS also return accurate data, try downloading Savaari application from google play, It works like charm, your 2nd Question Yes it is possible to get coordinates after a specific time or distance interval, when ever you are registering your listner you have to provide time and distance (in Meters) after which you want to receive GPS Value.
Check out this snippet : -
public void startReadingGPS(int readAfterMinimumTime, int readAfterMinimumDistance ){
locationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, readAfterMinimumTime, readAfterMinimumDistance, this);
}
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
Added in API level 1
Register for location updates using the named provider, and a pending intent.
See requestLocationUpdates(long, float, Criteria, PendingIntent) for more detail on how to use this method.
Parameters
provider the name of the provider with which to register
minTime minimum time interval between location updates, in milliseconds
minDistance minimum distance between location updates, in meters
listener a LocationListener whose onLocationChanged(Location) method will be called for each location update

you should implement locationlistener in your activity
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
boolean isGPSEnabled = false;
LocationManager locationManager = (LocationManager) yourapplicationcontext
.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
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) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
//Add this permission
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />

Related

How to enforce my geo location is real GPS, not just my network endpoint's passive location?

We have in-house tablets, that we control, and we have the requirement that their recorded location be as accurate as possible. I do everything I should to turn on real GNSS GPS, but getLastKnownLocation("gps") always returns null.
We use a Samsung Galaxy Tab A7, SM-T500, whose specifications swear it has a real GPS GNSS radio receiver. Google Maps identifies my secret lair correctly.
Our AndroidManifest.xml requests GPS permissions:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<activity
android:name=".MainActivity"
android:foregroundServiceType="location"
...
>
In the tablet's Settings, our app has Location permission "Only while app is in use," which is fine because our app dominates our tablet and is interactive. Our tablet is not used in a vehicle, so the location only needs to be accurate within the last 10 minutes or so.
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) returns true, as does that call with PASSIVE_PROVIDER and NETWORK_PROVIDER. The "fused" provider is not available.
Then we call this, to pull every kind of location and return the most accurate one:
private static Location getLastKnownLocation(#NonNull LocationManager locationManager) {
List<String> providers = locationManager.getProviders(true);
Location bestLocation = null;
for (String provider : providers) {
Location l = locationManager.getLastKnownLocation(provider);
if (l == null)
continue;
if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy())
bestLocation = l; // Found best last known location: %s", l);
}
return bestLocation;
}
All we get is "passive." Do GPS locations specifically require a round-trip thru locationManager.requestLocationUpdates(), or is getLastKnownLocation() good enough?
Similar answers are elsewhere but this thread deserves closure. It seems getLastKnownLocation() does not work with GPS and GNSS satellites, so as Phantom Lord prompted the correct fix is to enable my main activity for GPS:
public class MainActivity extends AppCompatActivity implements LocationListener {
Then in onCreate() turn on a listener:
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return; // TODO spank user
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10, this);
}
Then catch the updates:
private Location gpsLocation = null;
#Override
public void onLocationChanged(Location location) {
gpsLocation = location;
}
Now a new question: Why is the passive location accuracy ~5 meters while the GPS location accuracy is ~14 meters? This is a naive tablet, so it certainly doesn't know my home address and such. According to my internet spam, my IP address is in a nearby city...

Fused Location Provider unexpected behavior

this is how I register my app to receive location updates:
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(Consts.ONE_MINUTE * 10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setFastestInterval(Consts.ONE_MINUTE);
Builder builder = new GoogleApiClient.Builder(context);
builder.addApi(ActivityRecognition.API);
mGoogleApiClient = builder.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
....
....
#Override
public void onConnected(Bundle connectionHint) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationUpdatespendingInent);
}
my pending intent been invoked in background almost in the exact requested intervals...
so far so good.
the problem: When WIFI is disabled/ not connected to any network, or when there is no 3G/4G network data enabled - the fused location provider not providing new location updates!!
my Location access settings are turned on, and GPS satellites and WI-FI & mobile network location is checked.
the even bigger problem: sometimes in that case, I do receive location updates callbacks via the pending intent, but with the last location it knew (even if it was an hour ago, and I'm long long gone away miles from that place)
according to the documentation of PRIORITY_BALANCED_POWER_ACCURACY :
Used with setPriority(int) to request "block" level accuracy.
Block level accuracy is considered to be about 100 meter accuracy. Using a coarse accuracy such as this often consumes less power.
I'm expecting that the fused location provider will open the GPS when it have no other choice, or at least won't provide a new location updates if he don't have any.
another unpredictable and disturbing issue:
I changed PRIORITY_BALANCED_POWER_ACCURACY to PRIORITY_HIGH_ACCURACY in order to see how it behaves (for 24 hours). all the intervals stayed the same (10 minutes interval between updates). accurate location indeed received even in phones with no network/sim card, but - the battery drained out fast! when I looked on the battery history, I was surprised to see that GPS radio was on full transmission mode all the time!!!! and I saw also in my log that loction was received every minute, even that I requested location each ten minutes (I don't have any other installed apps that opens GPS to receive locations..)
I noticed this behavior on several devices (such as Moto X 2013, HTC One X, Nexus 5) , all with latest Google Play Services (version 6.1.11) , and android KITKAT 4.4.4
my application depends a lot on the user current location, and periodically receives location updates in the specified interval as long as the user logged in, so I don't want to use the PRIORITY_HIGH_ACCURACY mode, to prevent battery drain..
my questions:
is the fused location provider suppose to use GPS at all if it set to receive updates with PRIORITY_BALANCED_POWER_ACCURACY and don't have any WI-FI or cell towers info ?
if it does, then what am I doing wrong?
why I'm getting this misleading location updates that are not correct? (as I explained in the the "even bigger problem" section..
why GPS radio is opened all the time instead of been opened for the 10 minutes interval when I used the PRIORITY_HIGH_ACCURACY parameter? (I don't have other installed apps that triggers location updates faster..)
For the questions specified,
1. is the fused location provider suppose to use GPS at all if it set to receive updates with PRIORITY_BALANCED_POWER_ACCURACY and don't have any WI-FI or cell towers info ? &
2. if it does, then what am I doing wrong?
Apparently no explicitly unique source is specified anywhere within documentation. With either PRIORITY options, even through code, the "source" of obtained location is "fused".
[location.getProvider() returns :"fused"]
I have seen GPS being used only when the LocationRequest has PRIORITY_HIGH_ACCURACY. So it does not use GPS under other conditions.
4. why GPS radio is opened all the time instead of been opened for the 10 minutes interval when I used the PRIORITY_HIGH_ACCURACY parameter? (I don't have other installed apps that triggers location updates faster..)
The fastest interval has been set for 1 minute. From what i understood, the setFastestInterval is given precedence over setInterval when the value for fastest interval is shorter in duration than the value of setInterval.
In your case, 1 minute against 10.
About not having other installed apps that triggers location updates, its just given as an example and not specified that only that case explicitly.
This controls the fastest rate at which your application will receive
location updates, which might be faster than setInterval(long) in some
situations (for example, if other applications are triggering location
updates).
So, what happens is with PRIORITY_HIGH_ACCURACY, it requests location on the fastest interval set - 1min, by using GPS(kind of exclusively).
3. why I'm getting this misleading location updates that are not correct? (as I explained in the the "even bigger problem" section..
Need to check the code for pendingIntent mechanism also. Though there could be a few things to take note of:
You can add a location.getTime() to ensure and verify the time of obtained location. Very likely it is not being updated, if there is no wifi-cell towers in range and PRIORITY_BALANCED_POWER_ACCURACY is used.
A block level accuracy of location on the first place, which is being used when "lastKnown" is called wouldn't help.
The battery consumption was because of the combination of GPS and 1 min updates. Try setting the fastest interval as 5 or 10 mins, if that is suitable for your implementation but PRIORITY_BALANCED_POWER may not help if you need absolutely accurate location. I normally add a check for the location obtained in onLocationChanged and depending on that, switch the priority in LocationRequest. It helps in, surely, obtaining a location generally, unless i am inside a building with no line-of-sight for GPS and Wifi-Network are off.
I would suggest you to use AlarmManager and FusedLocationProvider together in such a way that your AlarmManager fire alarm on every 10minute with a view to start location updates.
Once you get updated location, disconnect the location client. You don't need to keep it running for all the time by setting interval time in LocationRequest, Instead you can invoke the process on each time interval by using AlarmManager.
In such kind of mechanism, you will have following benefits which will resolve your problems:
GPS radio will stay open only for few seconds while retrieving location because you are going to disconnect after getting first location update. Thus GPS radio will not stay open all the time so the battery will be saved.
You will be able to get new location on each 10minutes without messing around with old location or something.
I hope it will be helpful.
Cell towers cover a several mile area so they aren't the best for getting a location from. Look at the location accuracy when you are working with locations.
#Override
public void onLocationChanged(Location location) {
//it happens
if (location == null) {
return;
}
// all locations should have an accuracy
if (!location.hasAccuracy()) {
return;
}
// if its not accurate enough don't use it
// this value is in meters
if (location.getAccuracy() > 200) {
return;
}
}
You could put a broadcastreceiver on the network status and when there is no connection you could restart your location provider with priority_high_accuracy which will use the GPS only when the user has the GPS enabled otherwise it falls back on the wifi and cell towers.
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
/** Checks whether the device currently has a network connection */
private boolean isDeviceOnline() {
ConnectivityManager connMgr = (ConnectivityManager) activity
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
return true;
}
return false;
}
For updating of the GPS coordinates you can use GPS and WI-FI providers also. For updating of the position use as well minimum distance parameter. I will provide you with small GPS service example.
Answers :
1) PRIORITY_BALANCED_POWER_ACCURACY do not use GPS.
2) Use GPS and WI-FI to detect location.
3) PRIORITY_BALANCED_POWER_ACCURACY probably because of no WI-FI in area.
Code example :
public class GPSservice extends Service implements LocationListener {
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 2;
private static final long MIN_TIME_BW_UPDATES = 1000 * 1;
double latitude, longitude;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
protected LocationManager locationManager;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
getLocation();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onLocationChanged(Location location) {
new LocationReceiver(location, getApplicationContext());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
public Location getLocation() {
try {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
Log.d("Network", "NO network");
} else {
this.canGetLocation = true;
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) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
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) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
}

Location service works in emulator but not on real android device

I would like to get location of user, so I have this code:
LocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MINIMUM_TIME_BETWEEN_UPDATES,
MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("locationManager ", "locationManager ");
/*
* try to get last know location
*/
Location location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
public void onLocationChanged(Location location) {
this.location=location;
}
and than I send geot fix:
geo fix -122.41914 37.77919
it works fine in emulator, but when I try on on real device. it doesn't work, and I see the GPS icon blinking on device.
Notice: GPS is enabled on device.

wifi provider onLocationChanged is never called

I got a weird problem. I uses wifi to retrieve user location. I have tested on several phones; on some of them, I could never get a location update. it seemed that the method onLocationChanged is never called. My code is attached below.. Any suggestions appreciated!!!
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LocationManager locationManager;
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
String provider = locationManager.NETWORK_PROVIDER;
Location l = locationManager.getLastKnownLocation(provider);
updateWithNewLocation(l);
locationManager.requestLocationUpdates(provider, 0, 0,
locationListener);
}
private void updateWithNewLocation(Location location) {
TextView myLocationText;
myLocationText = (TextView)findViewById(R.id.myLocationText);
String latLongString = "No location found";
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
latLongString = "Lat:" + lat + "\nLong:" + lng;
}
myLocationText.setText("Your Current Position is:\n" +
latLongString);
}
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
Log.i("onLocationChanged", "onLocationChanged");
Toast.makeText(getApplicationContext(), "location changed",
Toast.LENGTH_SHORT).show();
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status,
Bundle extras) {}
};
Manifest
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
My guess is that the phones on which you don't get location updates from do not have proper data connection. Network Provider needs GSM/3G or WiFi data connection to retrieve a location fix from Google servers using phones's cell/wifi data. You can use the method below to check this.
public boolean isOnline() {
ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
Please check that your onProviderDisabled method is not being called immediately.
If you find it is being called as soon as your provider registers, it means that the phone you're on has location services disabled.
It's my suspicion now that Google Location Services were down in select areas. My app started working again with no changes to the code (the apk from the Play Store).
I too faced the same issue with NetworkProvider while testing in ICS(4.0) but working fine in older versions(2.2 and 2.3.3 i tested). Here is the solution i found and working fine in ICS as well. Please use the Criteria for getting the location updates as below:
LocationManager locationManager= (LocationManager) <YourAct>
.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE); //ACCURACY_COARSE or ACCURACY_FINE based on usage
String provider = locationManager.getBestProvider(criteria, true);
// Register the listener with the Location Manager to receive location
// updates
locationManager.requestLocationUpdates(provider, 0, 0, locationListener);
Replace the code as above. This will help u in getting the location updates.
I had the very same problem and in turns out that onLocationChanged is not called if there is getLastKnownLocation which is the same as "current". That means that you will not get new location because there is nothing new to report...
Solution is to use the last known location even it is very old (and continue to listen for updates if you need more precise/new location (if such occurres)).

Why does the LocationManager does not have a lastKnown location?

I want the location of user and that too just once after that user navigates on his own
locationManager = (LocationManager)this.getSystemService(LOCATION_SERVICE);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
System.out.println(location.toString());
lat=location.getLatitude();
lng=location.getLongitude();
}
p = new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));
However i am not able to get the location of the user is it because of slow internet connection from the mobile ??
The getLastKnownLocation method will only return a location if the gps LocationProvider has stored a location somewhere. If the user has not yet used the gps on his device long enough to obtain a valid GPS fix the method will return null.
Even if you retrieve a location check the time of the location, there is no guarantee that the location isn't very very old.
It's not enough to just get a locationManager and call getLastKnownLocation()
because until there is an update there will be no "last known location"
You are missing that request provided by the LocationManager class:
public void requestLocationUpdates(java.lang.String provider,
long minTime,
float minDistance,
android.location.LocationListener listener)
If your activity implements LocationListener as mine did, you can pass in "this" as the LocationListener for a call originating in a method of that class. Otherwise, there are several other overloads taking Activity or Looper classes instead.
locationManager.requestLocationUpdates(provider, minTime, minDistance, this);
In order to make sure the device is getting a location, request updates - but you also may
want to put guards for failure to find providers or getLastKnownLocation returning null.
locationManager.requestLocationUpdates(provider, 1, 0, this);
mostRecentLocation = locationManager.getLastKnownLocation(provider);
if(mostRecentLocation == null)
// lower your expectations, or send user message with Toast or something similar
Tell the user to turn on their location sharing or other provider services.

Categories

Resources