Location update rate in Google Maps (Android) - android

I'm writing a simple GPS based app for location awareness. Whenever GPS is enabled, the app requests location updates and prints latitude and longitude in a TextView. If GPS is disabled, the location provider fall-backs to LocationManager.NETWORK_PROVIDER for triangulating device position relative to neighboring cell-towers. The aim is whenever device movement is detected, it should start populating the TextView with lat/long. When there is no movement, the process should stop. In order to do so, I've implemented the location update rate as:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, this);
The above line causes very frequent location updates (even when there is no movement, I keep getting lat/long values). I read somewhere that putting minTime=0 is not a good idea (battery drains faster). When I change it to 2 or 3 seconds, the update becomes very slow (even if the device moves more than 50 meters). Changing minDistance doesn't seem to work either! I want to know what settings does Google Maps application use? Power consumption is not a limiting factor for me as I'm developing the app for some network drive test equipment (which gets constant power from vehicle's on-board lead acid battery).

The frequency of updates is highly dependent on the hardware. Good gps chips send very frequent updates(Samsung Galaxy S3) while some struggle even to show lat-lan position. The gist here is normalize the the frequency for receiving updates on the basis of distance and time. Use various time and distance configuration and test them and use the most appropriate values. For my project I used following values:
//for walking user
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5, 10, this);
//for user in a car
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2, 50, this);

Related

How does Apple or Android calculate speed in devices?

There are any documentation for this? I've checked many formulas and algorithms but didn't find an explicit definition how they get the speed provided in Geolocation object.
The GPS chipset provides the current velocity to the system along with the current location.
The chipset may compute the velocity by comparing location over time and correcting for the curvature of the Earth at the current location, or from the Doppler shift of the received satellite signals.
Whichever method is used, the operating system doesn’t need to do any processing to get the speed. The velocity data is provided along with location and altitude data directly from the GPS chip (actually chips in many newer devices support both GPS and GLONASS, but which system is used is not visible to the user).
Physics.org has a simple explanation of how GPS works
Wherever you are on the planet, at least four GPS satellites are ‘visible’ at any time. Each one transmits information about its position and the current time at regular intervals. These signals, travelling at the speed of light, are intercepted by your GPS receiver, which calculates how far away each satellite is based on how long it took for the messages to arrive.
Once it has information on how far away at least three satellites are, your GPS receiver can pinpoint your location using a process called trilateration.
But you can search for more detailed explanations of the mathematics and physics involved.
It basically scans your location (i.e. your latitude and longitude) and compares with the last check. Using euclidian distance, it can get the distance in the period of time. With the time (for example, if it scans your location every 2 seconds), it can easily estimate your speed by doing Speed = Distance/2.

How does some apps(wechat) ignore fake location and then detect the real one?

I have installed a fake location app and set my location different. Then opened Google Maps and Wechat app,
Google Maps shows my location as what i set(fake)
Wechat app ignores fake location and detects real location (how?)
Then i wanted to prevent wechat analyze my previously received real locations and new fake location.
Uninstalled Wechat
Restarted my device
Set my location as fake
Installed Wechat again
But same result, it detects my real location.
I really want to understand how they do this. Any ideas?
What i have tried
Gps provider spoof
Network provider spoof
Fused location provider spoof
IP geolocation spoof
Gps provider spoof + IP geolocation spoof
UPDATE
Uses GPS even when disabled.
07-02 11:46:15.504 2346-2356/? D/LocationManagerService: request 434a7e28 gps Request[ACCURACY_FINE gps requested=+1s0ms fastest=+1s0ms] from com.tencent.mm(10173)
CONCLUSION
You can fake location on older versions of wechat(lower than 6.0)
Uses something like BaiduLocationSDK. It's not affected from any mock attempt through LocationManager and Fused provider.
I'm not sure but, seems like BaiduLocationSDK uses GPS through hardware level.
To check for fake location most applications look for GGA and GSV sentences in the NMEA (National Marine Electronics Association) data received by them. The fake location providers do not send NMEA sentences along with location, so this parameter can be used to If they haven't received and GGA and GSV sentences in a threshold amount of time, say 100 seconds they red flag the current location provider.
This process is repeated till a valid set of NMEA sentences has been received and then the corresponding location is selected.
To retreive NMEA data LocationManager#addNmeaListener(GpsStatus.NmeaListener listener) is called and then in the listener
void onNmeaReceived(long timestamp, String nmea) {
Log.d("Nmea Data",nmea);
}
for more info see adding a NmeaListener
the NMEA sentences, GGA and GSV look as follows
GGA - essential fix data which provide 3D location and accuracy data.
Sample : "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"
Where:
GGA Global Positioning System Fix Data
123519 Fix taken at 12:35:19 UTC
4807.038,N Latitude 48 deg 07.038' N
01131.000,E Longitude 11 deg 31.000' E
1 Fix quality: 0 = invalid
1 = GPS fix (SPS)
2 = DGPS fix
3 = PPS fix
4 = Real Time Kinematic
5 = Float RTK<br/>
6 = estimated (dead reckoning) (2.3 feature)
7 = Manual input mode>
8 = Simulation mode
08 Number of satellites being tracked
0.9 Horizontal dilution of position
545.4,M Altitude, Meters, above mean sea level
46.9,M Height of geoid (mean sea level) above WGS84 ellipsoid
(empty field) time in seconds since last DGPS update
(empty field) DGPS station ID number
*47 the checksum data, always begins with *
GSV - Satellites in View shows data about the satellites that the unit might be able to find based on its viewing mask and almanac data. It also shows current ability to track this data. Note that one GSV sentence only can provide data for up to 4 satellites and thus there may need to be 3 sentences for the full information. It is reasonable for the GSV sentence to contain more satellites than GGA might indicate since GSV may include satellites that are not used as part of the solution. It is not a requirement that the GSV sentences all appear in sequence. To avoid overloading the data bandwidth some receivers may place the various sentences in totally different samples since each sentence identifies which one it is.
Sample:"$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75"
Where:
GSV Satellites in view
2 Number of sentences for full data
1 sentence 1 of 2
08 Number of satellites in view
01 Satellite PRN number
40 Elevation, degrees
083 Azimuth, degrees
46 SNR - higher is better
for up to 4 satellites per sentence
*75 the checksum data, always begins with *
Source : NMEAData
Some 3rd party location sdk like BaiduLocationSDK doesn't reflect the fake location setup by system.
It's for safety purpose.
The reason I was asking the questions in the comments is that I was hoping you tested how Wechat responds to different conditions.
There are a couple of other ways to detect device location which TestProvider shouldn't affect AFAIK. This needs testing but here are some ideas:
LocationManager.getLastKnownLocation(String provider) - this allows you to force using for example a GPS provider and get cached data.
GPS NMEA listener, and a new one in API 24 - these APIs allow listening for low-level events from GPS hardware using NMEA 0183 protocol.
IP address geolocation.
You can get country-level geolocation via Telephony Manager.
Edit: added Telephony manager option.
#Bona Fide
Then you can remove the TestProvider from the LocationManager and get
the actual location.
Even wechat would use this approach before requesting location updates, to avoid providers being spoofed by other applications, like something below
// HERE WECHAT APP
// WECHAT REMOVES THEM IF ANY (just supposition)
locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER);
// WECHAT REQUESTING LOCATION UPDATES
// ....
So this approach causes throwing a IllegalArgumentException on the location faker app. Even in that case, i can easily handle this issue and continue spoofing GPS and NETWORK providers again,
// HERE LOCATION FAKER APP
// LOCATION FAKER APP SETS FAKE LOCATIONS
while (mRunning){
try {
locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, gpsLocation);
} catch (IllegalArgumentException e){
locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, false, false, false, false, true, true, 1, 1);
locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
}
try {
locationManager.setTestProviderLocation(LocationManager.NETWORK_PROVIDER, networkLocation);
} catch (IllegalArgumentException e){
locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, false, false, false, false, false, true, true, 1, 1);
locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true);
}
gpsLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
gpsLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
networkLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
networkLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
try {
Thread.sleep(500);
} catch (Exception e) {}
}
Everything works perfectly but out of WECHAT
Fake locations are possible if ALLOW_MOCK_LOCATION is set and a TestProvider is added to the LocationManager. To get the real location you need to do these two steps:
Detect if MockSettings are enabled and whether there are Apps installed how could fake the location.
Then you can remove the TestProvider from the LocationManager and get the actual location.
Checkout Jambaaz answer to get an example how this works in code.
Note: To remove an TestProvider you need the Permission android.permission.ACCESS_MOCK_LOCATION and ALLOW_MOCK_LOCATION is now deprecated since API 23. You can now check if the Location is from a TestProvider directly from Location.isFromMockProvider()
I have managed to spoof location with wechat and zalo, both seem just as difficult.
I would load a mock location and fake gps app. set my location. check maps and see it's correct, can even move around the world and it's working.
But wechat and zalo don't agree, they say I am in my basement lol.
THEN I uninstall fake gps app (might be able to force stop and disable) and go to wechat and clear location etc and try again and often it will move me to faked gps location. It won't stay that way after closing the wechat app though. it is temporary.
It might not be easy to do but might give someone a hint or path to look at.

Experience of Location Services on Android using GPS and Network providers

I have written a piece of code to get a feel of what my customer (cab driver) will experience when I enable location services on his device for my cab booking application. I enabled location services using both Network and GPS providers on the same listener.
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
// God.KM20TIME, God.KM20DISTANCE, (LocationListener) updates);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, God.KM20TIME,
God.KM20DISTANCE, (LocationListener) updates);
My battery ran out much faster than normal. I also had my phone heating up more than normal. But the consistency I was expecting was really low. I have decided to not use GPS, and only Network provider. I am building a cab booking app, so I need to know where the cab is approximately. Even if I know that the cab was at a approximate (300 meters) location about 15 mins back, I should be good. So I guess my decision to not over engineer this logic by using both providers is correct. I wonder if anyone can relate to a different experience here ? Am I missing something ?
From my experience, the quality of the Network provider can vary quite a bit.
The network provider uses a combination of WiFi and Cell tower information to provide location information.
If you happen to be close to a Wifi network, which is common in urbanized areas, but not outside of cities, you usually get a very good accuracy.
However, outside of range of a Wifi, you're at the mercy of the cell towers. Here, the precision depends on the quality and features of the cell tower, as well as the amount of cell towers that can be used to triangulate your position.
In these situations, the quality can vary alot, both between locations, but also depending on which Carrier you use, the distance between their cell towers, but also what make and generation of cell towers they have. Newer have more features regarding location, and might for example provide bearing on its own.
My application runs in Sweden, and in some areas of our country, a carrier might have only one tower within a very large area. In those cases, all lon/lat fixes end up directly on the tower, with a precision of even up to 20.000 - 30.000 meters.
Basically, my point is that when using the network provider, if you're not near a Wifi, i'd be very satisfied with 300 meters accuracy.
Regarding the battery / heat - with your requirements, you can play around a lot with the time / distance parameters to get a "good enough" update frequency that doesn't tax the phone as much.

Why couldn't I get GPS coordinates in a remote place?

I went on a trip somewhere remote and I didn't have mobile access but I thought that my GPS would work anyway since a GPS transmitter just relies on satellites. I have the following code to get GPS location:
mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
I tried to record my GPS coordinates and they ended up empty.
Is there something that I am not doing correctly or that I don't understand?
What can I change so that my phone can record raw GPS data with or without network access?
A GPS receiver needs to have several GPS satellites above the horizon, in order to receive the signals it uses to calculate its longitude and latitude. Each satellite broacasts this ephemeris information as part of its data stream, but a standalone receiver might take several minutes to scan through the available satellite frequencies from a "cold start" (where cached ephemeris information is out of date or incorrect for the current location).
GPS receivers on cell phones often implement "carrier assisted GPS", where the cellular network pushes the up-to-date GPS satellite ephemerides out to the handsets from time to time, so the phone already knows which satellites are in view at any given time/location without having to do a search.
If you don't have cellular network access, your phone might be programmed to fall back to a satellite-by-satellite search for usable signals, and might take longer to get its first GPS fix (if it can get one at all without carrier assistance).

Android GPS accuracy

I'd like to use fine gps position in my app. So I followed a simple tutorial (basic usage of LocationManager, explicitly reguested GPS provider, ask for updates 0 ms, 0 m ) and create an app. I was totally not impressed with accuracy and speed of updates. It was slow and best accuracy was 24 meters, but on average 96.
On the same phone, from the same location I run widely known GPS STATUS. And I was amazed to see how accurate the fix was. 4-6 meters, consistently.
So I switched off GPS Status and run my app - I see accuracy 6 meters, but seconds later it is 24, 56, 90, 128.... And fluctuate around 96.
Now, I wonder: how this is possible? Are there tricks to boost accuracy?!!
Does anybody have good examples/tutorials?
it does not help
Let me repeat: I get and print ALL updates. So I see a stream of locations with accuracy.
I see fluctuations, I see best results, and it is never better then 12 meters.
Now in the same spot, I start GPS Status => and I see how accuracy goes to 4 meters!
First I thought: ha, GPS STatus cheats, just devides the accuracy
But it seems to be not the case, because when I switched my app on and get lastknown positon it is indeed the one with accuracy 4!
And start to degrade to the best case 12.
Summary: same hw, same conditions, different apps => different accuracy!
So my question: are there any tricks? Any extra commands? Any special power settings? Any relations to "how heavy you app"?
related to: Android GPS. Location Listener does not want to acquire a fix :(
The best accuracy you can get with GnssMeasurement, but is hard to code. Android 7+ I have Doodgee shoot dual(very not popular china smartphone) and work's. https://developer.android.com/reference/android/location/GnssMeasurement
https://developer.android.com/guide/topics/sensors/gnss (official support list).
GNNS(GPS/GLONASS/GALILEO/...)
LocationManager,( 0 ms, 0 m ) - don't work, after some times(1-20s) you will get this same coordination(if you will stay in one place)- accuracy is 3-10m. With LocationManager you dont get the "raw" GNNS data from physical modul, but calculated by Android API. With GnssMeasurement you can got it.
google has released a nice API on their recent Google IO 2013 event:
https://developers.google.com/events/io/sessions/324498944
you should check it out and see how you can minimize your code.
do note that it requires that the device would have the play store app for this to work.
this method has many advantages over using the normal location sensors (battery, speed , accuracy,...)
How about this?
-set accuracy + set power requirement high:
try{
locator = new GeoLocator(this);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.addGpsStatusListener(new GPSStatusManager(locationManager));
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria. POWER_HIGH);
bestProvider = locationManager.getBestProvider(criteria, true);
Bundle bundle = new Bundle();
//I copied the next two lines out of some tutorial hoping that they would help boost my gps, but I'm really not sure what they do
boolean xtraInjection=locationManager.sendExtraCommand(LocationManager.GPS_PROVIDER,
"force_xtra_injection",bundle);
boolean timeInjection=locationManager.sendExtraCommand(LocationManager.GPS_PROVIDER,
"force_time_injection",bundle);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0.0f, locator);
}catch(Exception e){}

Categories

Resources