Android requestLocationUpdates when phone idle - android

I'd like to track my Location every minute. For that I use a locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000, 0, pll);
Here is the log when my phone is idle.
Date Latitude Longitude Accuracy
07:45:35 51.362402459999996 - 6.2174867399999995 (75.0)
07:46:35 51.362402459999996 - 6.2174867399999995 (75.0)
07:47:35 51.362402459999996 - 6.2174867399999995 (75.0)
...
07:50:35 51.362402459999996 - 6.2174867399999995 (75.0) # I'm further than 75m away from my home at that time
I've indeed a new location every minute but it is exactly the same. Just the time is updated. The position is not updated (maybe normal when I don't move enough) but I find it strange that the coordinates are exactly the same. Also as I don't have wireless activated, it should locate me accordingly to the CellId (with an accuracy of ~1000m), here I still have an accuracy of 75.0. It seems, it is the last location recorded using wireless networks.
Any idea how can I record the real last location (even with low accuracy) ?
public void onLocationChanged(Location location) {
System.out.println(new Date(location.getTime())+" "
+location.getLatitude()+" - "+location.getLongitude()+" ("+location.getAccuracy()+")");
callback.addEntry(location);
}

Hey use GPS_PROVIDER instead of NETWORK_PROVIDER as per below code
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, pll);
NETWORK_PROVIDER will give you only fix tower location and gps will give you exact changing location

You have got nearest GSM tower coordinates.

It seems there is no way to force to compute the position using the LocationManager with the celltower only when there is no wireless connexion.
Maybe another way would be to use the method mentioned in the thread Poor Man GPS : manually compute the position knowing the CellId.
Pseudo code :
onLocationChanged(new_location)
if isConnected()
record(new_location)
else
cell_location = poorManGPS()
record(cell_location)
end
The problem is of course that I cannot query the cell-id database with no internet connection. I see several solutions :
Store the current (and previous) cell id when I have internet and hope I'll stay in this one when I won't have internet
Use the cell id database on the phone (but I think root privileges needed)
Store the cell id for further localization

Related

Android track app cause overheat to device

I have developed an android application which took the current location using GPS every 10 seconds, and send it to the server using socket. To achieve this I used postDelayed method to keep getting current location and send it to server.
myRunnable = new Runnable() {
#Override
public void run() {
Location mCurrentLocation =getCurrentLocation();
if(mCurrentLocation != null)
sendCurrentLocationToServer(mCurrentLocation);
Handler.postDelayed(this, 10000);
}};
public Location getCurrentLocation(){
Location currentLocation = myLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
return currentLocation;
}
but this code makes the device to overheat, and consumes the battery quickly, is there another way to achieve the same result and reduce the overheat?
Thanks
First off, don't use getLastKnownLocation. Not only will it normally return null, looping calling it is an EXTREMELY inefficient way of doing things. Instead, requestLocationUpdates, and it will call you when it has a new location.
Second, don't send the location to the server every 10 seconds. Sending it that frequently causes your phone to keep the radio (either wifi or cellular) on constantly, which is causing your heat issue. Sending data generates heat. Reduce it to once every minute or so, and send up heading and speed data with the location. If you need a more exact location the server can use speed and heading to programmatically calculate a probable location- if needed. Most likely you don't even really need that.

Location accuracy remains low using GPS

I have the following code in main activity:
LocationManager mlocMan = (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);
if (mlocMan.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
LocationListener mlocListener = new LocationManagerHelper(...);
mlocMan.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,mlocListener);
}
In the location listener I have this: (theAccuracy was initialized to -1)
if (theAccuracy == -1 || theAccuracy > loc.getAccuracy()) {
theAccuracy = Math.round(loc.getAccuracy());
latitude = loc.getLatitude();
longitude = loc.getLongitude();
}
updateTimes++;
if (updateTimes == 3) {
mLocMan.removeUpdates(this);
updateTimes = 0;
//get address for location
theAccuracy = -1;
}
Meaning, after 3 location updates from the GPS, take the best accurate location and get its address. On the emulator I get fixed accuracy of 20m (I send long/lat using DDMS) but that's not real life so I tried with my device and while the very first time (3 requests) gave me the exact address (on the spot) with 40m accuracy, the next ones were sometimes more accurate but the address was nearby. The best accuracy I got was 29m (happened once) most of the times it's above 30. Is this a problem of my GPS (LG G3) or is there any other idea that can make things more accurate after 3-4-5 requests?
A few reasons:
Your emulator doesn't have actual gps hardware, so it's probably using your ip address, so that's why it seems fixed.
GPS hardware on your phone has to warm up a bit. Set the frequency of polling up for a bit (1 update a second, or half-second), and let it run for a few seconds, before taking measurements that count.
The location manager supports both hardware and network lookups (wifi / celltowers). Not sure how to set provider to just your phone's hardware, but if you use the googlePlayServices gps client (LocationClient), it's quite simple:
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationClient.requestLocationUpdates(mLocationRequest, (LocationListener) this);
You're probably testing at your computer in doors. Buildings definitely effect gps accuracy.

Better way to query GPS regularly

I have a timer that runs every second. Every second I get the GPS location and do other stuffs.
I am wondering which way is better:
1- Request a single location update and then get the last known location
private void timeout(){
String data[] =new String[DATA_LENGTH];
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, this, null);
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
.
.
.
}
2- Start Location listener and then just get the last known location whenever my timer expire
OnCreate(){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
}
private void timeout(){
String data[] =new String[DATA_LENGTH];
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
.
.
.
}
Thank you
PS: Note that battery is not a concern to me as per the requirement of the product
requestSingleUpdate is meant to be single, if you need to query the GPS frequently you should definitely go with option 2.
Keep a global Location object in memory, use it in you other stuff and update it whenever your listener gets an update from the LocationManager.
You can listen for changes via requestLocationUpdates - the code below is a quick-n-dirty example (untested). Remember, you have to have location services turned on to use this.
LocationListener locGPSListener= new LocationListener() {...}
LocationListener locNetworkListener= new LocationListener() {...}
mgr = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// listens using GPS for location
mgr .requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locGPSListener);
// uses towers for location
mgr .requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locNetworkListener);
...
What approach is better, depends on
Androids GPS behaviour and
your Application.
ad 1. if explicitly getting a location delivers a more recent fix, than this is an advantage, because:
ad 2. if your application don't want the android filtering behaviour, and you can filter it yourself better, then this would be better for your app.
Example: (is for ios, but may apply here too:) if I drive with my car to a traffic signal, and do a harsh breaking, then ios still shows 5 km/h speed, although I am standing still. This I call unwanted filtering.
This has all nothing to do with battery: if you get the location via message or if you query it is the same from battery point of view. It smore a software design issue: (events vs. polling)
A difference would only be if GPS is disabled, but disabling GPS makes only sense if it can be disabled for long time.

Android LocationClient.getLastLocation() returns old and inaccurate location with a new timestamp

I've been using the fused location provider since its release and I am pretty happy with it (way better than the old system). But I ran into a peculiar problem when using geofencing in combination with LocationClient.lastKnownLocation(). The setup is as follows:
I drop several geofences around some home location (with increasing ranges). When I get the intent that a fence is crossed I retrieve the last known location from LocationClient and work with it. Apart from than I also registered for regular location updates with update mode PRIORITY_BALANCED_POWER_ACCURACY.
Most of the times this works perfectly fine, but sometimes this happens:
Time 000 s - (Lat,Lon,Accuracy) = (48.127316,11.5855167,683.0)
Time 120 s - (Lat,Lon,Accuracy) = (48.1260497,11.5731745,31.823)
Time 300 s - (Lat,Lon,Accuracy) = (48.1217455,11.5641666,143.81)
Time 420 s - (Lat,Lon,Accuracy) = (48.1189942,11.559061,36.0)
Time 600s - (Lat,Lon,Accuracy) = (48.127316,11.5855167,683.0)
Notice that all these locations are retrieved by getLastKnownLocation(). What seems fishy here is that the first and the last location are identical (even in the other attributes), to be more specific:
* intent at time 0: *
component: ComponentInfo{package.Class}
key [location]: Location[mProvider=fused,mTime=1373524391934,mLatitude=48.127316,mLongitude=11.5855167,mHasAltitude=false,mAltitude=0.0,mHasSpeed=false,mSpeed=0.0,mHasBearing=false,mBearing=0.0,mHasAccuracy=true,mAccuracy=683.0,mExtras=Bundle[mParcelledData.dataSize=352]]
* intent at time 600: *
component: ComponentInfo{package.Class}
key [location]: Location[mProvider=fused,mTime=1373524994871,mLatitude=48.127316,mLongitude=11.5855167,mHasAltitude=false,mAltitude=0.0,mHasSpeed=false,mSpeed=0.0,mHasBearing=false,mBearing=0.0,mHasAccuracy=true,mAccuracy=683.0,mExtras=Bundle[mParcelledData.dataSize=352]]
* note the ~600 s difference in the timestamp *
I do not understand how this can happen, as there have been locations in between that were both more recent and more accurate. Also the new timestamp on an old location makes me curious... apparently similar things happened when using the old API, but this new location provider is just called fused, so I can not distinguish GPS from WPS from sensors... If it is the cell tower switching problem (outlined in the linked question concerning the old API) then why would the phone connect to a "far away" tower if it has seen closer towers?
Why is this happening?
The first and last points were gotten using cell triangulation. The error/accuracy is typical of cell-based location, and it looks like the Google power saving logic decided that switching to cell would be OK, even as you say its recent history included points much closer.
Aw, SHUCKS! I got this too today... And I moved to the new Google Play Services location precisely to AVOID this... And I was so thrilled up until just now when I got it too. You may or may not know that the old one had these kind of problems, and it was a pain.
There are lots of threads regarding this, including one of my own :(
Why is locationmanager returning old location fixes with new gettime-timestamp?
I guess the only thing to do is avoid using cached location...
Instead of polling, one can work around one or more sources of inaccuracy using this subscription mechanism.
LocationListener locListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (location == null)
return;
// process these:
// location.getLatitude();
// location.getLongitude();
// location.getAccuracy();
...
}
...
}
((LocationManager) getSystemService(Context.LOCATION_SERVICE)
.requestLocationUpdates(LocationManager.GPS_PROVIDER,
minTimeMilliSec,
minDistanceMeters,
locListener));

onlocationChanged is called even if I am sitting at the same place

I have used the code below and everything is working fine except that onLocationChanged is called even if I am sitting at the same location .
I thought it should be called only when I am moving right ?
I only want to get the location after I have moved a certain distance.
Please help me out.
Thanks in advance.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
locationMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
this);
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(this, "Working!", Toast.LENGTH_SHORT).show();
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
String Text = "Latitud = " + lat + "\nLongitud = " +
lng;
Toast.makeText(getBaseContext(),Text,Toast.LENGTH_SHORT).show();
}
}
You're requesting location updates at the shortest possible intervals/distances
locationMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
this);
This is what the documentation says about those parameters
" The location update interval can be controlled using the minTime parameter. The elapsed time between location updates will never be less than minTime, although it can be more depending on the Location Provider implementation and the update interval requested by other applications. "
The minDistance parameter can also be used to control the frequency of location updates. If it is greater than 0 then the location provider will only send your application an update when the location has changed by at least minDistance meters, AND at least minTime milliseconds have passed. However it is more difficult for location providers to save power using the minDistance parameter, so minTime should be the primary tool to conserving battery life.
I personally use a minTime of 10 seconds and 10 meters for my app
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000,
10, locationListener);
Network location is not as precise as you would think it is. Therefore the result returned by the sensors can fluctuate. This is even more true when you consider that GPS signal weakens if you don't have direct line of sight with the satellites, and the number of visible satellites also has effect on the precision. This gets even worse when you start using the network provider, where the position is calculated by triangulation of the signal strength of cell towers, and the number and SSIDs of visible wireless network. Since these can fluctuate quite a lot, the precision suffers greatly. There are bunch of averaging algorithms, and heuristics employed to minimize such fluctuations, but ultimately nothing can stabilize it to be as good as you expect it to be.
A simple averaging and variation filtering can help you. Adding a correction based on the device accelerometer can also help a lot, but it will make your code more complex.

Categories

Resources