I am making location tracker application in android so I call a function
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
30000,
0,
listener);
So in this example i set 5minute interval.
Now my question is why GPS signal is constantly activate, though my interval time is 5minute..
Can't is deactivate till 5 minute and after 5 minute can't it automatically activate??
I thing device require more battery power though it constant active...
What I have to do to deactivate GPS for particular interval defined in function.
No you can't but you can always run a service that asks for a single shot fix every five minutes.
For e/g use requestSingleUpdate (String provider, PendingIntent intent)
To broadcast an intent when a single shot fix is obtained.
I had exactly the same problem with my app. I used a timer initialized on startup:
serviceHandler = new Handler();
serviceHandler.postDelayed( new RunTask(),1000L );
This runs locupdate and adds one to counter every second.
class RunTask implements Runnable {
public void run() {
++counter;
locupdate(0,0);
serviceHandler.postDelayed( this, 1000L );
}
}
this is the locupdate function used above. Note, mlocManager is defined globaly as a LocationManager.
public void locupdate(int minTime, float minDistance) {
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
if (mlocListener != null && mlocManager != null) {
mlocManager.removeUpdates(mlocListener);
}
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
minTime, minDistance, mlocListener);
}
One last thing. At the end of the onLocationChanged method in LocationListener I remove updates after 5 locations fixes:
mlocManager.removeUpdates(mlocListener);
This is similar to requestSingleUpdate() but i find it more flexible. Hope this helps!
Basically this function takes time interval as follows,
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 0, listener);
the meaning over here is that give me GPS update if you found within the given time with no
other priority tasks.
so this is you method
public void requestLocationUpdates (long minTime, float minDistance, Criteria criteria, PendingIntent intent)
& these are the parameters, please read it carefully you can understand it
Parameters
minTime = the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.
minDistance = the minimum distance interval for notifications, in meters criteria contains parameters for the location manager to choose the appropriate provider and parameters to compute the location
intent = a {#link PendingIntent} to be sent for each location update
That is all about
Best Regards,
~Anup
Related
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;
}
}
I am currently writing an application that receives location data every minute (or other specified amount of time) and thes send it to server.
The problem that I have noticed is:
When I use my application connected to power source it works perfectly - sends updates with defined interval.
When I use it on battery it sends updates randomly.
For my application I use timer to specify interval of update. This timer runs in Background service. I request updates in timer and remove updates when I receive location.
Fragment of my code:
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
date = date.getInstance(); //used to set time of update.
if(!GPSupdating)
{
locationManager.requestLocationUpdates("gps", 0, 0, locationListenerGPS);
GPSupdating = true;
}
}
};
My location listener:
LocationListener locationListenerGPS = new LocationListener()
{
public void onLocationChanged(Location updatedLocation)
{
myGPSLocation = updatedLocation;
haveLocationGPS = true;
locationManager.removeUpdates(locationListenerGPS);
GPSupdating = false;
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
Do you have any idea why this is not working correctly?
It's not good solution - enable/disable listener on each minute.
Better to try following things:
1) Set minimal update time (in requestLocationUpdates ) to one minute and send data to server in update listener:
locationManager.requestLocationUpdates("gps", 60*1000, 0, locationListenerGPS);
If you need more accurate update intervals, than:
2) Start separate thread and enable GPS updates on it. Store last location in thread or service variable. Also start timer and on timer tick send location to the server.
Try using Criteria to manage the power. Set power requirement to POWER_LOW. You will loose some accuracy though.
LocationManager locationManager= (LocationManager) getSystemService(context);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_LOW);
provider = locationManager.getBestProvider(criteria, true);
You will not save energy by enabling and disabling GPS once per minute. Either choose a greater intervall (5 minute) or get the location evry second.
Then store the location in a lastValidLocation filed, start your own Timer, and once a minute read out lastValidLocation. and send to server if changed.
I have registered my LocationManager for location updates, every 10 seconds
mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, 50, this);
But the onLocationChanged callback returns a location every 10 secs, which(the location) is more than 2 hours old. And that time-stamp is never changing.
The problem is:
2 hours back I was in a complete different location(home) where I used the device on a wifi. Now currently I am in some other location(office) on a different wifi where my application shows my current location as home. Same thing happened at home yesterday, when it was showing office as my current location. It got to work(started showing correct location) when I closed my app, opened FourSquare app and re-opened my app.
Complete Code:
public class LocationService extends Service implements LocationListener {
public static double curLat = 0.0;
public static double curLng = 0.0;
private LocationManager mgr;
private String best;
private Location location;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
best = LocationManager.NETWORK_PROVIDER;
location = mgr.getLastKnownLocation(best);
if (location != null) {
dumpLocation(location);
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 1000, 50, this);
}
return START_NOT_STICKY;
}
}
private void dumpLocation(Location l) {
SimpleDateFormat s = new SimpleDateFormat("dd/MM/yyyy:hh:mm:ss",
Locale.ENGLISH);
String format = s.format(l.getTime());
//The above time is always 28/03/2013:09:26:41 which is more than 2 hrs old
curLat = l.getLatitude();
curLng = l.getLongitude();
}
#Override
public void onLocationChanged(Location location) {
dumpLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
Being started in an Activity this way:
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, LocationService.class);
pi = PendingIntent.getService(this, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), 10000, pi);
Permissions in 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.INTERNET" />
I can get the correct location now, by opening some other location based app like Maps, Navigator, Foursquare etc.., But why my app isn't able to get a new/fresh fix from the provider.
Thank You
You are getting old location because of this line
location = mgr.getLastKnownLocation(best);
because if GPS is not enabled then it will show you the old location . So remove this code It will work like a champ
You can also refer to this library
https://github.com/nagendraksrivastava/Android-Location-Tracking-Library
On the basis of your comments I have edited the answer Okay Let me explain line by line
location = mgr.getLastKnownLocation(best); it will give you object of last know location then it will go inside if condition and it will call dumplocation and will get last location data and after that you called
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 1000, 50, this);
but suppose GPS provider is disabled then it will not fetch new location so you will get old location only . So either you can change it like
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,new NagendraSingleLocationListener(),null);
}
else
{
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,new NagendraSingleLocationListener(),null);
}
I think because you cancel your pending intent right away, thus the requestLocationUpdate would not start update before you cancel. Why don't you sleep may be for 2 second before cancel.
From my experience android will give you a location when you request the updates even if gps has not enough sattelites to work. So even if gps is on - if you are inside or in a location that is bad (like under a bridge) android will deliver an old fix to you. Can be a very old one indeed.
The only thing I found to be working 100% is to generelly not use the first position but only remember the time. When new positions arrive you can check that the time is newer than the last. If you want to only use very precise positions you may also need to check that location.getAccuracy() is low (the lower the better).
I use gps to get my timestamps for a soap interface as the android clock can be very off sometimes and this was the only way for me to get a valid time from gps.
I am using Network Location provider.
I need to call onLocationChanged method from my LocationListener only once per 1 hour.
Here is my code:
MyLocationListener locationListener = new MyLocationListener();
locationMangaer.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3600000, 0,locationListener);
But it doesn't work. My onLocationChanged calling very often.
What parameters must I use?
From the LocationManager#requestLocationUpdates() documentation:
Prior to Jellybean, the minTime parameter was only a hint, and some location provider implementations ignored it. From Jellybean and onwards it is mandatory for Android compatible devices to observe both the minTime and minDistance parameters.
However you can use requestSingleUpdate() with a Looper and Handler to run the updates once an hour.
Addition
To start you can read more about Loopers and Handlers here.
You are using API 8 which is a good choice, but this limits which LocationManager methods we can call since most were introduced in API 9. API 8 only have these three methods:
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener, Looper looper)
requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent)
Let's use the first method, it is the simplest.
First, create your LocationManager and LocationListener as you normally would, but in onLocationChanged() stop requesting more updates:
#Override
public void onLocationChanged(Location location) {
mLocationManager.removeUpdates(mLocationListener);
// Use this one location however you please
}
Second, create a couple new class variables:
private Handler mHandler = new Handler();
private Runnable onRequestLocation = new Runnable() {
#Override
public void run() {
// Ask for a location
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
// Run this again in an hour
mHandler.postDelayed(onRequestLocation, DateUtils.HOUR_IN_MILLIS);
}
};
Of course, you ought to disable all of your callbacks in onPause() and enable them again in onResume() to prevent the LocationManager from wasting resources by acquiring unused updates in the background.
A more technical point:
If you are concerned about blocking the UI thread with the LocationManager, then you can use the second requestLocationUpdates() method to supply a specific Looper from a new Thread (say a HandlerThread).
I am using the location manager's requestLocationUpdates() method to receive an intent to my broadcast receiver periodically. The system is correctly firing the intent to my receiver, and I have been able to use it correctly. The only problem is that the GPS location provider only stays active for a few seconds after the initial location acquisition, and I need it to stay on a little longer so that the location estimates are more accurate.
My question is how to make the GPS location provider stay active for each periodic request that comes from the LocationManager requestLocationUpdates. Does anyone know how to do this?
Try something like this. I think it is the right approach
private void createGpsListner()
{
gpsListener = new LocationListener(){
public void onLocationChanged(Location location)
{
curLocation = location;
// check if locations has accuracy data
if(curLocation.hasAccuracy())
{
// Accuracy is in rage of 20 meters, stop listening we have a fix
if(curLocation.getAccuracy() < 20)
{
stopGpsListner();
}
}
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
}
private void startGpsListener()
{
if(myLocationManager != null)
// hit location update in intervals of 5sec and after 10meters offset
myLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, gpsListener);
}
private void stopGpsListner()
{
if(myLocationManager != null)
myLocationManager.removeUpdates(gpsListener);
}
if you keep your LocationListener active, it should continue to receive updates to onLocationChanged() if the fix accuracy narrows. and indeed location.getAccuracy() will tell you the current accuracy
maybe set minTime and minDistance both to 0 to receive updates with greater frequency? will use more battery, but is more preise.
There is a example about get GPS location with timeout.
http://sikazi.blogspot.com/2010/09/android-gps-timeout.html#more
To get GPS location periodically, get the location from onLocationChanged method of locationListener and in onResume method specify the timing in milliseconds for getting periodic updates
onResume
location_manager.requestLocationUpdates(provider, 1000, 1, MainActivity.this);